HOWTO在同一个TcpListener中使用SslStream和NegotiateStream。 [英] HOWTO Use SslStream and NegotiateStream in same TcpListener.

查看:59
本文介绍了HOWTO在同一个TcpListener中使用SslStream和NegotiateStream。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请帮忙,

我正在尝试将NTLM添加到我的网络服务器应用程序(基于TcpListener),同时拥有SSL和NTLM。

我成功添加了SSL,但现在我需要NTLM,遗憾的是,没有关于如何同时使用这两者的文档。

此外,我甚至没有找到干净的样本即使您没有SSL,如何应用NTLM。

I am trying to add NTLM to my web server app, which is based off TcpListener, to have both SSL and NTLM.
I've succeded with adding SSL, but now I need NTLM, and sadly, there is no documentation on how to have both.
Furthermore, I've not found a clean sample on even how to apply the NTLM, even if you do not have SSL.

为了使问题成为焦点,下面我从我的服务器中提取了代码,无论是否使用SSL都可以使用gret。但它缺少NTLM,我不知道该怎么做才能添加它。

To keep the issue in focus, below I have extracted code from my server, which works greate with and without SSL. But it is missing the NTLM, and I do not know what to do to add it in.

请帮助我在2个点找到代码的答案评论://什么我们在这里做什么?

Please help me get the answer to the code at the 2 spots commented with: // What do we do here???





