public override HttpStatusCode ValidateAuthentication(HttpListenerContext listenerContext) { HttpStatusCode forbidden = base.ValidateAuthentication(listenerContext); if ((forbidden == HttpStatusCode.OK) && this.RequireClientCertificate) { HttpListenerRequest request = listenerContext.Request; X509Certificate2 clientCertificate = request.GetClientCertificate(); if (clientCertificate == null) { if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, 0x40010, System.ServiceModel.SR.GetString("TraceCodeHttpsClientCertificateNotPresent"), new HttpListenerRequestTraceRecord(listenerContext.Request), this, null); } forbidden = HttpStatusCode.Forbidden; } else if ((request.ClientCertificateError != 0) && !this.useCustomClientCertificateVerification) { if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, 0x4000f, System.ServiceModel.SR.GetString("TraceCodeHttpsClientCertificateInvalid"), new HttpListenerRequestTraceRecord(listenerContext.Request), this, null); } forbidden = HttpStatusCode.Forbidden; } if ((forbidden != HttpStatusCode.OK) && (AuditLevel.Failure == (base.AuditBehavior.MessageAuthenticationAuditLevel & AuditLevel.Failure))) { string message = System.ServiceModel.SR.GetString("HttpAuthenticationFailed", new object[] { base.AuthenticationScheme, forbidden }); Exception exception = DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(message)); base.WriteAuditEvent(AuditLevel.Failure, (clientCertificate != null) ? System.ServiceModel.Security.SecurityUtils.GetCertificateId(clientCertificate) : string.Empty, exception); } } return(forbidden); }
private Request ConvertRequestToNancyRequest(HttpListenerRequest request) { Uri uri1 = _baseUriList.FirstOrDefault(uri => uri.IsCaseInsensitiveBaseOf(request.Url)); if (uri1 == null) { throw new InvalidOperationException(string.Format("Unable to locate base URI for request: {0}", request.Url)); } long expectedRequestLength = GetExpectedRequestLength(request.Headers.ToDictionary()); string str = uri1.MakeAppLocalPath(request.Url); Url url1 = new Url(); url1.Scheme = (request.Url.Scheme); url1.HostName = (request.Url.Host); url1.Port = (request.Url.IsDefaultPort ? new int?() : request.Url.Port); url1.BasePath = (uri1.AbsolutePath.TrimEnd('/')); url1.Path = (HttpUtility.UrlDecode(str)); url1.Query = (request.Url.Query); Url url2 = url1; byte[] numArray = null; if (_configuration.EnableClientCertificates) { X509Certificate2 clientCertificate = request.GetClientCertificate(); if (clientCertificate != null) { numArray = clientCertificate.RawData; } } return(new Request(request.HttpMethod, url2, RequestStream.FromStream(request.InputStream, expectedRequestLength, false), request.Headers.ToDictionary(), request.RemoteEndPoint != null ? request.RemoteEndPoint.Address.ToString() : null, numArray)); }
public async Task GetClientCertificate_NoCertificate_ReturnsNull() { HttpListenerRequest request = await GetRequest("POST", null, null); Assert.Null(request.GetClientCertificate()); Assert.Equal(0, request.ClientCertificateError); }
private string Certificate(HttpListenerRequest arg) { X509Certificate2 certificate = arg.GetClientCertificate(); if (certificate != null) { return(JsonConvert.SerializeObject("Certificate Thumbprint :" + certificate.Thumbprint)); } else { return(JsonConvert.SerializeObject("No Certificate Provided")); } }
private Request ConvertRequestToNancyRequest(HttpListenerRequest request) { var baseUri = this.GetBaseUri(request); if (baseUri == null) { throw new InvalidOperationException(string.Format("Unable to locate base URI for request: {0}", request.Url)); } var expectedRequestLength = GetExpectedRequestLength(request.Headers.ToDictionary()); var relativeUrl = baseUri.MakeAppLocalPath(request.Url); var nancyUrl = new Url { Scheme = request.Url.Scheme, HostName = request.Url.Host, Port = request.Url.IsDefaultPort ? null : (int?)request.Url.Port, BasePath = baseUri.AbsolutePath.TrimEnd('/'), Path = HttpUtility.UrlDecode(relativeUrl), Query = request.Url.Query, }; byte[] certificate = null; if (this.configuration.EnableClientCertificates) { var x509Certificate = request.GetClientCertificate(); if (x509Certificate != null) { certificate = x509Certificate.RawData; } } // NOTE: For HTTP/2 we want fieldCount = 1, // otherwise (HTTP/1.0 and HTTP/1.1) we want fieldCount = 2 var fieldCount = request.ProtocolVersion.Major == 2 ? 1 : 2; var protocolVersion = string.Format("HTTP/{0}", request.ProtocolVersion.ToString(fieldCount)); return(new Request( request.HttpMethod, nancyUrl, RequestStream.FromStream(request.InputStream, expectedRequestLength, StaticConfiguration.DisableRequestStreamSwitching ?? false), request.Headers.ToDictionary(), (request.RemoteEndPoint != null) ? request.RemoteEndPoint.Address.ToString() : null, certificate, protocolVersion)); }
private Request ConvertRequestToNancyRequest(HttpListenerRequest request) { var baseUri = this.baseUriList.FirstOrDefault(uri => uri.IsCaseInsensitiveBaseOf(request.Url)); if (baseUri == null) { throw new InvalidOperationException(String.Format("Unable to locate base URI for request: {0}", request.Url)); } var expectedRequestLength = GetExpectedRequestLength(request.Headers.ToDictionary()); var relativeUrl = baseUri.MakeAppLocalPath(request.Url); var nancyUrl = new Url { Scheme = request.Url.Scheme, HostName = request.Url.Host, Port = request.Url.IsDefaultPort ? null : (int?)request.Url.Port, BasePath = baseUri.AbsolutePath.TrimEnd('/'), Path = HttpUtility.UrlDecode(relativeUrl), Query = request.Url.Query, Fragment = request.Url.Fragment, }; byte[] certificate = null; if (this.configuration.EnableClientCertificates) { var x509Certificate = request.GetClientCertificate(); if (x509Certificate != null) { certificate = x509Certificate.RawData; } } return(new Request( request.HttpMethod, nancyUrl, RequestStream.FromStream(request.InputStream, expectedRequestLength, false), request.Headers.ToDictionary(), (request.RemoteEndPoint != null) ? request.RemoteEndPoint.Address.ToString() : null, certificate)); }
public override HttpStatusCode ValidateAuthentication(HttpListenerContext listenerContext) { HttpStatusCode result = base.ValidateAuthentication(listenerContext); if (result == HttpStatusCode.OK) { if (this.shouldValidateClientCertificate) { HttpListenerRequest request = listenerContext.Request; X509Certificate2 certificateEx = request.GetClientCertificate(); if (certificateEx == null) { if (this.RequireClientCertificate) { if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.HttpsClientCertificateNotPresent, SR.GetString(SR.TraceCodeHttpsClientCertificateNotPresent), new HttpListenerRequestTraceRecord(listenerContext.Request), this, null); } result = CertificateErrorStatusCode; } } else if (request.ClientCertificateError != 0 && !useCustomClientCertificateVerification) { if (DiagnosticUtility.ShouldTraceWarning) { TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.HttpsClientCertificateInvalid, SR.GetString(SR.TraceCodeHttpsClientCertificateInvalid1, "0x" + (request.ClientCertificateError & 65535).ToString("X", CultureInfo.InvariantCulture)), new HttpListenerRequestTraceRecord(listenerContext.Request), this, null); } result = CertificateErrorStatusCode; } // Audit Authentication failure if (result != HttpStatusCode.OK && (AuditLevel.Failure == (this.AuditBehavior.MessageAuthenticationAuditLevel & AuditLevel.Failure))) { string message = SR.GetString(SR.HttpAuthenticationFailed, this.AuthenticationScheme, result); Exception exception = DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(message)); WriteAuditEvent(AuditLevel.Failure, (certificateEx != null) ? SecurityUtils.GetCertificateId(certificateEx) : String.Empty, exception); } } } return(result); }
internal bool TryGetClientCert(ref X509Certificate value, ref Exception errors) { if (!_request.IsSecureConnection) { return(false); } try { value = _request.GetClientCertificate(); if (_request.ClientCertificateError != 0) { errors = new Win32Exception(_request.ClientCertificateError); } return(value != null); } catch (HttpListenerException) { // TODO: LOG return(false); } }
private Request ConvertRequest(Uri baseUri, HttpListenerRequest httpRequest) { var expectedRequestLength = GetExpectedRequestLength(ConvertToDictionary(httpRequest.Headers)); var url = new Url { Scheme = httpRequest.Url.Scheme, HostName = httpRequest.Url.Host, Port = httpRequest.Url.IsDefaultPort ? null : (int?)httpRequest.Url.Port, BasePath = baseUri.AbsolutePath.TrimEnd('/'), Path = baseUri.MakeAppLocalPath(httpRequest.Url), Query = httpRequest.Url.Query, }; var fieldCount = httpRequest.ProtocolVersion.Major == 2 ? 1 : 2; var protocolVersion = string.Format("HTTP/{0}", httpRequest.ProtocolVersion.ToString(fieldCount)); byte[] certificate = null; if (httpRequest.IsSecureConnection) { var x509Certificate = httpRequest.GetClientCertificate(); if (x509Certificate != null) { certificate = x509Certificate.RawData; } } return(new Request( httpRequest.HttpMethod, url, RequestStream.FromStream(httpRequest.InputStream, expectedRequestLength, false), ConvertToDictionary(httpRequest.Headers), httpRequest.RemoteEndPoint, protocolVersion, certificate)); }
private void Worker(object state) { HttpListenerRequest request = null; HttpListenerResponse response = null; try { var context = state as HttpListenerContext; // request = context.Request; response = context.Response; // if (request.UserLanguages != null && request.UserLanguages.Length > 0) { try { CultureInfo culture = CultureInfo.CreateSpecificCulture(request.UserLanguages[0].ToLowerInvariant().Trim()); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; } catch { } } // if (request.IsSecureConnection) { var clientCertificate = request.GetClientCertificate(); var chain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck } }; chain.Build(clientCertificate); if (chain.ChainStatus.Length != 0) { // Invalid certificate response.StatusCode = (int)HttpStatusCode.Unauthorized; response.OutputStream.Close(); return; } } // response.Headers.Set(HttpResponseHeader.Server, "MIG WebService Gateway"); response.KeepAlive = false; // bool requestHasAuthorizationHeader = request.Headers["Authorization"] != null; string remoteAddress = request.RemoteEndPoint.Address.ToString(); string logExtras = ""; // if (servicePassword == "" || requestHasAuthorizationHeader) //request.IsAuthenticated) { bool verified = false; // string authUser = ""; string authPass = ""; // //NOTE: context.User.Identity and request.IsAuthenticated //aren't working under MONO with this code =/ //so we proceed by manually parsing Authorization header // //HttpListenerBasicIdentity identity = null; // if (requestHasAuthorizationHeader) { //identity = (HttpListenerBasicIdentity)context.User.Identity; // authuser = identity.Name; // authpass = identity.Password; byte[] encodedDataAsBytes = Convert.FromBase64String(request.Headers["Authorization"].Split(' ')[1]); string authtoken = Encoding.UTF8.GetString(encodedDataAsBytes); authUser = authtoken.Split(':')[0]; authPass = authtoken.Split(':')[1]; } // //TODO: complete authorization (for now with one fixed user 'admin', add multiuser support) // if (servicePassword == "" || authUser == serviceUsername && Utility.Encryption.SHA1.GenerateHashString(authPass) == servicePassword) { verified = true; } // if (verified) { string url = request.RawUrl.TrimStart('/').TrimStart('\\').TrimStart('.'); if (url.IndexOf("?") > 0) { url = url.Substring(0, url.IndexOf("?")); } // Check if this url is an alias url = UrlAliasCheck(url.TrimEnd('/')); // // url aliasing check if (url == "" || url.TrimEnd('/') == baseUrl.TrimEnd('/')) { // default home redirect response.Redirect("/" + baseUrl.TrimEnd('/') + "/index.html"); //TODO: find a solution for HG homepage redirect ---> ?" + new TimeSpan(DateTime.UtcNow.Ticks).TotalMilliseconds + "#page_control"); response.Close(); } else { var connectionWatch = Stopwatch.StartNew(); MigService.Log.Info(new MigEvent(this.GetName(), remoteAddress, "HTTP", request.HttpMethod, $"{response.StatusCode} {request.RawUrl} [OPEN]")); // this url is reserved for Server Sent Event stream if (url.TrimEnd('/').Equals("events")) { HandleEventsRoute(request, response, context, remoteAddress); } else { try { MigClientRequest migRequest = null; if (url.StartsWith("api/")) { string message = url.Substring(url.IndexOf('/', 1) + 1); var migContext = new MigContext(ContextSource.WebServiceGateway, context); migRequest = new MigClientRequest(migContext, new MigInterfaceCommand(message)); // Disable HTTP caching response.Headers.Set(HttpResponseHeader.CacheControl, "no-cache, no-store, must-revalidate"); response.Headers.Set(HttpResponseHeader.Pragma, "no-cache"); response.Headers.Set(HttpResponseHeader.Expires, "0"); // Store POST data (if any) in the migRequest.RequestData field migRequest.RequestData = WebServiceUtility.ReadToEnd(request.InputStream); migRequest.RequestText = request.ContentEncoding.GetString(migRequest.RequestData); } OnPreProcessRequest(migRequest); bool requestHandled = migRequest != null && migRequest.Handled; if (requestHandled) { SendResponseObject(context, migRequest.ResponseData); } else if (url.StartsWith(baseUrl) || baseUrl.Equals("/")) { // If request begins <base_url>, process as standard Web request string requestedFile = GetWebFilePath(url); if (!File.Exists(requestedFile)) { response.StatusCode = (int)HttpStatusCode.NotFound; WebServiceUtility.WriteStringToContext(context, $"<h1>404 - Not Found</h1><br/>{requestedFile}"); } else { bool isText = false; if (url.ToLower().EndsWith(".js")) // || requestedurl.EndsWith(".json")) { response.ContentType = "text/javascript"; isText = true; } else if (url.ToLower().EndsWith(".css")) { response.ContentType = "text/css"; isText = true; } else if (url.ToLower().EndsWith(".zip")) { response.ContentType = "application/zip"; } else if (url.ToLower().EndsWith(".png")) { response.ContentType = "image/png"; } else if (url.ToLower().EndsWith(".jpg")) { response.ContentType = "image/jpeg"; } else if (url.ToLower().EndsWith(".gif")) { response.ContentType = "image/gif"; } else if (url.ToLower().EndsWith(".svg")) { response.ContentType = "image/svg+xml"; } else if (url.ToLower().EndsWith(".mp3")) { response.ContentType = "audio/mp3"; } else if (url.ToLower().EndsWith(".wav")) { response.ContentType = "audio/x-wav"; } else if (url.ToLower().EndsWith(".appcache")) { response.ContentType = "text/cache-manifest"; } else if (url.ToLower().EndsWith(".otf") || url.ToLower().EndsWith(".ttf") || url.ToLower().EndsWith(".woff") || url.ToLower().EndsWith(".woff2")) { response.ContentType = "application/octet-stream"; } else if (url.ToLower().EndsWith(".xml")) { response.ContentType = "text/xml"; isText = true; } else { response.ContentType = "text/html"; isText = true; } var file = new FileInfo(requestedFile); response.ContentLength64 = file.Length; bool modified = true; if (request.Headers.AllKeys.Contains("If-Modified-Since")) { var modifiedSince = DateTime.MinValue; DateTime.TryParse(request.Headers["If-Modified-Since"], out modifiedSince); if (file.LastWriteTime.ToUniversalTime().Equals(modifiedSince)) { modified = false; } } bool disableCacheControl = HttpCacheIgnoreCheck(url); if (!modified && !disableCacheControl) { // TODO: !IMPORTANT! exclude from caching files that contains SSI tags! response.StatusCode = (int)HttpStatusCode.NotModified; //!!DISABLED!! - The following line was preventing browser to load file from cache //response.Headers.Set(HttpResponseHeader.Date, file.LastWriteTimeUtc.ToString().Replace(",", ".")); } else { response.Headers.Set(HttpResponseHeader.LastModified, file.LastWriteTimeUtc.ToString().Replace(",", ".")); if (disableCacheControl) { response.Headers.Set(HttpResponseHeader.CacheControl, "no-cache, no-store, must-revalidate"); response.Headers.Set(HttpResponseHeader.Pragma, "no-cache"); response.Headers.Set(HttpResponseHeader.Expires, "0"); } else { response.Headers.Set(HttpResponseHeader.CacheControl, "max-age=86400"); } // PRE PROCESS text output if (isText) { try { WebFile webFile = GetWebFile(requestedFile); response.ContentEncoding = webFile.Encoding; response.ContentType += "; charset=" + webFile.Encoding.BodyName; // We don't need to parse the content again if it's coming from the cache if (!webFile.IsCached) { string body = webFile.Content; if (requestedFile.EndsWith(".md")) { // Built-in Markdown files support body = CommonMarkConverter.Convert(body); // TODO: add a way to include HTML header and footer template to be appended to the // TODO: translated markdown text } else { // HTML file // replace prepocessor directives with values bool tagFound; do { tagFound = false; var ts = body.IndexOf("{include "); if (ts >= 0) { var te = body.IndexOf("}", ts); if (te > ts) { var rs = body.Substring(ts + (te - ts) + 1); var cs = body.Substring(ts, te - ts + 1); var ls = body.Substring(0, ts); // try { if (cs.StartsWith("{include ")) { var fileName = cs.Substring(9).TrimEnd('}').Trim(); fileName = GetWebFilePath(fileName); var fileEncoding = DetectWebFileEncoding(fileName) ?? defaultWebFileEncoding; var incFile = File.ReadAllText(fileName, fileEncoding) + rs; body = ls + incFile; } } catch { body = ls + "<h5 style=\"color:red\">Error processing '" + cs.Replace("{", "[").Replace("}", "]") + "'</h5>" + rs; } tagFound = true; } } } while (tagFound); // continue if a pre processor tag was found // {hostos} body = body.Replace("{hostos}", Environment.OSVersion.Platform.ToString()); // {filebase} body = body.Replace("{filebase}", Path.GetFileNameWithoutExtension(requestedFile)); } // update the cache content with parsing results webFile.Content = body; } // Store the cache item if the file cache is enabled if (enableFileCache) { UpdateWebFileCache(requestedFile, webFile.Content, response.ContentEncoding); } // WebServiceUtility.WriteStringToContext(context, webFile.Content); } catch (Exception ex) { // TODO: report internal mig interface error response.StatusCode = (int)HttpStatusCode.InternalServerError; WebServiceUtility.WriteStringToContext(context, ex.Message + "\n" + ex.StackTrace); MigService.Log.Error(ex); } } else { WebServiceUtility.WriteBytesToContext(context, File.ReadAllBytes(requestedFile)); } } } requestHandled = true; } OnPostProcessRequest(migRequest); if (!requestHandled && migRequest != null && migRequest.Handled) { SendResponseObject(context, migRequest.ResponseData); } else if (!requestHandled) { response.StatusCode = (int)HttpStatusCode.NotFound; WebServiceUtility.WriteStringToContext(context, "<h1>404 - Not Found</h1>"); } } catch (Exception eh) { // TODO: add error logging Console.Error.WriteLine(eh); } } connectionWatch.Stop(); logExtras = " [CLOSED AFTER " + Math.Round(connectionWatch.Elapsed.TotalSeconds, 3) + " seconds]"; } } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; // this will only work in Linux (mono) //response.Headers.Set(HttpResponseHeader.WwwAuthenticate, "Basic"); // this works both on Linux and Windows response.AddHeader("WWW-Authenticate", "Basic realm=\"User Visible Realm\""); } } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; // this will only work in Linux (mono) //response.Headers.Set(HttpResponseHeader.WwwAuthenticate, "Basic"); // this works both on Linux and Windows response.AddHeader("WWW-Authenticate", "Basic realm=\"User Visible Realm\""); } MigService.Log.Info(new MigEvent(this.GetName(), remoteAddress, "HTTP", request.HttpMethod, $"{response.StatusCode} {request.RawUrl}{logExtras}")); } catch (Exception ex) { MigService.Log.Error(ex); } finally { // // CleanUp/Dispose allocated resources // try { request.InputStream.Close(); } catch { // TODO: add logging } try { response.OutputStream.Close(); } catch { // TODO: add logging } try { response.Close(); } catch { // TODO: add logging } try { response.Abort(); } catch { // TODO: add logging } } }
public X509Certificate2 GetClientCertificate() { return(Request.GetClientCertificate()); }
/// <summary> /// Create an <see cref="HttpMessage.Request"/> object out of the given /// <paramref name="originalRequest"/>. /// </summary> /// <param name="originalRequest">The original request to mimic.</param> /// <returns>An <see cref="HttpMessage.Request"/> object containing the request.</returns> private static HttpMessage.Request ConstructRequestInfo( HttpListenerRequest originalRequest) { HttpMessage.Request requestInfo = new HttpMessage.Request(); // Copy the request Uri and Method requestInfo.RequestUri = originalRequest.Url; requestInfo.Method = originalRequest.HttpMethod; // Copy all relevant headers to the request requestInfo.Headers = new HttpMessage.HeaderCollection(); foreach (string headerKey in originalRequest.Headers.AllKeys) { if (headerKey.Equals("User-Agent", StringComparison.OrdinalIgnoreCase)) { requestInfo.UserAgent = originalRequest.Headers[headerKey]; } else if (headerKey.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { requestInfo.ContentType = originalRequest.Headers[headerKey]; } else if (headerKey.Equals("Accept", StringComparison.OrdinalIgnoreCase)) { requestInfo.Accept = originalRequest.Headers[headerKey]; } else if (!headerKey.Equals("Connection", StringComparison.OrdinalIgnoreCase) && !headerKey.Equals("Host", StringComparison.OrdinalIgnoreCase) && !headerKey.Equals("Content-Length", StringComparison.OrdinalIgnoreCase) && !headerKey.Equals("Expect", StringComparison.OrdinalIgnoreCase)) { requestInfo.Headers.Add(new HttpMessage.Header { Name = headerKey, Value = originalRequest.Headers[headerKey] }); } } // Copy response cookies requestInfo.Cookies = new HttpMessage.CookieCollection(); foreach (Cookie cookie in originalRequest.Cookies) { requestInfo.Cookies.Add(new HttpMessage.Cookie { Name = cookie.Name, Value = cookie.Value, }); } // Copy response stream if (originalRequest.Headers.AllKeys.Contains("Content-Length")) { using (StreamReader reader = new StreamReader(originalRequest.InputStream)) { requestInfo.RequestText = reader.ReadToEnd(); } } // Retrieve the certificate on the request if any. requestInfo.Certificate = originalRequest.GetClientCertificate(); return(requestInfo); }
static internal void StartListener(string _serverCert, string _serverKey, string serverCA, string _clientCert, string _clientKey) { // note that the programmatic cert creation and installation didn't work so did this - // makecert.exe - r - a sha1 - n CN = localhost - sky exchange - pe - b 01 / 01 / 2000 - e 01 / 01 / 2050 - ss my // then this // C:\Repos\RIoT Development\Utlilities\RIoTUtils\bin\Debug\Certs>netsh http add sslcert ipport=0.0.0.0:5556 appid={20a30499-7f02-446f-8716-e85fcdbb0ce4} certhash=360e6b474436076ff6cca4b1281fda021c276dbb // SSL Certificate successfully added // we need to add the server cert to the store for HttpListener to use it string serverPfxFile = "ServerCert.PFX"; Helpers.MakePFXFile(_serverCert, _serverKey, serverPfxFile, null); Helpers.DeleteCertsByIssuer("MSR_TEST"); Helpers.InstallCert(serverCA); Helpers.InstallCert(serverPfxFile); Helpers.SetCertForPort(serverPfxFile, 5556); string clientPfxFile = "ClientCert.PFX"; Helpers.MakePFXFile(_clientCert, _clientKey, clientPfxFile, null); // 9970e392d44f8d08c158660f1a0b05838f6201f0 // 360e6b474436076ff6cca4b1281fda021c276dbb SSLValidator.OverrideValidation(); var listener = new HttpListener(); listener.Prefixes.Add("https://127.0.0.1:5556/ABC/"); listener.Start(); Console.WriteLine("Listening..."); SslTcpClient.RunClient(_clientCert, _clientKey); /* * // make a request * //You must change the path to point to your .cer file location. * X509Certificate Cert = X509Certificate.CreateFromCertFile("ClientCert.PFX"); * // Handle any certificate errors on the certificate from the server. * // You must change the URL to point to your Web server. * HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://127.0.0.1:5556/ABC/123"); * Request.ClientCertificates.Add(Cert); * Request.UserAgent = "Client Cert Sample"; * Request.Method = "GET"; * var responseFromServer = Request.GetResponseAsync(); * //string respx = responseFromServer.Result.ToString(); * */ var context = listener.GetContext(); HttpListenerRequest request = context.Request; // Obtain a response object. HttpListenerResponse response = context.Response; var cert = request.GetClientCertificate(); // Construct a response. string responseString = "<HTML><BODY> Hello world!</BODY></HTML>"; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); // Get a response stream and write the response to it. response.ContentLength64 = buffer.Length; System.IO.Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); // You must close the output stream. output.Close(); listener.Stop(); }
public X509Certificate2 GetClientCertificate() { return(inner.GetClientCertificate()); }
/// <summary> /// See interface docs. /// </summary> /// <returns></returns> public X509Certificate2 GetClientCertificate() => _Wrapped.GetClientCertificate();
private void Worker(object state) { HttpListenerRequest request = null; HttpListenerResponse response = null; try { var context = state as HttpListenerContext; // request = context.Request; response = context.Response; // if (request.UserLanguages != null && request.UserLanguages.Length > 0) { try { CultureInfo culture = CultureInfo.CreateSpecificCulture(request.UserLanguages[0].ToLowerInvariant().Trim()); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; } catch { } } // if (request.IsSecureConnection) { var clientCertificate = request.GetClientCertificate(); X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(clientCertificate); if (chain.ChainStatus.Length != 0) { // Invalid certificate response.StatusCode = (int)HttpStatusCode.Unauthorized; response.OutputStream.Close(); return; } } // response.Headers.Set(HttpResponseHeader.Server, "MIG WebService Gateway"); response.KeepAlive = false; // bool isAuthenticated = (request.Headers["Authorization"] != null); string remoteAddress = request.RemoteEndPoint.Address.ToString(); string logExtras = ""; // if (servicePassword == "" || isAuthenticated) //request.IsAuthenticated) { bool verified = false; // string authUser = ""; string authPass = ""; // //NOTE: context.User.Identity and request.IsAuthenticated //aren't working under MONO with this code =/ //so we proceed by manually parsing Authorization header // //HttpListenerBasicIdentity identity = null; // if (isAuthenticated) { //identity = (HttpListenerBasicIdentity)context.User.Identity; // authuser = identity.Name; // authpass = identity.Password; byte[] encodedDataAsBytes = System.Convert.FromBase64String(request.Headers["Authorization"].Split(' ')[1]); string authtoken = System.Text.Encoding.UTF8.GetString(encodedDataAsBytes); authUser = authtoken.Split(':')[0]; authPass = authtoken.Split(':')[1]; } // //TODO: complete authorization (for now with one fixed user 'admin', add multiuser support) // if (servicePassword == "" || (authUser == serviceUsername && Utility.Encryption.SHA1.GenerateHashString(authPass) == servicePassword)) { verified = true; } // if (verified) { string url = request.RawUrl.TrimStart('/').TrimStart('\\').TrimStart('.'); if (url.IndexOf("?") > 0) { url = url.Substring(0, url.IndexOf("?")); } // Check if this url is an alias url = UrlAliasCheck(url.TrimEnd('/')); // // url aliasing check if (url == "" || url.TrimEnd('/') == baseUrl.TrimEnd('/')) { // default home redirect response.Redirect("/" + baseUrl.TrimEnd('/') + "/index.html"); //TODO: find a solution for HG homepage redirect ---> ?" + new TimeSpan(DateTime.UtcNow.Ticks).TotalMilliseconds + "#page_control"); response.Close(); } else { var connectionWatch = Stopwatch.StartNew(); MigService.Log.Info(new MigEvent(this.GetName(), remoteAddress, "HTTP", request.HttpMethod.ToString(), String.Format("{0} {1} [OPEN]", response.StatusCode, request.RawUrl))); // this url is reserved for Server Sent Event stream if (url.TrimEnd('/').Equals("events")) { // TODO: move all of this to a separate function // Server sent events // NOTE: no PreProcess or PostProcess events are fired in this case //response.KeepAlive = true; response.ContentEncoding = Encoding.UTF8; response.ContentType = "text/event-stream"; response.Headers.Set(HttpResponseHeader.CacheControl, "no-cache, no-store, must-revalidate"); response.Headers.Set(HttpResponseHeader.Pragma, "no-cache"); response.Headers.Set("Access-Control-Allow-Origin", "*"); // 2K padding for IE var padding = ":" + new String(' ', 2048) + "\n"; byte[] paddingData = System.Text.Encoding.UTF8.GetBytes(padding); response.OutputStream.Write(paddingData, 0, paddingData.Length); byte[] retryData = System.Text.Encoding.UTF8.GetBytes("retry: 1000\n"); response.OutputStream.Write(retryData, 0, retryData.Length); DateTime lastTimeStamp = DateTime.UtcNow; var lastId = context.Request.Headers.Get("Last-Event-ID"); if (lastId == null || lastId == "") { var queryValues = HttpUtility.ParseQueryString(context.Request.Url.Query); lastId = queryValues.Get("lastEventId"); } if (lastId != null && lastId != "") { double unixTimestamp = 0; double.TryParse(lastId, NumberStyles.Float | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out unixTimestamp); if (unixTimestamp != 0) { lastTimeStamp = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); lastTimeStamp.AddSeconds(Math.Round(unixTimestamp / 1000d)); } } bool connected = true; var timeoutWatch = Stopwatch.StartNew(); while (connected) { // dirty work around for signaling new event and // avoiding locks on long socket timetout lock (sseEventToken) Monitor.Wait(sseEventToken, 1000); // safely dequeue events List <SseEvent> bufferedData; do { bufferedData = sseEventBuffer.FindAll(le => le != null && le.Timestamp.Ticks > lastTimeStamp.Ticks); if (bufferedData.Count > 0) { foreach (SseEvent entry in bufferedData) { // send events try { // The following throws an error on some mono-arm (Input string was not in the correct format) // entry.Event.UnixTimestamp.ToString("R", CultureInfo.InvariantCulture) byte[] data = System.Text.Encoding.UTF8.GetBytes("id: " + entry.Event.UnixTimestamp.ToString().Replace(",", ".") + "\ndata: " + MigService.JsonSerialize(entry.Event) + "\n\n"); response.OutputStream.Write(data, 0, data.Length); //response.OutputStream.Flush(); lastTimeStamp = entry.Timestamp; } catch (Exception e) { MigService.Log.Info(new MigEvent(this.GetName(), remoteAddress, "HTTP", request.HttpMethod.ToString(), String.Format("{0} {1} [ERROR: {2}]", response.StatusCode, request.RawUrl, e.Message))); connected = false; break; } } Thread.Sleep(100); } // there might be new data after sending } while (connected && bufferedData.Count > 0); // check if the remote end point is still alive every 15 seconds or so if (timeoutWatch.Elapsed.TotalSeconds > 15) { connected = connected && IsRemoteEndPointConnected(request.RemoteEndPoint); timeoutWatch.Stop(); timeoutWatch = Stopwatch.StartNew(); } } } else { try { MigClientRequest migRequest = null; if (url.StartsWith("api/")) { string message = url.Substring(url.IndexOf('/', 1) + 1); var migContext = new MigContext(ContextSource.WebServiceGateway, context); migRequest = new MigClientRequest(migContext, new MigInterfaceCommand(message)); // Disable HTTP caching response.Headers.Set(HttpResponseHeader.CacheControl, "no-cache, no-store, must-revalidate"); response.Headers.Set(HttpResponseHeader.Pragma, "no-cache"); response.Headers.Set(HttpResponseHeader.Expires, "0"); // Store POST data (if any) in the migRequest.RequestData field migRequest.RequestData = WebServiceUtility.ReadToEnd(request.InputStream); migRequest.RequestText = request.ContentEncoding.GetString(migRequest.RequestData); } OnPreProcessRequest(migRequest); bool requestHandled = (migRequest != null && migRequest.Handled); if (requestHandled) { SendResponseObject(context, migRequest.ResponseData); } else if (url.StartsWith(baseUrl) || baseUrl.Equals("/")) { // If request begins <base_url>, process as standard Web request string requestedFile = GetWebFilePath(url); if (!System.IO.File.Exists(requestedFile)) { response.StatusCode = (int)HttpStatusCode.NotFound; WebServiceUtility.WriteStringToContext(context, "<h1>404 - Not Found</h1>"); } else { bool isText = false; if (url.ToLower().EndsWith(".js")) // || requestedurl.EndsWith(".json")) { response.ContentType = "text/javascript"; isText = true; } else if (url.ToLower().EndsWith(".css")) { response.ContentType = "text/css"; isText = true; } else if (url.ToLower().EndsWith(".zip")) { response.ContentType = "application/zip"; } else if (url.ToLower().EndsWith(".png")) { response.ContentType = "image/png"; } else if (url.ToLower().EndsWith(".jpg")) { response.ContentType = "image/jpeg"; } else if (url.ToLower().EndsWith(".gif")) { response.ContentType = "image/gif"; } else if (url.ToLower().EndsWith(".svg")) { response.ContentType = "image/svg+xml"; } else if (url.ToLower().EndsWith(".mp3")) { response.ContentType = "audio/mp3"; } else if (url.ToLower().EndsWith(".wav")) { response.ContentType = "audio/x-wav"; } else if (url.ToLower().EndsWith(".appcache")) { response.ContentType = "text/cache-manifest"; } else if (url.ToLower().EndsWith(".otf") || url.ToLower().EndsWith(".ttf") || url.ToLower().EndsWith(".woff") || url.ToLower().EndsWith(".woff2")) { response.ContentType = "application/octet-stream"; } else if (url.ToLower().EndsWith(".xml")) { response.ContentType = "text/xml"; isText = true; } else { response.ContentType = "text/html"; isText = true; } var file = new System.IO.FileInfo(requestedFile); response.ContentLength64 = file.Length; bool modified = true; if (request.Headers.AllKeys.Contains("If-Modified-Since")) { var modifiedSince = DateTime.MinValue; DateTime.TryParse(request.Headers["If-Modified-Since"], out modifiedSince); if (file.LastWriteTime.ToUniversalTime().Equals(modifiedSince)) { modified = false; } } bool disableCacheControl = HttpCacheIgnoreCheck(url); if (!modified && !disableCacheControl) { // TODO: !IMPORTANT! exclude from caching files that contains SSI tags! response.StatusCode = (int)HttpStatusCode.NotModified; //!!DISABLED!! - The following line was preventing browser to load file from cache //response.Headers.Set(HttpResponseHeader.Date, file.LastWriteTimeUtc.ToString().Replace(",", ".")); } else { response.Headers.Set(HttpResponseHeader.LastModified, file.LastWriteTimeUtc.ToString().Replace(",", ".")); if (disableCacheControl) { response.Headers.Set(HttpResponseHeader.CacheControl, "no-cache, no-store, must-revalidate"); response.Headers.Set(HttpResponseHeader.Pragma, "no-cache"); response.Headers.Set(HttpResponseHeader.Expires, "0"); } else { response.Headers.Set(HttpResponseHeader.CacheControl, "max-age=86400"); } // PRE PROCESS text output if (isText) { try { WebFile webFile = GetWebFile(requestedFile); response.ContentEncoding = webFile.Encoding; response.ContentType += "; charset=" + webFile.Encoding.BodyName; // We don't need to parse the content again if it's coming from the cache if (!webFile.IsCached) { string body = webFile.Content; if (requestedFile.EndsWith(".md")) { // Built-in Markdown files support body = CommonMark.CommonMarkConverter.Convert(body); // TODO: add a way to include HTML header and footer template to be appended to the // TODO: translated markdown text } else { // HTML file // replace prepocessor directives with values bool tagFound; do { tagFound = false; int ts = body.IndexOf("{include "); if (ts >= 0) { int te = body.IndexOf("}", ts); if (te > ts) { string rs = body.Substring(ts + (te - ts) + 1); string cs = body.Substring(ts, te - ts + 1); string ls = body.Substring(0, ts); // try { if (cs.StartsWith("{include ")) { string fileName = cs.Substring(9).TrimEnd('}').Trim(); fileName = GetWebFilePath(fileName); // Encoding fileEncoding = DetectWebFileEncoding(fileName); if (fileEncoding == null) { fileEncoding = defaultWebFileEncoding; } var incFile = System.IO.File.ReadAllText(fileName, fileEncoding) + rs; body = ls + incFile; } } catch { body = ls + "<h5 style=\"color:red\">Error processing '" + cs.Replace("{", "[").Replace("}", "]") + "'</h5>" + rs; } tagFound = true; } } } while (tagFound); // continue if a pre processor tag was found // {hostos} body = body.Replace("{hostos}", Environment.OSVersion.Platform.ToString()); // {filebase} body = body.Replace("{filebase}", Path.GetFileNameWithoutExtension(requestedFile)); } // update the cache content with parsing results webFile.Content = body; } // Store the cache item if the file cache is enabled if (enableFileCache) { UpdateWebFileCache(requestedFile, webFile.Content, response.ContentEncoding); } // WebServiceUtility.WriteStringToContext(context, webFile.Content); } catch (Exception ex) { // TODO: report internal mig interface error response.StatusCode = (int)HttpStatusCode.InternalServerError; WebServiceUtility.WriteStringToContext(context, ex.Message + "\n" + ex.StackTrace); MigService.Log.Error(ex); } } else { WebServiceUtility.WriteBytesToContext(context, System.IO.File.ReadAllBytes(requestedFile)); } } } requestHandled = true; } OnPostProcessRequest(migRequest); if (!requestHandled && migRequest != null && migRequest.Handled) { SendResponseObject(context, migRequest.ResponseData); } else if (!requestHandled) { response.StatusCode = (int)HttpStatusCode.NotFound; WebServiceUtility.WriteStringToContext(context, "<h1>404 - Not Found</h1>"); } } catch (Exception eh) { // TODO: add error logging Console.Error.WriteLine(eh); } } connectionWatch.Stop(); logExtras = " [CLOSED AFTER " + Math.Round(connectionWatch.Elapsed.TotalSeconds, 3) + " seconds]"; } } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; // this will only work in Linux (mono) //response.Headers.Set(HttpResponseHeader.WwwAuthenticate, "Basic"); // this works both on Linux and Windows //response.AddHeader("WWW-Authenticate", "Basic"); } } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; // this will only work in Linux (mono) //response.Headers.Set(HttpResponseHeader.WwwAuthenticate, "Basic"); // this works both on Linux and Windows //response.AddHeader("WWW-Authenticate", "Basic"); } MigService.Log.Info(new MigEvent(this.GetName(), remoteAddress, "HTTP", request.HttpMethod.ToString(), String.Format("{0} {1}{2}", response.StatusCode, request.RawUrl, logExtras))); } catch (Exception ex) { MigService.Log.Error(ex); } finally { // // CleanUp/Dispose allocated resources // try { request.InputStream.Close(); } catch { // TODO: add logging } try { response.OutputStream.Close(); } catch { // TODO: add logging } try { response.Close(); } catch { // TODO: add logging } try { response.Abort(); } catch { // TODO: add logging } } }
// </snippet1> public static void Main() { // <snippet2> // Set up a listener. HttpListener listener = new HttpListener(); HttpListenerPrefixCollection prefixes = listener.Prefixes; prefixes.Add(@"http://*****:*****@"http://contoso.com:8080/"); // Specify the authentication delegate. listener.AuthenticationSchemeSelectorDelegate = new AuthenticationSchemeSelector(AuthenticationSchemeForClient); // Start listening for requests and process them // synchronously. listener.Start(); // </snippet2> while (true) { // <snippet3> Console.WriteLine("Listening for {0} prefixes...", listener.Prefixes.Count); HttpListenerContext context = listener.GetContext(); HttpListenerRequest request = context.Request; Console.WriteLine("Received a request."); // This server requires a valid client certificate // for requests that are not sent from the local computer. // Did the client omit the certificate or send an invalid certificate? if (request.IsAuthenticated && request.GetClientCertificate() == null || request.ClientCertificateError != 0) { // Send a 403 response. HttpListenerResponse badCertificateResponse = context.Response; SendBadCertificateResponse(badCertificateResponse); Console.WriteLine("Client has invalid certificate."); continue; } // </snippet3> StringBuilder message = new StringBuilder(); // <snippet7> // When the client is not authenticated, there is no Identity. if (context.User == null) { message.Append("<HTML><BODY><p> Hello local user! </p></BODY></HTML>"); } else { // <snippet6> // Get the requester's identity. System.Security.Principal.WindowsIdentity identity = WindowsIdentity.GetCurrent(); // Construct the response body. message.AppendFormat("<HTML><BODY><p> Hello {0}!<br/>", identity.Name); message.AppendFormat("You were authenticated using {0}.</p>", identity.AuthenticationType); message.Append("</BODY></HTML>"); // </snippet6> } // Configure the response. HttpListenerResponse response = context.Response; // Use the encoding from the response if one has been set. // Otherwise, use UTF8. System.Text.Encoding encoding = response.ContentEncoding; if (encoding == null) { encoding = System.Text.Encoding.UTF8; response.ContentEncoding = encoding; } byte[] buffer = encoding.GetBytes(message.ToString()); response.ContentLength64 = buffer.Length; response.StatusCode = (int)HttpStatusCode.OK; response.StatusDescription = "OK"; response.ProtocolVersion = new Version("1.1"); // Don't keep the TCP connection alive; // We don't expect multiple requests from the same client. response.KeepAlive = false; // Write the response body. System.IO.Stream stream = response.OutputStream; stream.Write(buffer, 0, buffer.Length); // </snippet7> // <snippet4> Console.WriteLine("Request complete. Press q to quit, enter to continue."); string answer = Console.ReadLine(); if (answer.StartsWith("q")) { Console.WriteLine("bye."); listener.Close(); break; } // </snippet4> } }