Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNMPv3 over DTLS #133

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
210a3be
Merge pull request #1 from lextudio/master
kdurkin77 Nov 15, 2019
33d89e3
Merge pull request #2 from lextudio/master
kdurkin77 Dec 5, 2019
375dca0
Updated to use DTLS2.Net to allow for SNMPv3 over DTLS
kdurkin77 Dec 5, 2019
98a183d
Merge branch 'master' of https://github.com/kmiller77/sharpsnmplib
kdurkin77 Dec 5, 2019
ccb8536
Removed the project reference to DTLS2.Net and added the nuget package
kdurkin77 Dec 5, 2019
328f898
Forgot to remove my test project
kdurkin77 Dec 5, 2019
900037d
Removed the default keyword to allow for the Mac version to build pro…
kdurkin77 Dec 5, 2019
7007b74
Created a static Empty to use instead of the empty ctor for SecurityP…
kdurkin77 Dec 6, 2019
8319b80
Removed the Listeners and ListenerBindings (this needs to be moved in…
kdurkin77 Dec 6, 2019
2b42aa7
Added some unit testing and removed incorrect parameter comment in Ge…
kdurkin77 Dec 6, 2019
a11571a
Updating DTLS2.Net Version
kdurkin77 Dec 11, 2019
221da76
Updated GetBulkRequestMessage, GetNextRequestMessage, and SetRequestM…
kdurkin77 Dec 11, 2019
817c5b2
Forgot to update the test - will add more tests for the other message…
kdurkin77 Dec 11, 2019
2c47b81
Updated DTLS2.Net package - that update includes a timeout when conne…
kdurkin77 Dec 19, 2019
1927f5a
Added a timeout to connecting to the server in GetSecureResponse
kdurkin77 Jan 3, 2020
0d3b7a8
Created separate timeout for connection and response
kdurkin77 Jan 7, 2020
a7e33ce
Updated to the new DTLS2.Net library
kdurkin77 Jan 9, 2020
a4488c8
Upgraded DTLS2.Net library - using async
kdurkin77 Jan 14, 2020
c1e0a27
Merge branch 'master' of https://github.com/lextudio/sharpsnmplib
kdurkin77 Jan 14, 2020
cb8914b
Fixed from merge
kdurkin77 Jan 14, 2020
f10b0e9
Merge pull request #4 from lextudio/master
kdurkin77 Jan 16, 2020
5a9ef97
Updated DTLS2.Net
kdurkin77 Jan 17, 2020
2c50ccc
Merge pull request #5 from lextudio/master
kdurkin77 Jan 17, 2020
14c6417
Updated DTLS2.Net project
kdurkin77 Jan 17, 2020
44efc4c
Updating DTLS2.Net and no longer calling StopAsync since Client is no…
kdurkin77 Jan 20, 2020
8dee6aa
Updated the async functions to have the Async suffix
kdurkin77 Jan 28, 2020
bff3913
Updating DTLS library
kdurkin77 Jan 28, 2020
89f378c
Updated the DTLS2.Net library in an effort to help with high CPU with…
kdurkin77 Feb 3, 2020
39457b2
Merge pull request #6 from lextudio/master
kdurkin77 Feb 3, 2020
5adcd46
Added support for standard 2.1 and upgraded DTLS2.Net
kdurkin77 Feb 4, 2020
d27a0ec
Merge pull request #7 from lextudio/master
kdurkin77 Jun 11, 2020
fb4d8cf
Updated DTLS2.NET
kdurkin77 Jun 11, 2020
d849c60
Upgraded DLTS2.Net and added in missing .ConfigureAwait(false)
kdurkin77 Aug 12, 2020
18c2c72
Added ability to use TimeSpan for timeouts as well as int for millise…
kdurkin77 Aug 24, 2020
59ce5d9
Updated packages
kdurkin77 Aug 28, 2020
3d33735
Updated DTLS2.Net
kdurkin77 Sep 15, 2020
b677193
Updated DTLS.Net library
kdurkin77 Jul 1, 2021
4933bc7
Merge branch 'master' of https://github.com/lextudio/sharpsnmplib int…
kdurkin77 Feb 16, 2022
af04e83
Some cleanup based on warnings
kdurkin77 Feb 16, 2022
c9cc316
merged from upstream master
kdurkin77 May 10, 2024
dfed035
corrected the target frameworks and added net8.0
kdurkin77 May 10, 2024
a4c181d
updated packages
kdurkin77 May 10, 2024
2a55df2
Updated TargetFrameworks and Microsoft.SourceLink.GitHub and SonarAna…
kdurkin77 May 13, 2024
ed31d91
updated DTLS2.Net
kdurkin77 May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions SharpSnmpLib/Header.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public sealed class Header : ISegment
private readonly Integer32 _maxSize;
private readonly OctetString _flags;
private readonly Integer32 _securityModel;
private static readonly Integer32 DefaultSecurityModel = new Integer32(3);
private static readonly Integer32 DefaultSecurityModel = new Integer32((int)SecurityModel.Usm);
private static readonly Integer32 DefaultMaxMessageSize = new Integer32(MaxMessageSize);
private static readonly Header EmptyHeader = new Header();
private readonly Sequence _container;
Expand Down Expand Up @@ -82,8 +82,9 @@ public Header(ISnmpData data)
/// <param name="messageId">The message id.</param>
/// <param name="maxMessageSize">Size of the max message.</param>
/// <param name="securityLevel">The security level.</param>
/// <param name="securityModel">The security model.</param>
/// <remarks>If you want an empty header, please use <see cref="Empty"/>.</remarks>
public Header(Integer32 messageId, Integer32 maxMessageSize, Levels securityLevel)
public Header(Integer32 messageId, Integer32 maxMessageSize, Levels securityLevel, Integer32 securityModel)
{
if (maxMessageSize == null)
{
Expand All @@ -94,7 +95,19 @@ public Header(Integer32 messageId, Integer32 maxMessageSize, Levels securityLeve
_maxSize = maxMessageSize;
SecurityLevel = securityLevel;
_flags = new OctetString(SecurityLevel);
_securityModel = DefaultSecurityModel;
_securityModel = securityModel;
}

/// <summary>
/// Initializes a new instance of the <see cref="Header"/> class.
/// </summary>
/// <param name="messageId">The message id.</param>
/// <param name="maxMessageSize">Size of the max message.</param>
/// <param name="securityLevel">The security level.</param>
/// <remarks>If you want an empty header, please use <see cref="Empty"/>.</remarks>
public Header(Integer32 messageId, Integer32 maxMessageSize, Levels securityLevel)
: this(messageId, maxMessageSize, securityLevel, DefaultSecurityModel)
{
}

/// <summary>
Expand All @@ -119,6 +132,15 @@ public int MessageId
get { return _messageId.ToInt32(); }
}

/// <summary>
/// Gets the security model.
/// </summary>
/// <value>The security model.</value>
public SecurityModel SecurityModel
{
get { return (SecurityModel)_securityModel.ToInt32(); }
}

#region ISegment Members

/// <summary>
Expand Down
100 changes: 90 additions & 10 deletions SharpSnmpLib/Messaging/GetRequestMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using Lextm.SharpSnmpLib.Security;
kdurkin77 marked this conversation as resolved.
Show resolved Hide resolved
using System;
using System.Collections.Generic;
using System.Globalization;
using Lextm.SharpSnmpLib.Security;

namespace Lextm.SharpSnmpLib.Messaging
{
Expand Down Expand Up @@ -83,6 +83,60 @@ public GetRequestMessage(VersionCode version, int messageId, int requestId, Octe
{
}

/// <summary>
/// Initializes a new instance of the <see cref="GetRequestMessage"/> class.
/// </summary>
/// <param name="version">The version.</param>
/// <param name="messageId">The message id.</param>
/// <param name="requestId">The request id.</param>
/// <param name="userName">Name of the user.</param>
/// <param name="contextName">Context name.</param>
/// <param name="variables">The variables.</param>
/// <param name="privacy">The privacy provider.</param>
/// <param name="maxMessageSize">Size of the max message.</param>
/// <param name="securityModel">The type of security model</param>
public GetRequestMessage(VersionCode version, int messageId, int requestId, OctetString userName, OctetString contextName, IList<Variable> variables, IPrivacyProvider privacy, int maxMessageSize)
{
if (userName == null)
{
throw new ArgumentNullException(nameof(userName));
}

if (variables == null)
{
throw new ArgumentNullException(nameof(variables));
}

if (contextName == null)
{
throw new ArgumentNullException(nameof(contextName));
}

if (version != VersionCode.V3)
{
throw new ArgumentException("Only v3 is supported.", nameof(version));
}

if (privacy == null)
{
throw new ArgumentNullException(nameof(privacy));
}

Version = version;
Privacy = privacy;
Header = new Header(new Integer32(messageId), new Integer32(maxMessageSize), privacy.ToSecurityLevel() | Levels.Reportable, new Integer32((int)SecurityModel.Tsm));
Parameters = new SecurityParameters();

var pdu = new GetRequestPdu(
requestId,
variables);
var contextEngineId = OctetString.Empty;
Scope = new Scope(contextEngineId, contextName, pdu);

Privacy.ComputeHash(Version, Header, Parameters, Scope);
_bytes = this.PackMessage(null).ToBytes();
}

/// <summary>
/// Initializes a new instance of the <see cref="GetRequestMessage"/> class.
/// </summary>
Expand All @@ -95,7 +149,8 @@ public GetRequestMessage(VersionCode version, int messageId, int requestId, Octe
/// <param name="privacy">The privacy provider.</param>
/// <param name="maxMessageSize">Size of the max message.</param>
/// <param name="report">The report.</param>
public GetRequestMessage(VersionCode version, int messageId, int requestId, OctetString userName, OctetString contextName, IList<Variable> variables, IPrivacyProvider privacy, int maxMessageSize, ISnmpMessage report)
/// <param name="securityModel">The type of security model</param>
public GetRequestMessage(VersionCode version, int messageId, int requestId, OctetString userName, OctetString contextName, IList<Variable> variables, IPrivacyProvider privacy, int maxMessageSize, ISnmpMessage report, SecurityModel securityModel)
{
if (userName == null)
{
Expand Down Expand Up @@ -129,17 +184,26 @@ public GetRequestMessage(VersionCode version, int messageId, int requestId, Octe

Version = version;
Privacy = privacy;
Header = new Header(new Integer32(messageId), new Integer32(maxMessageSize), privacy.ToSecurityLevel() | Levels.Reportable, new Integer32((int)securityModel));

Header = new Header(new Integer32(messageId), new Integer32(maxMessageSize), privacy.ToSecurityLevel() | Levels.Reportable);
var parameters = report.Parameters;
var authenticationProvider = Privacy.AuthenticationProvider;
Parameters = new SecurityParameters(
parameters.EngineId,
parameters.EngineBoots,
parameters.EngineTime,
userName,
authenticationProvider.CleanDigest,
Privacy.Salt);

if (securityModel == SecurityModel.Tsm)
{
Parameters = new SecurityParameters();
kdurkin77 marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
Parameters = new SecurityParameters(
parameters.EngineId,
parameters.EngineBoots,
parameters.EngineTime,
userName,
authenticationProvider.CleanDigest,
Privacy.Salt);
}

var pdu = new GetRequestPdu(
requestId,
variables);
Expand All @@ -151,6 +215,22 @@ public GetRequestMessage(VersionCode version, int messageId, int requestId, Octe
_bytes = this.PackMessage(null).ToBytes();
}

/// <summary>
/// Initializes a new instance of the <see cref="GetRequestMessage"/> class.
/// </summary>
/// <param name="version">The version.</param>
/// <param name="messageId">The message id.</param>
/// <param name="requestId">The request id.</param>
/// <param name="userName">Name of the user.</param>
/// <param name="contextName">Context name.</param>
/// <param name="variables">The variables.</param>
/// <param name="privacy">The privacy provider.</param>
/// <param name="maxMessageSize">Size of the max message.</param>
/// <param name="report">The report.</param>
public GetRequestMessage(VersionCode version, int messageId, int requestId, OctetString userName, OctetString contextName, IList<Variable> variables, IPrivacyProvider privacy, int maxMessageSize, ISnmpMessage report)
: this(version, messageId, requestId, userName, contextName, variables, privacy, maxMessageSize, report, SecurityModel.Usm)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="GetRequestMessage"/> class.
Expand Down
12 changes: 10 additions & 2 deletions SharpSnmpLib/Messaging/MessageFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,15 @@ private static ISnmpMessage ParseMessage(int first, Stream stream, UserRegistry
{
header = new Header(body[1]);
parameters = new SecurityParameters((OctetString)body[2]);
privacy = registry.Find(parameters.UserName);
if (header.SecurityModel == SecurityModel.Tsm)
{
privacy = new TsmPrivacyProvider(TsmAuthenticationProvider.Instance);
}
else
{
privacy = registry.Find(parameters.UserName);
}

if (privacy == null)
{
// handle decryption exception.
Expand Down Expand Up @@ -187,7 +195,7 @@ private static ISnmpMessage ParseMessage(int first, Stream stream, UserRegistry
throw new SnmpException(string.Format(CultureInfo.InvariantCulture, "invalid v3 packets scoped data: {0}", code));
}

if (!privacy.VerifyHash(version, header, parameters, body[3], body.GetLengthBytes()))
if (header.SecurityModel != SecurityModel.Tsm && !privacy.VerifyHash(version, header, parameters, body[3], body.GetLengthBytes()))
{
parameters.IsInvalid = true;
}
Expand Down
133 changes: 133 additions & 0 deletions SharpSnmpLib/Messaging/SecureDiscovery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Discovery type.
// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

/*
* Created by SharpDevelop.
* User: lextm
* Date: 5/24/2009
* Time: 11:56 AM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using Lextm.SharpSnmpLib.Security;
using System.Threading.Tasks;
using SharpSnmpLib.DTLS;
using DTLS;

namespace Lextm.SharpSnmpLib.Messaging
{
/// <summary>
/// Discovery class that participates in SNMP v3 discovery process.
/// </summary>
public sealed class SecureDiscovery
{
private readonly ISnmpMessage _discovery;
private static readonly UserRegistry Empty = new UserRegistry();
private static readonly SecurityParameters DefaultSecurityParameters =
new SecurityParameters(
OctetString.Empty,
Integer32.Zero,
Integer32.Zero,
OctetString.Empty,
OctetString.Empty,
OctetString.Empty);

/// <summary>
/// Initializes a new instance of the <see cref="Discovery"/> class.
/// </summary>
/// <param name="requestId">The request id.</param>
/// <param name="messageId">The message id.</param>
/// <param name="maxMessageSize">The max size of message.</param>
public SecureDiscovery(int messageId, int requestId, int maxMessageSize)
{
_discovery = new GetRequestMessage(
VersionCode.V3,
new Header(
new Integer32(messageId),
new Integer32(maxMessageSize),
Levels.Reportable),
DefaultSecurityParameters,
new Scope(
OctetString.Empty,
OctetString.Empty,
new GetRequestPdu(requestId, new List<Variable>())),
DefaultPrivacyProvider.DefaultPair,
null);
}

/// <summary>
/// Gets the response.
/// </summary>
/// <param name="timeout">The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.</param>
/// <param name="receiver">The receiver.</param>
/// <returns></returns>
public ReportMessage GetResponse(int timeout, IPEndPoint receiver, Client client)
{
if (receiver == null)
{
throw new ArgumentNullException(nameof(receiver));
}

return (ReportMessage)_discovery.GetSecureResponse(timeout, receiver, client, Empty);
}

/// <summary>
/// Gets the response.
/// </summary>
/// <param name="receiver">The receiver.</param>
/// <returns></returns>
public async Task<ReportMessage> GetResponseAsync(IPEndPoint receiver)
{
if (receiver == null)
{
throw new ArgumentNullException(nameof(receiver));
}

using (var socket = receiver.GetSocket())
{
return (ReportMessage)await _discovery.GetResponseAsync(receiver, Empty, socket).ConfigureAwait(false);
}
}

/// <summary>
/// Converts to the bytes.
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
return _discovery.ToBytes();
}

/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "discovery class: message id: {0}; request id: {1}", _discovery.MessageId(), _discovery.RequestId());
}
}
}
Loading