HttpAddUrl on localhost fails for non-admin users - c++

Using the Windows HTTP API I'm running a HTTP file server on localhost.
This involves calling HttpAddUrl(hRequestQueue, L"http://localhost:80/", NULL).
This fails with ERROR_ACCESS_DENIED unless the user runs the application as administrator. I need this functionality for users who don't have admin privileges. (What's wrong with a user running a localhost server anyway? It's just for the user themselves.)
I found a hotfix for Vista and XP which seems aimed at solving this, but there's nothing for Windows 7. The article implies it was fixed in Vista SP1, and I have Windows 7 SP1 and it's still a problem - did the fix not make it to Windows 7?
Is there anything else I can do to get the server to run for non-admins?

Answering my own question, but found a workaround: the IANA port numbers state ports 49152-65535 are for dynamic/private purposes. HttpAddUrl for localhost on a port >= 49152 works fine for non-admins.

This must be configured on system level because HTTP API uses http.sys (kernel driver). You can use netsh.exe command executed with Administrator privileges to grant access to the user or application:
netsh http add urlacl url=http://localhost:80/ user=EVERYONE listen=yes delegate=no

Ports 1-1024, by default, require administrative access. Otherwise you get error code 5 (ACCESS_DENIED). If you attempt to bind to a port above 1024, e.g.:
http://localhost:8080/
it will work for non-admin users. In your case you tried to listen on port 80, which HttpServer API limits to administrators.
Everything in Windows is controlled by Access Control Lists (ACLs); this includes the listen ports allowed when using HttpServer. You can display the current ACLs used by http by running:
>netsh http show urlacl
If you do that, you'll see a lot of ACLs already defined by various systems.
Windows Communication Foundation
One ACL entry is particularly interesting:
Reserved URL : http://+:80/Temporary_Listen_Addresses/
User: \Everyone
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;WD)
Everyone is granted the right to listen on port 80, as long as you live off of:
/Temporary_Listen_Addresses/
This url is used by Windows Communication Foundation (WCF), which normally constructs a URL of the form:
http://+:80/Temporary_Listen_Addresses/{random-guid}/
It also means, if you really want port 80, you can listen with your own, for example:
http://localhost:80/Temporary_Listen_Addresses/64E3DCC6-FE47-4A86-87F4-48D2E1B44AE9/
As long as nobody is already using port 80 (i'm looking at your Skype!), you'll get it.
WinSock listening sockets do not require admin
While the HttpServer API has ACLs controlling access to ports below 1024, it should be noted that the WinSock API has no restriction.
If you want to use WinSock to open a listening socket on port 80, you do not need to be an administrator. It is only the Http api that has the ACL.

Related

C++ Gain Sufficient Privilege to Bind to Port 80

I am writing a C++ application that accepts HTTP request from browser and sending back the response.
int port = 2127; //80;
int bind_res = ::bind(port, p_ref->ai_addr, p_ref->ai_addrlen);
The application works as expected on OSX when I set it to listen at port 2127. But when I set it to listen on port 80, the application stopped working with exception:
server: bind: Permission denied
My application is a command line application, and it opened by other GUI application, also written in C++ but with Qt.
How can I gain enough privilege to bind to port 80? Is there any API to show user and password prompt - like in XAMPP Control Panel, for example - to get those privilege?
EDIT:
I write the app for running on OSX 10.8 Mountain Lion.
Usually you cannot bind because of two issues:
something (Apache server, Skype) is already bound to that port.
you run as user and try to bind to a port below 1024.
It feels you have problem with that second case. For running with super user privileges there is sudo command on all Unixes (OSX is Unix).
If you do not like sudo then you can permanently redirect the port to other port that can be bound by user.

embedded http server in c++ for chrome extension native client

i was trying to find some examples that would give me some pointers on how to create an http server within a chrome extension, but haven't had any luck. does anyone know a how to start an NPAPI,NACL http server?
Thanks
Short answer: not possible.
If you want to open a port on a local machine to allow connections, then that is not allowed by the web security model. NaCl runs with the same privileges as JavaScript, no extra holes. However, you may specify extra flags to chrome on start to get more permissions from NaCl, such as open debug port, or get access to raw network sockets.
If you want to 'emulate' an HTTP server to make your extension keep using it regardless of being offline, then it is easier to use the PostMessage API.

CFHTTP firewall issue? How are CFHTTP requests made?

CFHTTP on my new CF 9 server is failing. I get back "408 Request Time-out" when attempting to connect to the test page on the server via its internal or external IP. I am not using SSL and using the standard port 80.
My old CF 9 server can connect to itself fine but it also fails if attempting to connect to the new server.
If I RDP into the server, I am able to pull up the same test page via a web browser or via telnet to that ip port 80.
I suspect that this is a firewall issue. I'd like to know how CF makes an HTTP request under the hood before I talk to the hosting team. What service is making the call? What port is it running under, etc.
You don't say what operating system you are running under, but if it is Windows, I'd take a look at the Windows Firewall settings on your new machine, and disable the firewall. That will allow you to check if indeed it is the Firewall in the way.
If that works you can then try and add a firewall exception for the application, i.e. JRun.
Hope that helps.

Windows Integrated Authentication fails ONLY if web svcs client is on same machine as IIS server

I have a web service running under IIS7 on a server with a host header set so that it receives requests made to http://myserver1.mydomain.com.
I've set Windows INtegrated Authentication to Enabled and everything else (basic, anonymous, etc) to Disabled.
I'm testing the web service using a powershell script, and it works fine when I run it from my workstation against http://myserver1.mydomain.com
However, when I run the same exact script on the IIS server itself, I get a 401-Unauthorized message.
In addition, I've tried installing the web service on a second server, myserver2.mydomain.com. Again I can call my test script fine from BOTH my workstation and from myserver1.
So it seems the only issue is when the client is on the same box as the web server itself - somehow the windows credentials are not being passed or recognized.
I tried playing with IE settings on myserver1 (checked and unchecked 'Enable Windows Integrated Authentication', and added the URL to Local Sites). That did not seem to have an effect.
When I look at the IIS logs, I see the 401 unauthorized line but very little other information.
I see basically the same behavior when testing with IE (v9) - works from my workstation but not when IE is running on the IIS server.
I found the answer after several hours:
By default, there is something called a LoopbackCheck which will reject windows authentication if the host header used for the site does not match the local host's name. This behavior will only be seen when the client is on the local host. The check is there to defeat possible reflection attacks.
More details here:
http://support.microsoft.com/kb/896861
The kb item discusses ways to disable the Loopback check, but I ended up just switching from using host headers to ports to distinguish the different sites on the IIS server.
Thanks to those who gave assistance.
Try checking the actual credential that is being passed when you are running on the server itself. Often times you will be running on some system account that doesn't have access to the resource in question.
For example, on your box your credentials are running as...
MYDOMAIN\MYNAME
and the server will be something like...
SYSTEM\SYSTEM_ACCOUNT
and so this will fail because 'SYSTEM\SYSTEM_ACCOUNT' doesn't have credentials.
If this is the case, you can fix the problem in one of two ways.
Give 'SYSTEM\SYSTEM_ACCOUNT' access to the resource in question. Most people would avoid this strategy due to security concerns (which is why the account has no access in the first place).
Impersonate, or change the credentials of the client manually to something that does have access to the resource, 'MYDOMAIN\MYNAME' for example. This is what most people would probably go with, including myself.

HttpAddUrl permissions

I'm trying to run a custom WinHTTP based web-server on Windows Server 2008 machine.
I pass "http://*:22222/" to HttpAddUrl
When I start my executable as Administrator or LocalSystem everything works fine. However if I try to run it as NetworkService to minimize security risks (since there are no legitimate reasons for the app to use admin rights) function fails with "Access Denied" error code.
I wasn't aware of NetworkService having any restrictions on which ports and interfaces it can listen on.
Is there a way to configure permissions in such a way so that I actually can run the app under NetworkService account and connect to it from other internet hosts?
You must be an administrator to add URLs to the http.sys URL mappings. Network Service does is not a member of the admin group, but the admnistrator's group and the System account are members.
IIS gets around this by having one process, inetinfo.exe, that runs as SYSTEM and sets up the URL mappings for worker processes (w3wp.exe) that run as Network Service.
Hope that clarifies tings.