- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
.NET 的 SslStream
类在关闭连接之前不会发送 close_notify
警报。
如何手动发送 close_notify
警报?
最佳答案
感谢您提出这个问题。它为我指明了正确的方向,即 .Net 中存在一个我很少想到的错误。
我在编写 FTPS 服务器和 Filezilla(或可能是 GnuTLS)客户端的实现时遇到了这个问题,客户端提示“gnutls_record_recv 中的 GnuTLS 错误 -110:TLS 连接未正确终止”。我认为这是 SslStream 实现中的一个相当大的缺点。
所以我最终写了一个包装器,它在关闭流之前发送这个警报:
public class FixedSslStream : SslStream {
public FixedSslStream(Stream innerStream)
: base(innerStream) {
}
public FixedSslStream(Stream innerStream, bool leaveInnerStreamOpen)
: base(innerStream, leaveInnerStreamOpen) {
}
public FixedSslStream(Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback)
: base(innerStream, leaveInnerStreamOpen, userCertificateValidationCallback) {
}
public FixedSslStream(Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback)
: base(innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, userCertificateSelectionCallback) {
}
public FixedSslStream(Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback, EncryptionPolicy encryptionPolicy)
: base(innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, userCertificateSelectionCallback, encryptionPolicy) {
}
public override void Close() {
try {
SslDirectCall.CloseNotify(this);
} finally {
base.Close();
}
}
}
下面的代码是为了让它工作(这段代码要求汇编是“不安全的”):
public unsafe static class SslDirectCall {
public static void CloseNotify(SslStream sslStream) {
if (sslStream.IsAuthenticated) {
bool isServer = sslStream.IsServer;
byte[] result;
int resultSz;
var asmbSystem = typeof(System.Net.Authorization).Assembly;
int SCHANNEL_SHUTDOWN = 1;
var workArray = BitConverter.GetBytes(SCHANNEL_SHUTDOWN);
var sslstate = ReflectUtil.GetField(sslStream, "_SslState");
var context = ReflectUtil.GetProperty(sslstate, "Context");
var securityContext = ReflectUtil.GetField(context, "m_SecurityContext");
var securityContextHandleOriginal = ReflectUtil.GetField(securityContext, "_handle");
NativeApi.SSPIHandle securityContextHandle = default(NativeApi.SSPIHandle);
securityContextHandle.HandleHi = (IntPtr)ReflectUtil.GetField(securityContextHandleOriginal, "HandleHi");
securityContextHandle.HandleLo = (IntPtr)ReflectUtil.GetField(securityContextHandleOriginal, "HandleLo");
var credentialsHandle = ReflectUtil.GetField(context, "m_CredentialsHandle");
var credentialsHandleHandleOriginal = ReflectUtil.GetField(credentialsHandle, "_handle");
NativeApi.SSPIHandle credentialsHandleHandle = default(NativeApi.SSPIHandle);
credentialsHandleHandle.HandleHi = (IntPtr)ReflectUtil.GetField(credentialsHandleHandleOriginal, "HandleHi");
credentialsHandleHandle.HandleLo = (IntPtr)ReflectUtil.GetField(credentialsHandleHandleOriginal, "HandleLo");
int bufferSize = 1;
NativeApi.SecurityBufferDescriptor securityBufferDescriptor = new NativeApi.SecurityBufferDescriptor(bufferSize);
NativeApi.SecurityBufferStruct[] unmanagedBuffer = new NativeApi.SecurityBufferStruct[bufferSize];
fixed (NativeApi.SecurityBufferStruct* ptr = unmanagedBuffer)
fixed (void* workArrayPtr = workArray) {
securityBufferDescriptor.UnmanagedPointer = (void*)ptr;
unmanagedBuffer[0].token = (IntPtr)workArrayPtr;
unmanagedBuffer[0].count = workArray.Length;
unmanagedBuffer[0].type = NativeApi.BufferType.Token;
NativeApi.SecurityStatus status;
status = (NativeApi.SecurityStatus)NativeApi.ApplyControlToken(ref securityContextHandle, securityBufferDescriptor);
if (status == NativeApi.SecurityStatus.OK) {
unmanagedBuffer[0].token = IntPtr.Zero;
unmanagedBuffer[0].count = 0;
unmanagedBuffer[0].type = NativeApi.BufferType.Token;
NativeApi.SSPIHandle contextHandleOut = default(NativeApi.SSPIHandle);
NativeApi.ContextFlags outflags = NativeApi.ContextFlags.Zero;
long ts = 0;
var inflags = NativeApi.ContextFlags.SequenceDetect |
NativeApi.ContextFlags.ReplayDetect |
NativeApi.ContextFlags.Confidentiality |
NativeApi.ContextFlags.AcceptExtendedError |
NativeApi.ContextFlags.AllocateMemory |
NativeApi.ContextFlags.InitStream;
if (isServer) {
status = (NativeApi.SecurityStatus)NativeApi.AcceptSecurityContext(ref credentialsHandleHandle, ref securityContextHandle, null,
inflags, NativeApi.Endianness.Native, ref contextHandleOut, securityBufferDescriptor, ref outflags, out ts);
} else {
status = (NativeApi.SecurityStatus)NativeApi.InitializeSecurityContextW(ref credentialsHandleHandle, ref securityContextHandle, null,
inflags, 0, NativeApi.Endianness.Native, null, 0, ref contextHandleOut, securityBufferDescriptor, ref outflags, out ts);
}
if (status == NativeApi.SecurityStatus.OK) {
byte[] resultArr = new byte[unmanagedBuffer[0].count];
Marshal.Copy(unmanagedBuffer[0].token, resultArr, 0, resultArr.Length);
Marshal.FreeCoTaskMem(unmanagedBuffer[0].token);
result = resultArr;
resultSz = resultArr.Length;
} else {
throw new InvalidOperationException(string.Format("AcceptSecurityContext/InitializeSecurityContextW returned [{0}] during CloseNotify.", status));
}
} else {
throw new InvalidOperationException(string.Format("ApplyControlToken returned [{0}] during CloseNotify.", status));
}
}
var innerStream = (Stream)ReflectUtil.GetProperty(sslstate, "InnerStream");
innerStream.Write(result, 0, resultSz);
}
}
}
使用的 Windows API:
public unsafe static class NativeApi {
internal enum BufferType {
Empty,
Data,
Token,
Parameters,
Missing,
Extra,
Trailer,
Header,
Padding = 9,
Stream,
ChannelBindings = 14,
TargetHost = 16,
ReadOnlyFlag = -2147483648,
ReadOnlyWithChecksum = 268435456
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SSPIHandle {
public IntPtr HandleHi;
public IntPtr HandleLo;
public bool IsZero {
get {
return this.HandleHi == IntPtr.Zero && this.HandleLo == IntPtr.Zero;
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal void SetToInvalid() {
this.HandleHi = IntPtr.Zero;
this.HandleLo = IntPtr.Zero;
}
public override string ToString() {
return this.HandleHi.ToString("x") + ":" + this.HandleLo.ToString("x");
}
}
[StructLayout(LayoutKind.Sequential)]
internal class SecurityBufferDescriptor {
public readonly int Version;
public readonly int Count;
public unsafe void* UnmanagedPointer;
public SecurityBufferDescriptor(int count) {
this.Version = 0;
this.Count = count;
this.UnmanagedPointer = null;
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct SecurityBufferStruct {
public int count;
public BufferType type;
public IntPtr token;
public static readonly int Size = sizeof(SecurityBufferStruct);
}
internal enum SecurityStatus {
OK,
ContinueNeeded = 590610,
CompleteNeeded,
CompAndContinue,
ContextExpired = 590615,
CredentialsNeeded = 590624,
Renegotiate,
OutOfMemory = -2146893056,
InvalidHandle,
Unsupported,
TargetUnknown,
InternalError,
PackageNotFound,
NotOwner,
CannotInstall,
InvalidToken,
CannotPack,
QopNotSupported,
NoImpersonation,
LogonDenied,
UnknownCredentials,
NoCredentials,
MessageAltered,
OutOfSequence,
NoAuthenticatingAuthority,
IncompleteMessage = -2146893032,
IncompleteCredentials = -2146893024,
BufferNotEnough,
WrongPrincipal,
TimeSkew = -2146893020,
UntrustedRoot,
IllegalMessage,
CertUnknown,
CertExpired,
AlgorithmMismatch = -2146893007,
SecurityQosFailed,
SmartcardLogonRequired = -2146892994,
UnsupportedPreauth = -2146892989,
BadBinding = -2146892986
}
[Flags]
internal enum ContextFlags {
Zero = 0,
Delegate = 1,
MutualAuth = 2,
ReplayDetect = 4,
SequenceDetect = 8,
Confidentiality = 16,
UseSessionKey = 32,
AllocateMemory = 256,
Connection = 2048,
InitExtendedError = 16384,
AcceptExtendedError = 32768,
InitStream = 32768,
AcceptStream = 65536,
InitIntegrity = 65536,
AcceptIntegrity = 131072,
InitManualCredValidation = 524288,
InitUseSuppliedCreds = 128,
InitIdentify = 131072,
AcceptIdentify = 524288,
ProxyBindings = 67108864,
AllowMissingBindings = 268435456,
UnverifiedTargetName = 536870912
}
internal enum Endianness {
Network,
Native = 16
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport("secur32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern int ApplyControlToken(ref SSPIHandle contextHandle, [In] [Out] SecurityBufferDescriptor outputBuffer);
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport("secur32.dll", ExactSpelling = true, SetLastError = true)]
internal unsafe static extern int AcceptSecurityContext(ref SSPIHandle credentialHandle, ref SSPIHandle contextHandle, [In] SecurityBufferDescriptor inputBuffer, [In] ContextFlags inFlags, [In] Endianness endianness, ref SSPIHandle outContextPtr, [In] [Out] SecurityBufferDescriptor outputBuffer, [In] [Out] ref ContextFlags attributes, out long timeStamp);
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport("secur32.dll", ExactSpelling = true, SetLastError = true)]
internal unsafe static extern int InitializeSecurityContextW(ref SSPIHandle credentialHandle, ref SSPIHandle contextHandle, [In] byte* targetName, [In] ContextFlags inFlags, [In] int reservedI, [In] Endianness endianness, [In] SecurityBufferDescriptor inputBuffer, [In] int reservedII, ref SSPIHandle outContextPtr, [In] [Out] SecurityBufferDescriptor outputBuffer, [In] [Out] ref ContextFlags attributes, out long timeStamp);
}
反射实用程序:
public static class ReflectUtil {
public static object GetField(object obj, string fieldName) {
var tp = obj.GetType();
var info = GetAllFields(tp)
.Where(f => f.Name == fieldName).Single();
return info.GetValue(obj);
}
public static void SetField(object obj, string fieldName, object value) {
var tp = obj.GetType();
var info = GetAllFields(tp)
.Where(f => f.Name == fieldName).Single();
info.SetValue(obj, value);
}
public static object GetStaticField(Assembly assembly, string typeName, string fieldName) {
var tp = assembly.GetType(typeName);
var info = GetAllFields(tp)
.Where(f => f.IsStatic)
.Where(f => f.Name == fieldName).Single();
return info.GetValue(null);
}
public static object GetProperty(object obj, string propertyName) {
var tp = obj.GetType();
var info = GetAllProperties(tp)
.Where(f => f.Name == propertyName).Single();
return info.GetValue(obj, null);
}
public static object CallMethod(object obj, string methodName, params object[] prm) {
var tp = obj.GetType();
var info = GetAllMethods(tp)
.Where(f => f.Name == methodName && f.GetParameters().Length == prm.Length).Single();
object rez = info.Invoke(obj, prm);
return rez;
}
public static object NewInstance(Assembly assembly, string typeName, params object[] prm) {
var tp = assembly.GetType(typeName);
var info = tp.GetConstructors()
.Where(f => f.GetParameters().Length == prm.Length).Single();
object rez = info.Invoke(prm);
return rez;
}
public static object InvokeStaticMethod(Assembly assembly, string typeName, string methodName, params object[] prm) {
var tp = assembly.GetType(typeName);
var info = GetAllMethods(tp)
.Where(f => f.IsStatic)
.Where(f => f.Name == methodName && f.GetParameters().Length == prm.Length).Single();
object rez = info.Invoke(null, prm);
return rez;
}
public static object GetEnumValue(Assembly assembly, string typeName, int value) {
var tp = assembly.GetType(typeName);
object rez = Enum.ToObject(tp, value);
return rez;
}
private static IEnumerable<FieldInfo> GetAllFields(Type t) {
if (t == null)
return Enumerable.Empty<FieldInfo>();
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.DeclaredOnly;
return t.GetFields(flags).Concat(GetAllFields(t.BaseType));
}
private static IEnumerable<PropertyInfo> GetAllProperties(Type t) {
if (t == null)
return Enumerable.Empty<PropertyInfo>();
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.DeclaredOnly;
return t.GetProperties(flags).Concat(GetAllProperties(t.BaseType));
}
private static IEnumerable<MethodInfo> GetAllMethods(Type t) {
if (t == null)
return Enumerable.Empty<MethodInfo>();
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance |
BindingFlags.DeclaredOnly;
return t.GetMethods(flags).Concat(GetAllMethods(t.BaseType));
}
}
我在编写与非托管环境的可靠交互方面没有经验,所以我希望有人可以看看并解决问题(并可能使其“安全”)。
关于.NET SslStream 没有正确关闭 TLS 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/237807/
是否可以使用 OpenSSL 或其他工具通过 TLS 建立 TLS 连接? 如果可能,每个级别的证书是否需要不同? 最佳答案 这在理论上应该工作得很好,但我不能确定 OpenSSL 或其他东西是否会轻
在我的 java 代码中,我正在使用命令创建 SSL 上下文的一个实例 SSLContext ctx = SSLContext.getInstance("TLS"); 但是在我的 tomcat 服务器
在我的 java 代码中,我正在使用命令创建一个 SSL 上下文实例 SSLContext ctx = SSLContext.getInstance("TLS"); 但在我的 tomcat 服务器中,
范围:这是一个具有一个 channel 的网络,该 channel 由 3 个组织组成,每个组织 1 个 anchor 节点,每个组织 1 个 CA 和每个组织 1 个 MSP。 我在我的 Hyper
无法找到用于在 iis 上启用/禁用 tls 的特定设置。启用/禁用 ssl 是否与启用/禁用 tls 相同? 我浏览了一些博客,发现 SSL 是 TLS 的前身,旧版本的 SSL 已被弃用。但我无法
最近,我一直在为基于物联网的项目评估不同的 API 网关 (API GW) 选项。这样做的目的是找到一个足够好的解决方案来执行设备和 API GW 的相互 TLS (mTLS) 身份验证。 我尝试过的
几个月来,我的 Web 应用程序在不同版本的 IE/Firefox/Chrome 上运行良好。我的应用程序在 IIS 10.0 上运行。当我从 Windows 7 框 (IE 11.0.***) 中点
我有一个在 Java 7 上运行的 HTTPS 网络服务。我需要进行更改,以便此服务仅接受 TLS1.2 连接并拒绝 SSL3、TLS1.0 和 TLS1.1。 我添加了以下 Java 参数,使 TL
我在资源管理器不显示网站时遇到问题:“无法显示此页面。在高级设置中打开 TLS 1.0、TLS 1.1 和 TLS 1.2”。 我在 chrome 中调试了证书并说“连接是使用 aes_128_cbc
我正在与 5 个订购者、1 个组织和 2 个同行建立我的网络。还有 1 个 cli 和 1 个 ca。 我从 1 个排序者扩展到 5 个实现 Raft 的排序者。这就是为什么我想扩展我的网络并对多个对
当k8s集群开启了TLS认证后,每个节点的kubelet组件都要使用由kube-apiserver的CA签发的有效证书才能与kube-apiserver通信;当节点非常多的时候,为每个节点都单独签署证
我正在尝试使用 pjsip 安装中的 pjsua 程序在两个虚拟机之间进行安全调用。我通过以下方式在每个节点上启动程序: pjsua-x86_64-unknown-linux-gnu --use-tl
我开发的软件应用程序使用 gRPC 在客户端和服务器之间建立双向流。 我只在 java 中寻找类似于这张票的答案的东西:How to enable server side SSL for gRPC?
我正在尝试调试与 TLS 相关的问题。TLS 在两个应用程序客户端 A 和服务器 B 之间设置。A 和 B 都交换了证书,我已经验证证书具有正确的扩展名,并且还通过其根 CA 成功验证。叶证书的根 C
“Java 1.7 TLS 1.1 服务器”和“Java 1.8 客户端”之间的 SSL/TLS 握手在我的环境中失败,服务器端出现以下异常: java.security.NoSuchAlgorith
我正在尝试了解 Docker ,但我不断收到神秘的(对我而言)错误消息。 可能最简单的例子是尝试打印我安装的 Docker 版本: $ sudo docker version Client versi
这是我第一次使用 Amazon Lighsail、Wordpress Multisite、Bitnami甚至使用 Let's Encrypt;现在似乎一切正常,除了我的虚拟主机文件中的 SSL 指令。
我有一个 MariaDB "M"。在同一台机器上有一个应用程序“A”,它可以访问它。在不同的服务器上,另一个应用程序“B”也在访问它。 现在我想在 MariaDB 上启用 TLS 以保护连接 B ->
我正在寻找通过代理连接到一些 HTTPS/TLS 站点,其中到代理本身的连接也是通过 HTTPS/TLS 建立的,来自一个高度依赖请求的 python 应用程序。 urllib3(因此 request
现在我正在努力改变 EMQtt 和 Erlang MQTT 代理,以便我可以使用预共享 key 而不是非对称方法执行 TLS 握手。 到目前为止,我几乎遍历了源代码中的每个文件,但找不到任何加密函数。
我是一名优秀的程序员,十分优秀!