Mongrel as Windows service with normal privileges

I am trying to run Mongrel 1.1.5 with mongrel_service 0.3.4 on Ruby
1.8.6 with a “normal” user account, i.e. a user which belongs only to
the Windows group “Users”. The rationale behind this is that running a
web server with full administrative rights (e.g. Local System) is not
something that I would like to do.

Unfortunately, starting the service from the services control panel
results in the following error message: “The service did not respond to
the start or control request in a timely fashion” (the error comes up
very quickly, maybe 1 second max).

This happens only if the user the service is configured to run as does
not belong to the “Administrators” group, otherwise it works fine.

I have read a couple of threads about this subject, so this is what I
have already tried:

(With psexec -l cmd.exe:)

  1. mongrel_rails start -e development -a 127.0.0.1 -p 3000
    ===> WORKS
  2. mongrel_service console single -e development -a 127.0.0.1 -p 3000
    ===> WORKS

(Interactively logged in as the service user:)
3. mongrel_rails start -e development -a 127.0.0.1 -p 3000
===> WORKS
4. mongrel_service console single -e development -a 127.0.0.1 -p 3000
===> WORKS

  1. Running the service with service user in Administrator group
    ===> WORKS

  2. Running the service with service user only in Users (or Power Users)
    group
    ===> DOES NOT WORK

I had to change a couple of NTFS security settings in order to get it
run with normal privileges. Now the only thing that still does not work
is #6. Unfortunately, no log files are being generated, especially
ServiceFB.log is nowhere to be found. The server is Windows Server 2003
Standard, by the way.

Could anybody please enlighten me how I could further analyze this
problem ? I followed the advise here in the list as far as I could, but
now I am at a loss.

Thanks in advance,
Ingmar

On Wed, Jun 4, 2008 at 1:37 PM, Ingmar S. [email protected] wrote:

===> WORKS
6. Running the service with service user only in Users (or Power Users)
group
===> DOES NOT WORK

I had to change a couple of NTFS security settings in order to get it run
with normal privileges. Now the only thing that still does not work is #6.
Unfortunately, no log files are being generated, especially ServiceFB.log
is nowhere to be found. The server is Windows Server 2003 Standard, by the
way.

32bits or x64 editions?

In any case, serviceFB.log and mongrel.log and mongrel_service.log
should be stored into ruby/bin folder since was not possible by the
service point to the directory of the service.

I suggest you also try the psexec tool from Sysinternals and also
runas program (builtin in Windows) to get more detail information.

PATH reports from these environment will be help, also the security
bits from the ACLs too, since if it runs as administrator maybe there
is some file down there in your app (maybe log folder) that is not
allowed to be written in it.

Could anybody please enlighten me how I could further analyze this problem ?
I followed the advise here in the list as far as I could, but now I am at a
loss.

It’s hard to replicate all the environments, so please try go back to
0.3.3 which generates the servicefb.log file and see what it outputs.

In any case, mongrel.log should always be generated.

Thanks in advance,
Ingmar

HTH and please post your results so we can help you out.

Regards,

Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

Luis L. wrote:

32bits or x64 editions?

Windows 2003 32bit.

In any case, serviceFB.log and mongrel.log and mongrel_service.log
should be stored into ruby/bin folder since was not possible by the
service point to the directory of the service.

Thanks for the hint of using mongrel_service 0.3.3. I get these log
files now:

servicefb.log:

_initialize() constructor
_initialize() constructor done
ServiceProcess(new_name)
ServiceProcess(new_name) done
ServiceHost()
ServiceHost() done
ServiceHost.Add()
_add_to_references()
_add_to_references() done
ServiceHost.Add() done
ServiceController.RunMode()
CurrentPID: 5108
ParentPID: 512
Error with OpenProcess
GetLastError: 0The operation completed successfully.
Parent Name:
ServiceController.RunMode() done
ServiceHost() destructor
ServiceHost() destructor done
ServiceProcess() destructor
ServiceProcess() destructor done
_terminate() destructor
_terminate() destructor done

mongrel_service.log:

Logfile created on 05.06.2008 09:51:06

native/mongrel_service.bas:44,
mongrel_service.singlemongrel.constructor:
redirecting to: c:\ruby\bin\mongrel.log

Not very helpful - OpenProcess fails with no apparent error.

I suggest you also try the psexec tool from Sysinternals and also
runas program (builtin in Windows) to get more detail information.

Could you please explain what you want me to do ? I think I have ran
everything I can using psexec and as the actual service user (explained
in my initial post). If there is something else, I will happily run it
:). On the other hand, since it works using these two methods, no error
message will appear. Only the service itself can not be started.

