HttpListener Access Denied

Windows 7C# 4.0UacHttplistener

Windows 7 Problem Overview


I am writing an HTTP server in C#.

When I try to execute the function HttpListener.Start() I get an HttpListenerException saying

> "Access Denied".

When I run the app in admin mode in windows 7 it works fine.

Can I make it run without admin mode? if yes how? If not how can I make the app change to admin mode after start running?

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        private HttpListener httpListener = null;

        static void Main(string[] args)
        {
            Program p = new Program();
            p.Server();
        }

        public void Server()
        {
            this.httpListener = new HttpListener();

            if (httpListener.IsListening)
                throw new InvalidOperationException("Server is currently running.");

            httpListener.Prefixes.Clear();
            httpListener.Prefixes.Add("http://*:4444/");

            try
            {
                httpListener.Start(); //Throws Exception
            }
            catch (HttpListenerException ex)
            {
                if (ex.Message.Contains("Access is denied"))
                {
                    return;
                }
                else
                {
                    throw;
                }
            }
        }
    }
}

Windows 7 Solutions


Solution 1 - Windows 7

Yes you can run HttpListener in non-admin mode. All you need to do is grant permissions to the particular URL. e.g.

netsh http add urlacl url=http://+:80/MyUri user=DOMAIN\user

Documentation is here.

Solution 2 - Windows 7

If you use http://localhost:80/ as a prefix, you can listen to http requests with no need for Administrative privileges.

Solution 3 - Windows 7

> Can I make it run without admin mode? if yes how? If not how can I make the app change to admin mode after start running?

You can't, it has to start with elevated privileges. You can restart it with the runas verb, which will prompt the user to switch to admin mode

static void RestartAsAdmin()
{
    var startInfo = new ProcessStartInfo("yourApp.exe") { Verb = "runas" };
    Process.Start(startInfo);
    Environment.Exit(0);
}

EDIT: actually, that's not true; HttpListener can run without elevated privileges, but you need to give permission for the URL on which you want to listen. See Darrel Miller's answer for details.

Solution 4 - Windows 7

The syntax was wrong for me, you must include the quotes:

netsh http add urlacl url="http://+:4200/" user=everyone

otherwise I received "The parameter is incorrect"

Solution 5 - Windows 7

As an alternative that doesn't require elevation or netsh you could also use TcpListener for instance.

The following is a modified excerpt of this sample: https://github.com/googlesamples/oauth-apps-for-windows/tree/master/OAuthDesktopApp

// Generates state and PKCE values.
string state = randomDataBase64url(32);
string code_verifier = randomDataBase64url(32);
string code_challenge = base64urlencodeNoPadding(sha256(code_verifier));
const string code_challenge_method = "S256";

// Creates a redirect URI using an available port on the loopback address.
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
string redirectURI = string.Format("http://{0}:{1}/", IPAddress.Loopback, ((IPEndPoint)listener.LocalEndpoint).Port);
output("redirect URI: " + redirectURI);

// Creates the OAuth 2.0 authorization request.
string authorizationRequest = string.Format("{0}?response_type=code&scope=openid%20profile&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
	authorizationEndpoint,
	System.Uri.EscapeDataString(redirectURI),
	clientID,
	state,
	code_challenge,
	code_challenge_method);

// Opens request in the browser.
System.Diagnostics.Process.Start(authorizationRequest);

// Waits for the OAuth authorization response.
var client = await listener.AcceptTcpClientAsync();

// Read response.
var response = ReadString(client);

// Brings this app back to the foreground.
this.Activate();

// Sends an HTTP response to the browser.
WriteStringAsync(client, "<html><head><meta http-equiv='refresh' content='10;url=https://google.com'></head><body>Please close this window and return to the app.</body></html>").ContinueWith(t =>
{
	client.Dispose();
	listener.Stop();

	Console.WriteLine("HTTP server stopped.");
});

// TODO: Check the response here to get the authorization code and verify the code challenge

The read and write methods being:

