1 20 21 package org.snmp4j.mp; 22 23 import java.io.*; 24 import java.net.*; 25 import java.nio.ByteBuffer ; 26 import java.util.*; 27 28 import org.snmp4j.*; 29 import org.snmp4j.asn1.*; 30 import org.snmp4j.event.*; 31 import org.snmp4j.log.*; 32 import org.snmp4j.security.*; 33 import org.snmp4j.smi.*; 34 35 41 public class MPv3 42 implements MessageProcessingModel { 43 44 public static final int ID = MessageProcessingModel.MPv3; 45 public static final int MPv3_REPORTABLE_FLAG = 4; 46 public static final int MAX_MESSAGE_ID = 2147483647; 47 48 public static final int MAXLEN_ENGINE_ID = 32; 49 public static final int MINLEN_ENGINE_ID = 5; 50 51 private static final int MAX_HEADER_PAYLOAD_LENGTH = 52 new OctetString("\0").getBERLength() + 54 3 * new Integer32(Integer.MAX_VALUE).getBERLength(); 56 57 private static final int MAX_HEADER_LENGTH = 58 MAX_HEADER_PAYLOAD_LENGTH + 59 BER.getBERLengthOfLength(MAX_HEADER_PAYLOAD_LENGTH) + 1; 60 61 private SecurityProtocols securityProtocols; 62 63 private static final LogAdapter logger = LogFactory.getLogger(MPv3.class); 64 private SecurityModels securityModels; 65 66 private Cache cache; 67 private Hashtable engineIDs; 68 private byte[] localEngineID; 69 70 private int currentMsgID = new Random().nextInt(MAX_MESSAGE_ID); 71 72 private static int enterpriseID = 4976; 74 75 private CounterSupport counterSupport; 76 77 transient Vector snmpEngineListeners; 78 79 80 83 public MPv3() { 84 engineIDs = new Hashtable(); 85 cache = new Cache(); 86 securityProtocols = SecurityProtocols.getInstance(); 87 securityModels = SecurityModels.getInstance(); 88 localEngineID = createLocalEngineID(); 89 counterSupport = CounterSupport.getInstance(); 90 } 91 92 97 public MPv3(byte[] localEngineID) { 98 this(); 99 setLocalEngineID(localEngineID); 100 } 101 102 107 public static byte[] createLocalEngineID() { 108 byte[] engineID = new byte[5]; 109 engineID[0] = (byte)(0x80 | ((enterpriseID >> 24) & 0xFF)); 110 engineID[1] = (byte)((enterpriseID >> 16) & 0xFF); 111 engineID[2] = (byte)((enterpriseID >> 8) & 0xFF); 112 engineID[3] = (byte)(enterpriseID & 0xFF); 113 engineID[4] = 1; 114 OctetString os = new OctetString(); 115 try { 116 os.setValue(InetAddress.getLocalHost().getAddress()); 117 } 118 catch (UnknownHostException ex) { 119 logger.debug("Local host cannot be determined for creation of local engine ID"); 120 engineID[4] = 4; 121 os.setValue("SNMP4J".getBytes()); 122 } 123 OctetString ownEngineID = new OctetString(engineID); 124 ownEngineID.append(os); 125 return ownEngineID.getValue(); 126 } 127 128 135 public static byte[] createLocalEngineID(OctetString id) { 136 byte[] engineID = new byte[5]; 137 engineID[0] = (byte)(0x80 | ((enterpriseID >> 24) & 0xFF)); 138 engineID[1] = (byte)((enterpriseID >> 16) & 0xFF); 139 engineID[2] = (byte)((enterpriseID >> 8) & 0xFF); 140 engineID[3] = (byte)(enterpriseID & 0xFF); 141 engineID[4] = 4; 142 OctetString ownEngineID = new OctetString(engineID); 143 ownEngineID.append(id); 144 return ownEngineID.getValue(); 145 } 146 147 153 public void setLocalEngineID(byte[] engineID) { 154 if ((engineID == null) || 155 (engineID.length < MINLEN_ENGINE_ID) || 156 (engineID.length > MAXLEN_ENGINE_ID)) { 157 throw new IllegalArgumentException ("Illegal (local) engine ID"); 158 } 159 this.localEngineID = engineID; 160 } 161 162 167 public byte[] getLocalEngineID() { 168 byte[] retval = new byte[localEngineID.length]; 169 System.arraycopy(localEngineID, 0, retval, 0, localEngineID.length); 170 return retval; 171 } 172 173 177 public void initDefaults() { 178 securityProtocols.addDefaultProtocols(); 179 } 180 181 189 public AuthenticationProtocol getAuthProtocol(OID id) { 190 return securityProtocols.getAuthenticationProtocol(id); 191 } 192 193 201 public PrivacyProtocol getPrivProtocol(OID id) { 202 return securityProtocols.getPrivacyProtocol(id); 203 } 204 205 213 public SecurityModel getSecurityModel(int id) { 214 return securityModels.getSecurityModel(new Integer32(id)); 215 } 216 217 public int getID() { 218 return ID; 219 } 220 221 public boolean isProtocolVersionSupported(int version) { 222 return (version == SnmpConstants.version3); 223 } 224 225 235 public boolean addEngineID(Address address, OctetString engineID) { 236 if (!Arrays.equals(this.localEngineID, engineID.getValue())) { 237 engineIDs.put(address, engineID); 238 if (snmpEngineListeners != null) { 239 fireEngineChanged(new SnmpEngineEvent(this, 240 SnmpEngineEvent.ADDED_ENGINE_ID, 241 engineID, address)); 242 } 243 return true; 244 } 245 return false; 246 } 247 248 257 public OctetString getEngineID(Address address) { 258 return (OctetString) engineIDs.get(address); 259 } 260 261 271 public OctetString removeEngineID(Address address) { 272 OctetString engineID = (OctetString) engineIDs.remove(address); 273 if ((engineID != null) && (snmpEngineListeners != null)) { 274 fireEngineChanged(new SnmpEngineEvent(this, 275 SnmpEngineEvent.REMOVED_ENGINE_ID, 276 engineID, address)); 277 } 278 return engineID; 279 } 280 281 282 288 protected static class CacheEntry extends StateReference { 289 int msgID; 290 long transactionID; 291 byte[] secEngineID; 292 SecurityModel secModel; 293 byte[] secName; 294 int secLevel; 295 byte[] contextEngineID; 296 byte[] contextName; 297 SecurityStateReference secStateReference; 298 int errorCode; 299 300 public CacheEntry(int msgID, 301 long reqID, 302 byte[] secEngineID, 303 SecurityModel secModel, 304 byte[] secName, 305 int secLevel, 306 byte[] contextEngineID, 307 byte[] contextName, 308 SecurityStateReference secStateReference, 309 int errorCode) { 310 this.msgID = msgID; 311 this.transactionID = reqID; 312 this.secEngineID = secEngineID; 313 this.secModel = secModel; 314 this.secName = secName; 315 this.secLevel = secLevel; 316 this.contextEngineID = contextEngineID; 317 this.contextName = contextName; 318 this.secStateReference = secStateReference; 319 this.errorCode = errorCode; 320 } 321 } 322 323 328 protected static class Cache { 329 330 private Map entries = new WeakHashMap(25); 331 332 344 public synchronized int addEntry(StateReference entry) { 345 if (logger.isDebugEnabled()) { 346 logger.debug("Adding cache entry: "+entry); 347 } 348 StateReference existing = 349 (StateReference) entries.get(entry.getPduHandle()); 350 if (existing != null) { 351 if (existing.equals(entry)) { 352 if (logger.isDebugEnabled()) { 353 logger.debug("Doubled message: "+entry); 354 } 355 return SnmpConstants.SNMP_MP_DOUBLED_MESSAGE; 356 } 357 } 358 PduHandle key = entry.getPduHandle(); 360 entry.setPduHandle(null); 363 entries.put(key, entry); 364 return SnmpConstants.SNMP_MP_OK; 365 } 366 367 375 386 394 public synchronized boolean deleteEntry(PduHandle pduHandle) { 395 StateReference e = (StateReference) entries.remove(pduHandle); 396 return (e != null); 397 } 398 399 408 public synchronized StateReference popEntry(int msgID) { 409 for (Iterator it = entries.keySet().iterator(); it.hasNext(); ) { 410 PduHandle key = (PduHandle) it.next(); 411 StateReference e = (StateReference) entries.get(key); 412 if ((e != null) && (e.getMsgID() == msgID)) { 413 it.remove(); 414 e.setPduHandle(key); 415 if (logger.isDebugEnabled()) { 416 logger.debug("Removed cache entry: "+e); 417 } 418 return e; 419 } 420 } 421 return null; 422 } 423 } 424 425 431 protected static class HeaderData 432 implements BERSerializable { 433 434 public static final byte FLAG_AUTH = 0x01; 435 public static final byte FLAG_PRIV = 0x02; 436 437 Integer32 msgID = new Integer32(0); 438 Integer32 msgMaxSize = new Integer32(Integer.MAX_VALUE); 439 OctetString msgFlags = new OctetString(new byte[1]); 440 Integer32 securityModel = new Integer32(SecurityModel.SECURITY_MODEL_ANY); 441 442 public void setMsgID(int msgID) { 443 this.msgID.setValue(msgID); 444 } 445 446 public int getMsgID() { 447 return msgID.getValue(); 448 } 449 450 public void setMsgMaxSize(int msgMaxSize) { 451 this.msgMaxSize.setValue(msgMaxSize); 452 } 453 454 public int getMsgMaxSize() { 455 return msgMaxSize.getValue(); 456 } 457 458 public void setMsgFlags(int flags) { 459 this.msgFlags.getValue()[0] = (byte) flags; 460 } 461 462 public int getMsgFlags() { 463 return msgFlags.getValue()[0] & 0xFF; 464 } 465 466 public void setSecurityModel(int model) { 467 securityModel.setValue(model); 468 } 469 470 public int getSecurityModel() { 471 return securityModel.getValue(); 472 } 473 474 public int getBERPayloadLength() { 475 int length = msgID.getBERLength(); 476 length += msgMaxSize.getBERLength(); 477 length += msgFlags.getBERLength(); 478 length += securityModel.getBERLength(); 479 return length; 480 } 481 482 public int getBERLength() { 483 int length = getBERPayloadLength(); 484 length += BER.getBERLengthOfLength(length) + 1; 485 return length; 486 } 487 488 public void decodeBER(BERInputStream message) throws IOException { 489 BER.MutableByte type = new BER.MutableByte(); 490 int length = BER.decodeHeader(message, type); 491 if (type.getValue() != BER.SEQUENCE) { 492 throw new IOException("Unexpected sequence header type: " + 493 type.getValue()); 494 } 495 msgID.decodeBER(message); 496 msgMaxSize.decodeBER(message); 497 if (msgMaxSize.getValue() < 484) { 498 throw new IOException("Invalid msgMaxSize: " + msgMaxSize); 499 } 500 msgFlags.decodeBER(message); 501 if (msgFlags.length() != 1) { 502 throw new IOException("Message flags length != 1: " + msgFlags.length()); 503 } 504 securityModel.decodeBER(message); 505 if (logger.isDebugEnabled()) { 506 logger.debug("SNMPv3 header decoded: msgId=" + msgID + 507 ", msgMaxSize=" + msgMaxSize + 508 ", msgFlags=" + msgFlags.toHexString() + 509 ", secModel=" + securityModel); 510 } 511 BER.checkSequenceLength(length, this); 512 } 513 514 public void encodeBER(OutputStream outputStream) throws IOException { 515 BER.encodeHeader(outputStream, BER.SEQUENCE, getBERPayloadLength()); 516 msgID.encodeBER(outputStream); 517 msgMaxSize.encodeBER(outputStream); 518 msgFlags.encodeBER(outputStream); 519 securityModel.encodeBER(outputStream); 520 } 521 } 522 523 528 public synchronized int getNextMessageID() { 529 if (currentMsgID >= MAX_MESSAGE_ID) { 530 currentMsgID = 1; 531 } 532 return currentMsgID++; 533 } 534 535 540 public SecurityProtocols getSecurityProtocols() { 541 return securityProtocols; 542 } 543 544 548 public void setSecurityProtocols(SecurityProtocols securityProtocols) { 549 this.securityProtocols = securityProtocols; 550 } 551 552 558 protected int getDefaultSecurityModel() { 559 return SecurityModel.SECURITY_MODEL_USM; 560 } 561 562 public void releaseStateReference(PduHandle pduHandle) { 563 cache.deleteEntry(pduHandle); 564 } 565 566 public int prepareOutgoingMessage(Address transportAddress, 567 int maxMessageSize, 568 int messageProcessingModel, 569 int securityModel, 570 byte[] securityName, 571 int securityLevel, 572 PDU pdu, 573 boolean expectResponse, 574 PduHandle sendPduHandle, 575 Address destTransportAddress, 576 BEROutputStream outgoingMessage) throws 577 IOException { 578 if (!(pdu instanceof ScopedPDU)) { 579 throw new IllegalArgumentException ( 580 "MPv3 only accepts ScopedPDU instances as pdu parameter"); 581 } 582 ScopedPDU scopedPDU = (ScopedPDU) pdu; 583 byte[] secEngineID = null; 585 OctetString securityEngineID = 586 (OctetString) engineIDs.get(transportAddress); 587 if (securityEngineID != null) { 588 secEngineID = securityEngineID.getValue(); 589 if (scopedPDU.getContextEngineID().length() == 0) { 590 if (logger.isDebugEnabled()) { 591 logger.debug("Context engine ID of scoped PDU is empty! Setting it to authoritative engine ID: "+ 592 securityEngineID.toHexString()); 593 } 594 scopedPDU.setContextEngineID(new OctetString(secEngineID)); 595 } 596 } 597 else { 598 secEngineID = new byte[0]; 599 } 600 601 if (pdu.isConfirmedPdu()) { 603 if (secEngineID.length == 0) { 604 securityLevel = SecurityLevel.NOAUTH_NOPRIV; 605 securityModel = getDefaultSecurityModel(); 606 scopedPDU = (ScopedPDU) scopedPDU.clone(); 608 scopedPDU.clear(); 609 } 610 } 611 else { 612 if (scopedPDU.getContextEngineID().length() == 0) { 613 if (logger.isDebugEnabled()) { 614 logger.debug("Context engine ID of unconfirmed scoped PDU is empty! "+ 615 "Setting it to local engine ID"); 616 } 617 scopedPDU.setContextEngineID(new OctetString(localEngineID)); 618 } 619 } 620 621 int scopedPDULength = pdu.getBERLength(); 623 BEROutputStream scopedPdu = 624 new BEROutputStream(ByteBuffer.allocate(scopedPDULength)); 625 626 scopedPDU.encodeBER(scopedPdu); 627 628 HeaderData headerData = new HeaderData(); 629 int flags = 0; 630 switch (securityLevel) { 631 case SecurityLevel.NOAUTH_NOPRIV: 632 flags = 0; 633 break; 634 case SecurityLevel.AUTH_NOPRIV: 635 flags = 1; 636 break; 637 case SecurityLevel.AUTH_PRIV: 638 flags = 3; 639 break; 640 } 641 if (scopedPDU.isConfirmedPdu()) { 642 flags |= MPv3_REPORTABLE_FLAG; 643 } 644 else { 645 secEngineID = localEngineID; 646 } 647 648 int msgID = getNextMessageID(); 649 headerData.setMsgFlags(flags); 650 headerData.setMsgID(msgID); 651 headerData.setMsgMaxSize(maxMessageSize); 652 headerData.setSecurityModel(securityModel); 653 654 ByteBuffer globalDataBuffer = 655 ByteBuffer.allocate(headerData.getBERLength()); 656 BEROutputStream globalDataOutputStream = 657 new BEROutputStream(globalDataBuffer); 658 headerData.encodeBER(globalDataOutputStream); 659 660 BERInputStream scopedPDUInput = new BERInputStream(scopedPdu.rewind()); 661 662 SecurityModel secModel = 663 securityModels.getSecurityModel(new Integer32(securityModel)); 664 if (secModel == null) { 665 return SnmpConstants.SNMP_MP_UNSUPPORTED_SECURITY_MODEL; 666 } 667 SecurityParameters securityParameters = 669 secModel.newSecurityParametersInstance(); 670 671 int status = 672 secModel.generateRequestMessage(messageProcessingModel, 673 globalDataBuffer.array(), 674 maxMessageSize, 675 securityModel, 676 secEngineID, 677 securityName, 678 securityLevel, 679 scopedPDUInput, 680 securityParameters, 681 outgoingMessage); 682 if (status == SnmpConstants.SNMPv3_USM_OK) { 683 if (expectResponse) { 684 cache.addEntry(new StateReference(msgID, 685 flags, 686 maxMessageSize, 687 sendPduHandle, 688 transportAddress, 689 null, 690 secEngineID, secModel, 691 securityName, securityLevel, 692 scopedPDU.getContextEngineID(). 693 getValue(), 694 scopedPDU.getContextName().getValue(), 695 null, 696 status)); 697 } 698 } 699 return status; 700 } 701 702 public int prepareResponseMessage(int messageProcessingModel, 703 int maxMessageSize, 704 int securityModel, 705 byte[] securityName, 706 int securityLevel, 707 PDU pdu, 708 int maxSizeResponseScopedPDU, 709 StateReference stateReference, 710 StatusInformation statusInformation, 711 BEROutputStream outgoingMessage) throws 712 IOException { 713 714 StateReference cacheEntry = cache.popEntry(stateReference.getMsgID()); 715 if (cacheEntry == null) { 716 return SnmpConstants.SNMP_MP_UNKNOWN_MSGID; 717 } 718 719 int scopedPDULength = pdu.getBERLength(); 722 BEROutputStream scopedPDU; 723 if (scopedPDULength > maxSizeResponseScopedPDU) { 725 PDU tooBigPDU = new ScopedPDU((ScopedPDU)pdu); 726 tooBigPDU.clear(); 727 tooBigPDU.setRequestID(pdu.getRequestID()); 728 tooBigPDU.setErrorStatus(SnmpConstants.SNMP_ERROR_TOO_BIG); 729 tooBigPDU.setErrorIndex(0); 730 scopedPDULength = tooBigPDU.getBERLength(); 731 scopedPDU = new BEROutputStream(ByteBuffer.allocate(scopedPDULength)); 732 tooBigPDU.encodeBER(scopedPDU); 733 } 734 else { 735 scopedPDU = new BEROutputStream(ByteBuffer.allocate(scopedPDULength)); 736 pdu.encodeBER(scopedPDU); 737 } 738 739 HeaderData headerData = new HeaderData(); 740 int flags = 0; 741 switch (securityLevel) { 742 case SecurityLevel.NOAUTH_NOPRIV: 743 flags = 0; 744 break; 745 case SecurityLevel.AUTH_NOPRIV: 746 flags = 1; 747 break; 748 case SecurityLevel.AUTH_PRIV: 749 flags = 3; 750 break; 751 } 752 headerData.setMsgFlags(flags); 754 headerData.setMsgID(stateReference.getMsgID()); 755 headerData.setMsgMaxSize(maxMessageSize); 756 headerData.setSecurityModel(securityModel); 757 758 ByteBuffer globalDataBuffer = 759 ByteBuffer.allocate(headerData.getBERLength()); 760 BEROutputStream globalDataOutputStream = 761 new BEROutputStream(globalDataBuffer); 762 headerData.encodeBER(globalDataOutputStream); 763 764 OctetString securityEngineID; 765 switch (pdu.getType()) { 766 case PDU.RESPONSE: 767 case PDU.TRAP: 768 case PDU.REPORT: 769 case PDU.V1TRAP: 770 securityEngineID = new OctetString(localEngineID); 771 break; 772 default: 773 securityEngineID = new OctetString(cacheEntry.getSecurityEngineID()); 774 } 775 776 BERInputStream scopedPDUInput = new BERInputStream(scopedPDU.rewind()); 777 778 SecurityModel secModel = 779 securityModels.getSecurityModel(new Integer32(securityModel)); 780 SecurityParameters securityParameters = 782 secModel.newSecurityParametersInstance(); 783 784 int status = 785 secModel.generateResponseMessage(getID(), 786 globalDataBuffer.array(), 787 maxMessageSize, 788 securityModel, 789 securityEngineID.getValue(), 790 securityName, 791 securityLevel, 792 scopedPDUInput, 793 cacheEntry.getSecurityStateReference(), 794 securityParameters, 795 outgoingMessage); 796 return status; 797 } 798 799 823 public int sendReport(MessageDispatcher messageDispatcher, 824 ScopedPDU pdu, 825 int securityLevel, 826 int securityModel, 827 OctetString securityName, 828 int maxSizeResponseScopedPDU, 829 StateReference stateReference, 830 VariableBinding payload) { 831 ScopedPDU reportPDU = new ScopedPDU(); 832 reportPDU.setType(PDU.REPORT); 833 if (pdu != null) { 834 reportPDU.setContextEngineID(pdu.getContextEngineID()); 835 reportPDU.setContextName(pdu.getContextName()); 836 reportPDU.setRequestID(pdu.getRequestID()); 837 } 838 reportPDU.add(payload); 839 StatusInformation statusInformation = new StatusInformation(); 840 try { 841 int status = messageDispatcher.returnResponsePdu(getID(), 842 securityModel, 843 securityName.getValue(), 844 securityLevel, 845 reportPDU, 846 maxSizeResponseScopedPDU, 847 stateReference, 848 statusInformation); 849 if (status != SnmpConstants.SNMP_ERROR_SUCCESS) { 850 logger.warn("Error while sending report: " + status); 851 return SnmpConstants.SNMP_MP_ERROR; 852 } 853 } 854 catch (MessageException mex) { 855 logger.error("Error while sending report: " + mex.getMessage()); 856 return SnmpConstants.SNMP_MP_ERROR; 857 } 858 return SnmpConstants.SNMP_MP_OK; 859 } 860 861 public int prepareDataElements(MessageDispatcher messageDispatcher, 862 Address transportAddress, 863 BERInputStream wholeMsg, 864 Integer32 messageProcessingModel, 865 Integer32 securityModel, 866 OctetString securityName, 867 Integer32 securityLevel, 868 MutablePDU pdu, 869 PduHandle sendPduHandle, 870 Integer32 maxSizeResponseScopedPDU, 871 StatusInformation statusInformation, 872 MutableStateReference mutableStateReference) { 873 try { 874 StateReference stateReference = new StateReference(); 875 if (mutableStateReference.getStateReference() != null) { 877 stateReference.setTransportMapping( 878 mutableStateReference.getStateReference().getTransportMapping()); 879 } 880 messageProcessingModel.setValue(MPv3); 881 wholeMsg.mark(16); 882 883 BER.MutableByte type = new BER.MutableByte(); 884 int length = BER.decodeHeader(wholeMsg, type); 885 if (type.getValue() != BER.SEQUENCE) { 886 return SnmpConstants.SNMP_MP_PARSE_ERROR; 887 } 888 long lengthOfLength = wholeMsg.getPosition(); 889 wholeMsg.reset(); 890 wholeMsg.mark(length); 891 if (wholeMsg.skip(lengthOfLength) != lengthOfLength) { 892 return SnmpConstants.SNMP_MP_PARSE_ERROR; 893 } 894 895 Integer32 snmpVersion = new Integer32(); 896 snmpVersion.decodeBER(wholeMsg); 897 if (snmpVersion.getValue() != SnmpConstants.version3) { 898 throw new RuntimeException ( 900 "Internal error unexpected snmp version read"); 901 } 902 HeaderData header = new HeaderData(); 904 header.decodeBER(wholeMsg); 905 securityModel.setValue(header.getSecurityModel()); 906 907 stateReference.setMsgID(header.getMsgID()); 908 stateReference.setMsgFlags(header.getMsgFlags()); 909 stateReference.setAddress(transportAddress); 910 911 mutableStateReference.setStateReference(stateReference); 912 913 maxSizeResponseScopedPDU.setValue(header.msgMaxSize.getValue() - 915 MAX_HEADER_LENGTH); 916 917 ScopedPDU scopedPdu = new ScopedPDU(); 918 pdu.setPdu(scopedPdu); 919 920 SecurityModel secModel = securityModels.getSecurityModel(securityModel); 921 if (secModel == null) { 922 logger.error("RFC3412 §7.2.4 - Unsupported security model: " + 923 securityModel); 924 CounterEvent event = 925 new CounterEvent(this, 926 SnmpConstants.snmpUnknownSecurityModels); 927 fireIncrementCounter(event); 928 return SnmpConstants.SNMP_MP_UNSUPPORTED_SECURITY_MODEL; 929 } 930 931 switch (header.getMsgFlags() & 0x03) { 933 case 3: { 934 securityLevel.setValue(SecurityLevel.AUTH_PRIV); 935 break; 936 } 937 case 0: { 938 securityLevel.setValue(SecurityLevel.NOAUTH_NOPRIV); 939 break; 940 } 941 case 1: { 942 securityLevel.setValue(SecurityLevel.AUTH_NOPRIV); 943 break; 944 } 945 default: { 946 securityLevel.setValue(SecurityLevel.NOAUTH_NOPRIV); 947 logger.debug("RFC3412 §7.2.5 - Invalid message (illegal msgFlags)"); 948 CounterEvent event = new CounterEvent(this, 949 SnmpConstants.snmpInvalidMsgs); 950 fireIncrementCounter(event); 951 return SnmpConstants.SNMP_MP_INVALID_MESSAGE; 953 } 954 } 955 956 int secParametersPosition = (int)wholeMsg.getPosition(); 957 SecurityParameters secParameters = 959 secModel.newSecurityParametersInstance(); 960 secParameters.decodeBER(wholeMsg); 961 secParameters.setSecurityParametersPosition(secParametersPosition); 962 963 boolean reportableFlag = ((header.getMsgFlags() & 0x04) > 0); 965 966 OctetString securityEngineID = new OctetString(); 967 SecurityStateReference secStateReference = 969 secModel.newSecurityStateReference(); 970 wholeMsg.reset(); 974 975 BEROutputStream scopedPDU = new BEROutputStream(); 976 int status = 977 secModel.processIncomingMsg(snmpVersion.getValue(), 978 header.getMsgMaxSize() - 979 MAX_HEADER_LENGTH, 980 secParameters, 981 secModel, 982 securityLevel.getValue(), 983 wholeMsg, 984 securityEngineID, 986 securityName, 987 scopedPDU, 988 maxSizeResponseScopedPDU, 989 secStateReference, 990 statusInformation); 991 wholeMsg.close(); 992 if (status == SnmpConstants.SNMPv3_USM_OK) { 993 try { 994 BERInputStream scopedPduStream = 995 new BERInputStream(scopedPDU.rewind()); 996 scopedPdu.decodeBER(scopedPduStream); 997 sendPduHandle.setTransactionID(scopedPdu.getRequestID().getValue()); 998 999 addEngineID(transportAddress, securityEngineID); 1001 } 1002 catch (IOException iox) { 1003 logger.warn("ASN.1 parse error: "+iox.getMessage()); 1004 if (logger.isDebugEnabled()) { 1005 iox.printStackTrace(); 1006 } 1007 CounterEvent event = new CounterEvent(this, 1008 SnmpConstants. 1009 snmpInASNParseErrs); 1010 fireIncrementCounter(event); 1011 return SnmpConstants.SNMP_MP_PARSE_ERROR; 1012 } 1013 if (((scopedPdu.getContextEngineID() == null) || 1014 (scopedPdu.getContextEngineID().length() == 0)) && 1015 ((scopedPdu.getType() != PDU.RESPONSE) && 1016 (scopedPdu.getType() != PDU.REPORT))) { 1017 CounterEvent event = new CounterEvent(this, 1018 SnmpConstants. 1019 snmpUnknownPDUHandlers); 1020 fireIncrementCounter(event); 1021 VariableBinding errorIndication = 1022 new VariableBinding(event.getOid(), event.getCurrentValue()); 1023 statusInformation.setErrorIndication(errorIndication); 1024 status = SnmpConstants.SNMP_MP_UNKNOWN_PDU_HANDLERS; 1025 } 1026 } 1027 1028 if (status != SnmpConstants.SNMPv3_USM_OK) { 1029 if ((reportableFlag) && 1030 (statusInformation.getErrorIndication() != null)) { 1031 try { 1033 if (scopedPDU.getBuffer() != null) { 1034 BERInputStream scopedPduStream = 1035 new BERInputStream(scopedPDU.rewind()); 1036 scopedPdu.decodeBER(scopedPduStream); 1037 } 1038 else { scopedPdu = null; 1040 } 1041 } 1042 catch (IOException iox) { 1043 logger.warn(iox); 1044 scopedPdu = null; 1045 } 1046 1047 StateReference cacheEntry = 1048 new StateReference(header.getMsgID(), 1049 header.getMsgFlags(), 1050 maxSizeResponseScopedPDU.getValue(), 1051 sendPduHandle, 1052 transportAddress, 1053 null, 1054 securityEngineID.getValue(), 1055 secModel, securityName.getValue(), 1056 securityLevel.getValue(), 1057 (scopedPdu == null) ? new byte[0] : 1058 scopedPdu.getContextEngineID().getValue(), 1059 (scopedPdu == null) ? new byte[0] : 1060 scopedPdu.getContextName().getValue(), 1061 secStateReference, status); 1062 cache.addEntry(cacheEntry); 1063 1064 int reportStatus = 1065 sendReport(messageDispatcher, scopedPdu, 1066 statusInformation.getSecurityLevel().getValue(), 1067 secModel.getID(), securityName, 1068 maxSizeResponseScopedPDU.getValue(), 1069 stateReference, 1070 statusInformation.getErrorIndication()); 1071 if (reportStatus != SnmpConstants.SNMP_MP_OK) { 1072 logger.warn("Sending report failed with error code: " + 1073 reportStatus); 1074 } 1075 } 1076 return SnmpConstants.SNMP_MP_USM_ERROR; 1077 } 1078 1079 stateReference.setAddress(transportAddress); 1080 stateReference.setSecurityName(securityName.getValue()); 1081 stateReference.setContextEngineID(scopedPdu.getContextEngineID().getValue()); 1082 stateReference.setContextName(scopedPdu.getContextName().getValue()); 1083 stateReference.setMaxSizeResponseScopedPDU(maxSizeResponseScopedPDU. 1084 getValue()); 1085 stateReference.setMsgID(header.getMsgID()); 1086 stateReference.setMsgFlags(header.getMsgFlags()); 1087 stateReference.setSecurityEngineID(securityEngineID.getValue()); 1088 stateReference.setSecurityLevel(securityLevel.getValue()); 1089 stateReference.setSecurityModel(secModel); 1090 stateReference.setSecurityStateReference(secStateReference); 1091 stateReference.setPduHandle(sendPduHandle); 1092 1093 if ((scopedPdu.getType() == PDU.RESPONSE) || 1094 (scopedPdu.getType() == PDU.REPORT)) { 1095 StateReference cacheEntry = cache.popEntry(header.getMsgID()); 1096 if (cacheEntry != null) { 1097 if (logger.isDebugEnabled()) { 1098 logger.debug("RFC3412 §7.2.10 - Received PDU (msgID=" + 1099 header.getMsgID() + ") is a response or " + 1100 "an internal class message. PduHandle.transactionID = " + 1101 cacheEntry.getPduHandle().getTransactionID()); 1102 } 1103 sendPduHandle.copyFrom(cacheEntry.getPduHandle()); 1104 1105 if (scopedPdu.getType() == PDU.REPORT) { 1106 1107 statusInformation.setContextEngineID(scopedPdu.getContextEngineID().getValue()); 1108 statusInformation.setContextName(scopedPdu.getContextName().getValue()); 1109 statusInformation.setSecurityLevel(securityLevel); 1110 1111 if (((cacheEntry.getSecurityEngineID().length != 0) && 1112 (!securityEngineID.equals(cacheEntry.getSecurityEngineID()))) || 1113 (secModel.getID() != cacheEntry.getSecurityModel().getID()) || 1114 ((!securityName.equals(cacheEntry.getSecurityName()) && 1115 (securityName.length() != 0)))) { 1116 if (logger.isDebugEnabled()) { 1117 logger.debug( 1118 "RFC 3412 §7.2.11 - Received report message does not match sent message"); 1119 } 1120 mutableStateReference.setStateReference(null); 1122 return SnmpConstants.SNMP_MP_MATCH_ERROR; 1123 } 1124 addEngineID(cacheEntry.getAddress(), securityEngineID); 1125 mutableStateReference.setStateReference(null); 1127 logger.debug("MPv3 finished"); 1128 return SnmpConstants.SNMP_MP_OK; 1129 } 1130 if (scopedPdu.getType() == PDU.RESPONSE) { 1131 if (((!securityEngineID.equals(cacheEntry.getSecurityEngineID())) && 1132 (cacheEntry.getSecurityEngineID().length != 0)) || 1133 (secModel.getID() != cacheEntry.getSecurityModel().getID()) || 1134 (!securityName.equals(cacheEntry.getSecurityName())) || 1135 (securityLevel.getValue() != cacheEntry.getSecurityLevel()) || 1136 ((!scopedPdu.getContextEngineID().equals(cacheEntry.getContextEngineID())) && 1137 (cacheEntry.getContextEngineID().length != 0)) || 1138 ((!scopedPdu.getContextName().equals(cacheEntry.getContextName()) && 1139 (cacheEntry.getContextName().length != 0)))) { 1140 logger.debug( 1141 "RFC 3412 §7.2.12.b - Received response message does not match sent message"); 1142 mutableStateReference.setStateReference(null); 1144 return SnmpConstants.SNMP_MP_MATCH_ERROR; 1145 } 1146 mutableStateReference.setStateReference(null); 1148 logger.debug("MPv3 finished"); 1149 return SnmpConstants.SNMP_MP_OK; 1150 } 1151 } 1152 else { 1153 if (logger.isDebugEnabled()) { 1154 logger.debug("RFC3412 §7.2.10 - Received PDU (msgID=" + 1155 header.getMsgID() + ") is a response or " + 1156 "internal class message, but cached " + 1157 "information for the msgID could not be found"); 1158 } 1159 return SnmpConstants.SNMP_MP_UNKNOWN_MSGID; 1160 } 1161 } 1162 else { 1163 logger.debug("RFC3412 §7.2.10 - Received PDU is NOT a response or " + 1164 "internal class message -> unchanged PduHandle = "+ 1165 sendPduHandle); 1166 } 1167 switch (scopedPdu.getType()) { 1168 case PDU.GET: 1169 case PDU.GETBULK: 1170 case PDU.GETNEXT: 1171 case PDU.INFORM: 1172 case PDU.SET: { 1173 if (securityEngineID.length() == 0) { 1174 logger.debug("Received confirmed message with 0 length security engine ID"); 1175 } 1176 else if (!securityEngineID.equals(localEngineID)) { 1177 if (logger.isDebugEnabled()) { 1178 logger.debug("RFC 3412 §7.2.13.a - Security engine ID " + 1179 securityEngineID.toHexString() + 1180 " does not match local engine ID " + 1181 new OctetString(localEngineID).toHexString()); 1182 } 1183 mutableStateReference.setStateReference(null); 1184 return SnmpConstants.SNMP_MP_INVALID_ENGINEID; 1185 } 1186 int cacheStatus = cache.addEntry(stateReference); 1187 if (cacheStatus == SnmpConstants.SNMP_MP_DOUBLED_MESSAGE) { 1188 mutableStateReference.setStateReference(null); 1189 } 1190 return SnmpConstants.SNMP_MP_OK; 1191 } 1192 case PDU.TRAP: 1193 case PDU.V1TRAP: { 1194 mutableStateReference.setStateReference(null); 1195 return SnmpConstants.SNMP_MP_OK; 1196 } 1197 } 1198 return SnmpConstants.SNMP_MP_ERROR; 1200 } 1201 catch (IOException iox) { 1202 logger.warn("MPv3 parse error: " + iox.getMessage()); 1203 if (logger.isDebugEnabled()) { 1204 iox.printStackTrace(); 1205 } 1206 return SnmpConstants.SNMP_MP_PARSE_ERROR; 1207 } 1208 } 1209 1210 1215 public void setSecurityModels(SecurityModels securityModels) { 1216 this.securityModels = securityModels; 1217 } 1218 1219 1224 public SecurityModels getSecurityModels() { 1225 return securityModels; 1226 } 1227 1228 1233 public static int getEnterpriseID() { 1234 return enterpriseID; 1235 } 1236 1237 1243 public static void setEnterpriseID(int newEnterpriseID) { 1244 enterpriseID = newEnterpriseID; 1245 } 1246 1247 1251 protected void fireIncrementCounter(CounterEvent e) { 1252 counterSupport.fireIncrementCounter(e); 1253 } 1254 1255 1262 public CounterSupport getCounterSupport() { 1263 return counterSupport; 1264 } 1265 1266 1272 public void setCounterSupport(CounterSupport counterSupport) { 1273 if (counterSupport == null) { 1274 throw new NullPointerException (); 1275 } 1276 this.counterSupport = counterSupport; 1277 } 1278 1279 1286 public synchronized void addSnmpEngineListener(SnmpEngineListener l) { 1287 if (snmpEngineListeners == null) { 1288 snmpEngineListeners = new Vector(); 1289 } 1290 snmpEngineListeners.add(l); 1291 } 1292 1293 1299 public synchronized void removeSnmpEngineListener(SnmpEngineListener l) { 1300 if (snmpEngineListeners != null) { 1301 snmpEngineListeners.remove(l); 1302 } 1303 } 1304 1305 1311 protected void fireEngineChanged(SnmpEngineEvent engineEvent) { 1312 if (snmpEngineListeners != null) { 1313 Vector listeners = snmpEngineListeners; 1314 int count = listeners.size(); 1315 for (int i = 0; i < count; i++) { 1316 ((SnmpEngineListener) listeners.elementAt(i)).engineChanged(engineEvent); 1317 } 1318 } 1319 } 1320} 1321 | Popular Tags |