PATH reports from these environment will be help, also the security
bits from the ACLs too, since if it runs as administrator maybe there
is some file down there in your app (maybe log folder) that is not
allowed to be written in it.

The app is a newly generated rails skeleton, and the user has “Full
Control” on the directory and on the Ruby directory. I am not sure how I
can get to the PATH variable when starting the service - any idea ?

Thanks,
Ingmar

I digged a bit through the source code, and I am under the impression
that a normal user may not query the service control manager with
PROCESS_QUERY_INFORMATION. Could this be the case ?

_process_name does not return the name and _process_name_dyn_psapi fails
as well. (tested with 0.3.1 and 0.3.3). It looks like OpenProcess can
not be used in this manner…

In a totally unrelated project [1] I solved what I think you are trying
to do here differently:
I just pass the parameter “-runservice” from SCM in order to determine
if the application should run as service (called from SCM) or as a
normal console application. Maybe this would be an easier approach for
mongrel_service as well ?

I would create a proof of concept, but unfortunately, I am not
proficient with FreeBasic…

Bye,
Ingmar

[1] http://www.nwnx.org

On Thu, Jun 5, 2008 at 11:23 AM, Ingmar S. [email protected] wrote:

I digged a bit through the source code, and I am under the impression that a
normal user may not query the service control manager with
PROCESS_QUERY_INFORMATION. Could this be the case ?

Look at the source code for 0.3.4 you will find that a process can be
opened for readonly functions and perform PROCESS_QUERY_INFORMATION
without problems.

That worked on 32 and 64 bits versions of many Windows Servers and XP,
so shoudl work in your scenario too, unless that specific user lack
the permission to “run and control services” which you will need to
check with your sysadmin for that configuration.

Basically mongrel_service inherited code from other project named
ServiceFB, which is a framework we created for other purposes at the
office.

It worked without issues on lot of scenarios, and it automatically
determine the running environment so you avoid the requirement to
“analyze” the command line.

I would create a proof of concept, but unfortunately, I am not proficient
with FreeBasic…

Actually, it’s basic, there are not too many keywords to worry about
(ruby has more) and it’s like C, I mean, you don’t need to hack a lot
of stuff to go low level :slight_smile:

Bye,
Ingmar

HTH,

Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

Luis L. wrote:

On this ticket:

http://rubyforge.org/tracker/?func=detail&atid=5145&aid=10820&group_id=1306

You can use PsExec tool [1] to simulate another user and remove
administrative privileges for testing:

Yes, it works with psexec. And it works running as the service user. If
you have a look at my initial post, you can see the command line options
I used for testing (nothing special here).

You can search the mailing list and other tickets that explain how to
perform it (was discussed several times).

Can you provide the ‘sc queryex’ and ‘sc qc’ for your service and
pastie it here?

C:>sc queryex rails3

SERVICE_NAME: rails3
TYPE : 10 WIN32_OWN_PROCESS
STATE : 1 STOPPED
(NOT_STOPPABLE, NOT_PAUSABLE,
IGNORES_SHUTDOWN))

    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0
    PID                : 0
    FLAGS              :

C:>sc qc rails3
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: rails3
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 3 DEMAND_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : “c:/ruby/bin/mongrel_service.exe” single -e
develop
ment -p 3000 -a 127.0.0.1 -l “log/mongrel.log” -P “log/mongrel.pid” -c
“C:/rails
/x” -t 0 -r “public” -n 1024
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : rails3
DEPENDENCIES :
SERVICE_START_NAME : .\web

C:>

I’ve just tested this on another, totally different machine: Windows XP
Home Edition, German, Rails 2.1.0, restricted user account: No go.
Parent Name: .

Thanks for your efforts,
Ingmar

On Thu, Jun 5, 2008 at 10:11 AM, Ingmar S. [email protected] wrote:

ServiceHost()
Parent Name:

Logfile created on 05.06.2008 09:51:06

native/mongrel_service.bas:44, mongrel_service.singlemongrel.constructor:
redirecting to: c:\ruby\bin\mongrel.log

Not very helpful - OpenProcess fails with no apparent error.

Because it couldn’t get parent process name.

I suggest you also try the psexec tool from Sysinternals and also
runas program (builtin in Windows) to get more detail information.

Could you please explain what you want me to do ? I think I have ran
everything I can using psexec and as the actual service user (explained in
my initial post). If there is something else, I will happily run it :). On
the other hand, since it works using these two methods, no error message
will appear. Only the service itself can not be started.

On this ticket:

http://rubyforge.org/tracker/?func=detail&atid=5145&aid=10820&group_id=1306

You can use PsExec tool [1] to simulate another user and remove
administrative privileges for testing:

You can search the mailing list and other tickets that explain how to
perform it (was discussed several times).

Can you provide the ‘sc queryex’ and ‘sc qc’ for your service and
pastie it here?

[1] PsExec - Sysinternals | Microsoft Learn


Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

The thing is that looking at the initial post:

  1. Running the service with service user only in Users (or Power Users) group
    ===> DOES NOT WORK

This make me think that running as user is not working, but the thing
is is not actually working under LocalSystem account, I’m correct?

Sorry if that was not clear. It does work as service under LocalSystem
but it does not work as service under user “web”.

“C:/rails
/x” -t 0 -r “public” -n 1024
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : rails3
DEPENDENCIES :
SERVICE_START_NAME : .\web

SERVICE_START_NAME looks like web is the username used?

Yes, “web” is the restricted user.

I made a test application when this was shown the first time, can you
please try with it and provide me the output.

I’ve added a small INPUT “Press Enter.”, s line at the end. This is the
output:

runas /user:web proc_info.exe

*** CURRENT PROCESS ***
EnumProcessModules (PID, name): 3904 proc_info.exe
Module32First (PID, name): 3904 proc_info.exe
GetProcessImageFileName (PID, name): 3904
\Device\HarddiskVolume5\Temp\proc_info
.exe

*** PARENT PROCESS ***
EnumProcessModules (PID, name): 244 Error with OpenProcess
GetLastError: 5Zugriff verweigert

Module32First (PID, name): 244 Error Creating Snap
(SNAPMODULE)
GetLastError: 5Zugriff verweigert

GetProcessImageFileName (PID, name): 244 Error with OpenProcess
GetLastError: 5Zugriff verweigert

Press Enter.

Zugriff verweigert = Access denied.

I think this confirms my suspicion that the normal user “web” may not
query the parent process. What do you think ?

Bye,
Ingmar

On Thu, Jun 5, 2008 at 3:00 PM, Ingmar S. [email protected] wrote:

Press Enter.

Hmn, looks like user web user is too limited to do anything.

Zugriff verweigert = Access denied.

I think this confirms my suspicion that the normal user “web” may not query
the parent process. What do you think ?

How normal is normal? I mean, it can log in? it has applied some group
policy stuff in it?

Just for the sake of testing, can you create a “limited” account using
the control panel and try running proc_info.exe with it?

With that info maybe I can figure out what’s wrong.

Thanks for your time,

Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

On Thu, Jun 5, 2008 at 2:04 PM, Ingmar S. [email protected] wrote:

Yes, it works with psexec. And it works running as the service user. If you
have a look at my initial post, you can see the command line options I used
for testing (nothing special here).

The thing is that looking at the initial post:

  1. Running the service with service user only in Users (or Power Users)
    group
    ===> DOES NOT WORK

This make me think that running as user is not working, but the thing
is is not actually working under LocalSystem account, I’m correct?

can you provide me the cacls output form C:\rails\x folder?

  TYPE               : 10  WIN32_OWN_PROCESS

“C:/rails
/x” -t 0 -r “public” -n 1024
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : rails3
DEPENDENCIES :
SERVICE_START_NAME : .\web

SERVICE_START_NAME looks like web is the username used?

C:>

I’ve just tested this on another, totally different machine: Windows XP Home
Edition, German, Rails 2.1.0, restricted user account: No go. Parent Name:
.

I made a test application when this was shown the first time, can you
please try with it and provide me the output.

Thanks,


Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

On Thu, Jun 5, 2008 at 4:19 PM, Ingmar S. [email protected] wrote:

The “normal” user may run the whole rails stack as service without problems.
I hacked ServiceFB_Utils.bas to ignore the result of parent_name, and now it
works as expected (btw, you are right, FreeBasic isnt’ that hard :)) with
limited rights. The test was run on the isolated XP home machine, so no
group policies are in effect.

So, at the end, the ServiceHost automatic stuff didn’t do the trick,
which is a pain. I wrote that code to be more intelligent, but I think
Windows beat me, again :stuck_out_tongue:

Can you provide me your patch for ServiceFB library in google code?:

http://code.google.com/p/mmediasys-labs/

Just create a new issue and attach / paste your patch, I’ll really
appreciate get rid of this thing that, at the end, didn’t provide
anything but just bring pain to us (sniff) :stuck_out_tongue:

Hope this helps,
Ingmar

It really does!