private string ReadString(TcpClient client)
{
	var readBuffer = new byte[client.ReceiveBufferSize];
	string fullServerReply = null;

	using (var inStream = new MemoryStream())
	{
		var stream = client.GetStream();

		while (stream.DataAvailable)
		{
			var numberOfBytesRead = stream.Read(readBuffer, 0, readBuffer.Length);
			if (numberOfBytesRead <= 0)
				break;

			inStream.Write(readBuffer, 0, numberOfBytesRead);
		}

		fullServerReply = Encoding.UTF8.GetString(inStream.ToArray());
	}

	return fullServerReply;
}

private Task WriteStringAsync(TcpClient client, string str)
{
	return Task.Run(() =>
	{
		using (var writer = new StreamWriter(client.GetStream(), new UTF8Encoding(false)))
		{
			writer.Write("HTTP/1.0 200 OK");
			writer.Write(Environment.NewLine);
			writer.Write("Content-Type: text/html; charset=UTF-8");
			writer.Write(Environment.NewLine);
			writer.Write("Content-Length: " + str.Length);
			writer.Write(Environment.NewLine);
			writer.Write(Environment.NewLine);
			writer.Write(str);
		}
	});
}

Solution 6 - Windows 7

In case you want to use the flag "user=Everyone" you need to adjust it to your system language. In english it is as mentioned:

netsh http add urlacl url=http://+:80/ user=Everyone

In german it would be:

netsh http add urlacl url=http://+:80/ user=Jeder

Solution 7 - Windows 7

By default Windows defines the following prefix that is available to everyone: http://+:80/Temporary_Listen_Addresses/

So you can register your HttpListener via:

Prefixes.Add("http://+:80/Temporary_Listen_Addresses/" + Guid.NewGuid().ToString("D") + "/";

This sometimes causes problems with software such as Skype which will try to utilise port 80 by default.

Solution 8 - Windows 7

You can start your application as administrator if you add Application Manifest to your project.

Just Add New Item to your project and select "Application Manifest File". Change the <requestedExecutionLevel> element to:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Solution 9 - Windows 7

httpListener.Prefixes.Add("http://*:4444/");

you use "*" so you execute following cmd as admin

netsh http add urlacl url=http://*:4444/ user=username

no use +, must use *, because you spec *:4444~.

https://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

Solution 10 - Windows 7

I also faced similar problem.If you have already reserved url then you have to first delete the url to run in non admin mode else it will fail with Access is Denied error.

netsh http delete urlacl url=http://+:80

Solution 11 - Windows 7

Thanks all, it was of great help. Just to add more [from MS page]:

> Warning > > Top-level wildcard bindings (http://*:8080/ and http://+:8080) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit host names rather than wildcards. Subdomain wildcard binding (for example, *.mysub.com) doesn't have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). See rfc7230 section-5.4 for more information.

Solution 12 - Windows 7

Unfortunately, for some reasons probably linked with HTTPS and certificates, the native .NET HttpListener requires admin privileges, and even for HTTP only protocol...

The good point

It is interesting to note that HTTP protocol is on top of TCP protocol, but launching a C# TCP listener doesn't require any admin privileges to run. In other words, it is conceptually possible to implement an HTTP server which do not requires admin privileges.

Alternative

Below, an example of project which doesn't require admin privileges: https://github.com/EmilianoElMariachi/ElMariachi.Http.Server

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRandall FlaggView Question on Stackoverflow
Solution 1 - Windows 7Darrel MillerView Answer on Stackoverflow
Solution 2 - Windows 7Ehsan MirsaeediView Answer on Stackoverflow
Solution 3 - Windows 7Thomas LevesqueView Answer on Stackoverflow
Solution 4 - Windows 7DaveView Answer on Stackoverflow
Solution 5 - Windows 7Michael OlsenView Answer on Stackoverflow
Solution 6 - Windows 7Christoph BrückmannView Answer on Stackoverflow
Solution 7 - Windows 7SebastianView Answer on Stackoverflow
Solution 8 - Windows 7R.TitovView Answer on Stackoverflow
Solution 9 - Windows 7NamedStarView Answer on Stackoverflow
Solution 10 - Windows 7vivek nunaView Answer on Stackoverflow
Solution 11 - Windows 7Manish PatilView Answer on Stackoverflow
Solution 12 - Windows 7Kino101View Answer on Stackoverflow