/// <summary> /// Encode a PDU to a binary stream. Then send the stream. /// </summary> /// <param name="pdu">A specified type of a PDU. This argument cannot be null. /// If it is null, ArgumentNullException will be thrown.</param> /// <exception cref="System.ArgumentNullException">Thrown when the input parameter is null.</exception> public void SendPdu(KerberosPdu pdu) { if (pdu == null) { throw new ArgumentNullException("pdu"); } if (UseProxy) { Debug.Assert(ProxyClient != null, "Proxy Client should be set when using proxy."); //temporarily change the tranpsort type to TCP, since all proxy messages are TCP format. var oriTransportType = Context.TransportType; Context.TransportType = TransportType.TCP; KDCProxyMessage message = ProxyClient.MakeProxyMessage(pdu); //send proxy message ProxyClient.SendProxyRequest(message); //restore the original transport type Context.TransportType = oriTransportType; } else { this.Connect(); kdcTransport.SendPacket(pdu); } }
/// <summary> /// Expect to receive a PDU of any type from the remote host. /// </summary> /// <param name="timeout">Timeout of receiving PDU.</param> /// <returns>The expected PDU.</returns> /// <exception cref="System.TimeoutException">Thrown when the timeout parameter is negative.</exception> public KerberosPdu ExpectPdu(TimeSpan timeout, Type pduType = null) { this.expectedPduType = pduType; KerberosPdu pdu = null; if (UseProxy) { Debug.Assert(ProxyClient != null, "Proxy Client should be set when using proxy."); int consumedLength = 0; int expectedLength = 0; if (ProxyClient.Error == KKDCPError.STATUS_SUCCESS) { KDCProxyMessage message = ProxyClient.GetProxyResponse(); //temporarily change the tranpsort type to TCP, since all proxy messages are TCP format. var oriTransportType = Context.TransportType; Context.TransportType = TransportType.TCP; //get proxy message pdu = getExpectedPduFromBytes(message.Message.kerb_message.ByteArrayValue, out consumedLength, out expectedLength); //restore the original transport type Context.TransportType = oriTransportType; } } else { if (timeout.TotalMilliseconds < 0) { throw new TimeoutException(KerberosConstValue.TIMEOUT_EXCEPTION); } TransportEvent eventPacket = kdcTransport.ExpectTransportEvent(timeout); pdu = (KerberosPdu)eventPacket.EventObject; this.DisConnect(); } return(pdu); }
/// <summary> /// Get the proxy message replied from the server. /// NULL will be returned if not response is received. /// </summary> /// <returns>The responded proxy message</returns> public KDCProxyMessage GetProxyResponse() { if (responseBytes == null) { return(null); } KDCProxyMessage message = new KDCProxyMessage(); message.FromBytes(responseBytes); return(message); }
/// <summary> /// Send the specified proxy message using https. /// </summary> /// <param name="message"></param> public void SendProxyRequest(KDCProxyMessage message) { try { //create web request HttpRequestMessage request = new HttpRequestMessage() { RequestUri = new Uri(config.KKDCPServerURL), Method = HttpMethod.Post, Version = HttpVersion.Version11, Content = new ByteArrayContent(message.ToBytes()) }; request.Headers.Connection.Add("keep-alive"); request.Headers.UserAgent.ParseAdd("Kerberos/1.0"); var clientHandler = new HttpClientHandler(); if (config.TlsClientCertificate != null) { clientHandler.ClientCertificates.Add(config.TlsClientCertificate); } HttpClient client = new HttpClient(clientHandler); //send message HttpResponseMessage response = client.SendAsync(request).Result; //get response if (response.StatusCode == HttpStatusCode.Forbidden) { //HTTP 403 error received, set ERROR to STATUS_AUTHENTICATION_FIREWALL_FAILED. Error = KKDCPError.STATUS_AUTHENTICATION_FIREWALL_FAILED; return; } responseBytes = response.Content.ReadAsByteArrayAsync().Result; } catch (AggregateException ex) { foreach (var e in ex.Flatten().InnerExceptions) { if (e is HttpRequestException) { //server dropped the TCP connection //set Error to STATUS_NO_LOGON_SERVERS Error = KKDCPError.STATUS_NO_LOGON_SERVERS; } else { throw; } } } }
/// <summary> /// Send the specified proxy message using https. /// </summary> /// <param name="message"></param> public void SendProxyRequest(KDCProxyMessage message) { //create web request HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(new Uri(config.KKDCPServerURL)); webRequest.KeepAlive = config.HttpKeepAlive; webRequest.Method = "POST"; webRequest.ProtocolVersion = config.HttpVersion; webRequest.CachePolicy = config.HttpCachePolicy; webRequest.UserAgent = config.HttpUserAgent; webRequest.Timeout = config.HttpRequestTimeout; if (config.TlsClientCertificate != null) { webRequest.ClientCertificates.Add(config.TlsClientCertificate); } //send message byte[] data = message.ToBytes(); webRequest.ContentLength = data.Length; Stream postData = webRequest.GetRequestStream(); postData.Write(data, 0, data.Length); postData.Close(); //get response try { HttpWebResponse response = (System.Net.HttpWebResponse)webRequest.GetResponse(); if (response.StatusCode == HttpStatusCode.Forbidden) { //HTTP 403 error received, set ERROR to STATUS_AUTHENTICATION_FIREWALL_FAILED. Error = KKDCPError.STATUS_AUTHENTICATION_FIREWALL_FAILED; return; } using (Stream responseDataSteam = response.GetResponseStream()) { using (MemoryStream ms = new MemoryStream()) { responseDataSteam.CopyTo(ms); responseBytes = ms.ToArray(); } } response.Close(); } catch (WebException) { //server dropped the TCP connection //set Error to STATUS_NO_LOGON_SERVERS Error = KKDCPError.STATUS_NO_LOGON_SERVERS; } }
/// <summary> /// Wrap the KerberosPdu provided into proxy message. /// </summary> /// <param name="pdu">the specified KerberosPdu to be wrapped</param> public KDCProxyMessage MakeProxyMessage(KerberosPdu pdu) { //prepare proxy message KDCProxyMessage message = new KDCProxyMessage(pdu); if (!string.IsNullOrEmpty(TargetDomain)) { message.TargetDomain = TargetDomain; } if (DCLocatorHint.HasValue) { message.DCLocatorHint = DCLocatorHint.Value; } return(message); }