Sorry for my late answer to this, been a bit hectic lately, but I’ll
really appreciate your code changes.


Luis L.
AREA 17

Human beings, who are almost unique in having the ability to learn from
the experience of others, are also remarkable for their apparent
disinclination to do so.
Douglas Adams

Luis L. wrote:

Hmn, looks like user web user is too limited to do anything.

Interesting: The result of proc_info.exe is different when I log in
interactively with the “web” user:

*** CURRENT PROCESS ***
EnumProcessModules (PID, name): 228 proc_info.exe
Module32First (PID, name): 228 proc_info.exe
GetProcessImageFileName (PID, name): 228
\Device\HarddiskVolume5\Temp\proc_info
.exe

*** PARENT PROCESS ***
EnumProcessModules (PID, name): 3312 cmd.exe
Module32First (PID, name): 3312 cmd.exe
GetProcessImageFileName (PID, name): 3312
\Device\HarddiskVolume1\WINDOWS\system
32\cmd.exe
Press Enter.

The previous attempt with “runas” had PID 244 as parent process id,
which at that time was “svchost.exe”. The full process hierarchy looked
like this (gathered with Process Explorer):

System - smss.exe - winlogon.exe - services.exe - svchost.exe -
proc_info.exe

It seems not to be only the user, but also the way the executeable is
started. The “web” user may query its parent process if it is cmd.exe,
but not if the parent is svchost.exe. I do not know how svchost starts
its child processes, but apparently with less rights than the command
shell does…

How normal is normal? I mean, it can log in? it has applied some group
policy stuff in it?

Just for the sake of testing, can you create a “limited” account using
the control panel and try running proc_info.exe with it?

With that info maybe I can figure out what’s wrong.

Thanks for your time,

The “normal” user may run the whole rails stack as service without
problems. I hacked ServiceFB_Utils.bas to ignore the result of
parent_name, and now it works as expected (btw, you are right, FreeBasic
isnt’ that hard :)) with limited rights. The test was run on the
isolated XP home machine, so no group policies are in effect.

Hope this helps,
Ingmar

On Jun 24, 2008 at 11:22 PM, Luis L. wrote:

So, at the end, the ServiceHost automatic stuff didn’t do the trick,
which is a pain. I wrote that code to be more intelligent, but I think
Windows beat me, again :stuck_out_tongue:

Can you provide me your patch for ServiceFB library in google code?:

Google Code Archive - Long-term storage for Google Code Project Hosting.

Sorry, I almost forgot about this.

I do not have a patch, really. I simpy commented out the call to
_process_name_dyn_psapi and always set RunAsService (instead of
RunAsUnknown):

 '# RunMode() provide a simple way to get (*you*) from where this 

process
was started
'# and do the corresponding action.
function ServiceController.RunMode() as ServiceRunMode
dim result as ServiceRunMode
dim currPID as DWORD
dim parent_pid as uinteger
dim parent_name as string
dim start_mode as string

     _dprint("ServiceController.RunMode()")

     '# get this process PID
     currPID = GetCurrentProcessId()
     _dprint("CurrentPID: " + str(currPID))

     '# get the parent PID
     parent_pid = _parent_pid(currPID)
     _dprint("ParentPID: " + str(parent_pid))

     '# now the the name
     parent_name = _process_name(parent_pid)
     '##if (parent_name = "<unknown>") then
     '##  parent_name = _process_name_dyn_psapi(parent_pid)
     '##end if
     _dprint("Parent Name: " + parent_name)

     '# this process started as service?
     '# that means his parent is services.exe
     if (parent_name = "services.exe") then
         result = RunAsService
     else
         '# ok, it didn't start as service, analyze command line 

then
start_mode = lcase(trim(command(1)))
if (start_mode = “manage”) then
'# start ServiceController.Manage()
result = RunAsManager
elseif (start_mode = “console”) then
'# start ServiceController.Console()
result = RunAsConsole
else
'# ok, the first paramenter in the commandline didn’t
work,
'# report back so we could send the banner!
'## (ing) Run service anyway:
'## result = RunAsUnknown
result = RunAsService
end if
end if

     _dprint("ServiceController.RunMode() done")
     return result
 end function

Just create a new issue and attach / paste your patch, I’ll really
appreciate get rid of this thing that, at the end, didn’t provide
anything but just bring pain to us (sniff) :stuck_out_tongue:

I do not know if this solves more problems than it opens up. Calling
mongrel_service.exe with no command line parameters just does nothing
with the
version I posted above - which is ok for me and works fine. I am not
sure if
this is an acceptable solution for everybody else, though …

Bye,
Ingmar