using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace MyNameSpace
{
  /*----------------------------------------------------------------------------------------*\
  |                                                                                          |
  \*----------------------------------------------------------------------------------------*/

  static class Program
  {
    /*----------------------------------------------------------------------------------------*\
    |                                                                                          |
    \*----------------------------------------------------------------------------------------*/

    static void Main()
    {
      string csHostName = Dns.GetHostName().Trim();
      byte[] zbCertificate;
      zbCertificate = File.ReadAllBytes("Path to some SSL Certificate");
      SslCertificate srcCertificate = new SslCertificate
      {
        Type = SslCertificate.CertificateTypes.X509Certificate2,
        Data = new X509Certificate2
        (
          zbCertificate, "Encryption String to work with SSL Certificate"
        ),
        ClientCertificateRequired = false,
        CheckCertificateRevocation = false
      };

      HttpServer HttpServer_MyServer = new HttpServer
      {
        HostName = HostName,
        Port = 50000,
        Certificate = srcCertificate,
        ReuseAddress = bReuseAddress
      };
      HttpServer_MyServer.RunListener();
    }
  }

  /*----------------------------------------------------------------------------------------*\
  |                                                                                          |
  \*----------------------------------------------------------------------------------------*/

  public class HttpServer
  {
    public string HostName;
    public int Port = 50000;
    public TcpListener TcpListener_This;
    public bool ReuseAddress { get; set; } = false;
    public SslCertificate Certificate { get; set; } = null;

    /*----------------------------------------------------------------------------------------*\
    |                                                                                          |
    \*----------------------------------------------------------------------------------------*/

    public void RunListener()
    {
      IPAddress ip = Dns.GetHostAddresses(HostName).Where
      (
        address => address.AddressFamily == AddressFamily.InterNetwork
      ).First();
      TcpListener_This = new TcpListener(ip, (int) Port);
      bool bIsActive = true;

      while (bIsActive)
      {
        TcpClient TcpClient_This = TcpListener_This.AcceptTcpClient();
        HttpProcessor HttpProcessor_This = new HttpProcessor(TcpClient_This, this);
        Thread Thread_That = new Thread(new ThreadStart(HttpProcessor_This.Process));

        if (!ThreadApartmentState.IsNull())
        {
          Thread_That.SetApartmentState((ApartmentState) ThreadApartmentState);
        }

        Thread_That.Start();
        Thread.Sleep(1);
      }
    }
  }

  /*----------------------------------------------------------------------------------------*\
  |                                                                                          |
  \*----------------------------------------------------------------------------------------*/

  public class HttpProcessor
  {
    public TcpClient Client { get; set; } = null;
    public HttpServer Server { get; set; }
    public Stream Stream_Input;
    public SslStream SslStream_Input = null;
    public BinaryWriter BinaryWriter_Output;

    public HttpProcessor(TcpClient TcpClient_Param, HttpServer HttpServer_Param)
    {
      Client = TcpClient_Param;
      Server = HttpServer_Param;
    }

    /*------------------------------------------------------------------------------------------*\
    |                                                                                            |
    \*------------------------------------------------------------------------------------------*/

    public override void Process()
    {
      // Note, ultimately NTLM and its negotiation/handhake goes to functionality in SECUR32.dll.
      // The SECUR32.dll function AcceptSecurityContext function in particular handles the
      // process. This process is possibly wrapped by System.Net.Security.NegotiateStream, but
      // below
      //
      // What do we do here, to get an System.Security.Principal.WindowsIdentity object, that
      // we can use to impersonate the NTLM authenitcated user.

      WindowsIdentity wiAuthenticatedUser = null;

      if (Server.Certificate != null)
      {
        SslStream_Input = new SslStream(Client.GetStream());
        SslStream_Input.AuthenticateAsServer
        (
          Certificate.X509Certificate,
          Certificate.ClientCertificateRequired,
          Certificate.SslProtocols,
          Certificate.CheckCertificateRevocation
        );
        Stream_Input = new BufferedStream(SslStream_Input);
        BinaryWriter_Output = new BinaryWriter(SslStream_Input);

        // MISSING NTLM AUTHENTICATION WITH SSL....
        //
        // What do we do here???
        // How do we get wiAuthenticatedUser populated...
        //
        // This point would do the NTLM handshake like above, but the trick here is that the SSL
        // stream has had to kick in 1st, to deal with the SSL encryption.
        //
        // Note, this sample code works, up to this point for SSL.
        //
        // Something extra needs to happen here, to ensure the SSL Stream is worked-with, qand not broken.
      }
      else
      {
        Stream_Input = new BufferedStream(Client.GetStream());
        BinaryWriter_Output = new BinaryWriter(new BufferedStream(Client.GetStream()));

        // MISSING NTLM AUTHENTICATION WITH NO SSL....
        //
        // What do we do here???
        // How do we get wiAuthenticatedUser populated...
        //
        // Note, NTLM has a handshake process, which will require returning 401, and waiting
        // for the client to follow the negotiation handshake, with possibly, challenges from the
        // server to the client.
      }

      // At this point, we have a Input and Output stream, we can use to get all HTTP parameters
      // and any HTTP posted data, process as desired, and return HTTP response as desired.
      //
      // For this demo, we'll just return HTTP 200.

      BinaryWriter_Output.Write("HTTP/1.0 200 OK\n");
      BinaryWriter_Output.Write("Content-Type: " + content_type + "\n");
      BinaryWriter_Output.Write("Connection: close\n");
      BinaryWriter_Output.Write("\n");
    }
  }

  /*----------------------------------------------------------------------------------------*\
  |                                                                                          |
  \*----------------------------------------------------------------------------------------*/

  public class SslCertificate
  {
    /*----------------------------------------------------------------------------------------*\
    |                                                                                          |
    \*----------------------------------------------------------------------------------------*/

    public enum CertificateTypes
    {
      [CSC.Names(new string[] { "X509Certificate" })]
      X509Certificate,

      [CSC.Names(new string[] { "X509Certificate2" })]
      X509Certificate2
    }

    public CertificateTypes Type { get; set; }
    public object Data { get; set; }
    public bool ClientCertificateRequired { get; set; } = true;
    public SslProtocols SslProtocols { get; set; } =  SslProtocols.Default;
    public bool CheckCertificateRevocation { get; set; } = true;
    public X509Certificate X509Certificate
    {
      get
      {
        if (Data.IsNull()) return null;
        X509Certificate xcerRET = null;
        ML.IGNORE(() => xcerRET = (X509Certificate) Data);
        return xcerRET;
      }
    }
  }
}




推荐答案

您好JSB,

感谢您在此发帖。

对于您的问题,我能否知道您想要的原因?用它们两个?根据我的搜索,我找不到两者的示例。  NegotiateStream是AuthenticatedStream的实现(如SslStream所示)。它是类似的。 

For your question, could I know why you want to use both of them? Based on my search, I do not find the example with both of them. NegotiateStream is an implementation of AuthenticatedStream (as SslStream is). It is similar. 

如果您想要同时制作它们,请尝试制作两个示例,然后选择选择您要使用的示例。

If you want make both of them, try to make two examples and then make a choice to choose which one you want to use.

最诚挚的问候,

Wendy


这篇关于HOWTO在同一个TcpListener中使用SslStream和NegotiateStream。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