Thursday, September 25, 2008

Run shell command in Ruby

Ruby supports the typical ways to run shell command - exec, system and backticks (``). You can google search and get info on them. Its pretty easy. This post is for those who tried these methods and still want more than what they provide. The issue with those methods are they do not give us stdout, exit-status and stderr easily.

So I recommend using open4 instead.

Here is how you do it :-

1. gem install open4
2. cd /usr/lib/ruby/gems/1.8/gems/open4-0.9.6/ (or whatever version you got)
3. ruby install.rb (to install open4. This copies open4.rb file into your ruby lib)
4. Write your code similar to the one below :-

require "open4"
pid, stdin, stdout, stderr = Open4::popen4 "sh"
stdin.puts "mount -t cif //172.20.30.18/write_shared /mnt/cifs -o user=name1,password=password1"
stdin.close
ignored, status = Process::waitpid2 pid
puts "pid : #{ pid }"
puts "stdout : #{ stdout.read.strip }"
puts "stderr : #{ stderr.read.strip }"
puts "status : #{ status.inspect }"
puts "exitstatus : #{ status.exitstatus }"

output:-

pid : 6441
stdout :
stderr : mount: unknown filesystem type 'cif'
status : #
exitstatus : 32


This is what this code does. It opens a shell and gives the mount command to its stdin. So its like you manually opening a shell and typing in the command there. The pid, output, error and status is now available in pid, stdin, stdout and stderr.

In my code I deliberately made a mistake of mount type cif instead of cifs. So It gives me the error in stderr and the exit code 32.

To do the same trick on Windows, use popen4. Here is the link to it. Click on the Class and you will get a sample code also.


After a lot of days, here I found a better way of doing the same thing. Instead of using "open4", use "systemu". I had to look for alternatives, because one day all of a sudden my code written using open4 started hanging. So I searched and found "systemu". This is more elegant and easier to do.

Install systemu using gem install and goto its directory in /usr/lib/ruby/gems and then run "ruby install.rb". Once the installation is over, use it as follows :-

require 'systemu'
cmd="date"
status, stdout, stderr = systemu cmd

Tuesday, September 16, 2008

Running PHP on 64 bit Windows

Today I was trying to get this working. Googling intially didn't help me much and I thought probably this is not possible. The fact is it is possible. Here is how you do it. I assume you have already installed php. I had php5 installed on Windows 2003 server SP1 64-bit.

First, You need to get IIS run with 32 bit application. For this run the following command :-

cd c:\Inetpub\AdminScripts\
adsutil.vbs set W3SVC/AppPools/Enable32bitAppOnWin64 1

Restart IIS with "iisreset" command on command-line

Now, when I tried accessing my php page, it gave me "Service Unavailable".

To resolve this, we have to first de-register ASP.Net framework before setting the above parameter - Enable32bitAppOnWin64 to 1.

To deregister ASP.Net ,
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -u
Start uninstalling ASP.NET (2.0.50727).

.
Finished uninstalling ASP.NET (2.0.50727).

Now run, the above command to set Enable32bitAppOnWin64 to 1.

cd c:\Inetpub\AdminScripts\
adsutil.vbs set W3SVC/AppPools/Enable32bitAppOnWin64 1


Now to re-register,

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -i
Start installing ASP.NET (2.0.50727).
.................................
Finished installing ASP.NET (2.0.50727).

Now do , iisreset

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>iisreset

Attempting stop...
Internet services successfully stopped
Attempting start...
Internet services successfully restarted

Now access your php page and it should work.

Kerberos authentication for IIS

Required tools :-

setspn - For adding/deleting/listing SPN entries
kerbtray - For checking the list of kerberos tickets granted. This will help us to know if kerberos is working. Get this from here
Wireshark - Another way to find out if kerberos is working

Use IE 7.0 if you want to avoid lot of pain. Also, its better to run kerberized site on port 80.

This scenario is where we need backend to be kerberos enabled. So when we access the site the authentication will be done silently using kerberos.

The sample setup I had

Server - myserver.xyz.com
Client - client0

Here are some prerequisites -

client0 should be in the same domain as the Server (myserver). In my case myserver itself was the domain controller. So I had DC and IIS on the same machine.
myserver name is resolvable from the client. In my case myserver also had DNS running which resolved the name myserver So client was set to use DNS server as myserver

Create a domain user (say user1) and login to client machine using the domain user login. In my case, logged into client using user1 credentials.

Settings to be done at IIS side

1. Open IIS manager
2. Click the Directory Security or File Security tab, and then, in the Authentication and access control section, click Edit.
3. In the Authenticated access section, select the Windows Integrated Authentication check box.
4. Click OK

Now, in IIS manager click on Websites node and check the identifier for the website to be "kerberized". In my case it is 694446059.

Use the following command

C:\Inetpub\AdminScripts>cscript adsutil.vbs get w3svc//root/NTAuthenticationProviders (replace identifier by your site identifier. In my case 694446059)

and verify that it gives the parameter "NTAuthenticationProviders" set to "Negotiate". If not set it to Negotiate by

C:\Inetpub\AdminScripts>cscript adsutil.vbs set w3svc//root/NTAuthenticationProviders "Negotiate"

Now we need to set SPN. SPN is in the following format

SPN:HTTP/<fqdn> <iis computer-name>


Set the SPN using "setspn -A <SPN>" command. In my case,

setspn -A HTTP/myserver.xyz.com myserver


Settings to be done on Domain Controller (DC):

I didn't find these setting necessary but it is mentioned in some websites.

- Under Active Directory Users and Computers -> -> Computers, Select the web server, right click ->Properties
Make sure that "Trust Computer for delegation" is selected.

- Domain account (user1) is trusted for delegation
- Is a member of IIS_WPG group on the local IIS computer
- Has "Act as a part of Operating System"/"Impersonate a client after authentication" privileges.


Settings on IE:
- Add the URL to "Local Intranet Zone". In IE 7.0, you just need to have "Automatically detect intranet Sites" checked under Tools->internet Options -> Security->Sites
-Under Tools -> Internet Options -> Advanced Tab
enable Integrated Windows Authentication

Now login to client as domain user and checkout the website. If kerberos is setup correctly no password would be asked and you should get the website. If password is asked it means Windows is falling back to NTLM.

To verify that kerberos is actually being used, you may use the kerbtray tool.
Double click on the kerbtray tool. A green icon comes up in the system tray.
Right click on the icon and say list tickets. It should list ticket granted to http service and the details of it.

You may also run wireshark while accessing the website and filter the traffic by http later. Open the HTTP section of the packet and look for keywords GSS-API and SPNEGO.

Wednesday, September 10, 2008

The local policy of this system does not permit you to logon interactively

I got this error today when I tried to login by rdesktop to a machine in my domain using the domain user account. Yes, the machine B is part of the domain xyz.com whose domain controller is machine A. Let us say the account name is user1.

The first thing I did was to be sure that the username user1 is not there in “Deny logon through Terminal Services” and "Deny log on locally" policies.

1. Goto machine B
2. Start -> Run and type secpol.msc and enter
3. Ensure that user1 is not in the above policies under "Local Policies".

No, its not there. So now what next ? Ok..let me first try with a local user. I tried adding a local user named testuser1 and also verfied it is not there in above policies. Tried rdesktop to machine B with the local username. Again the same error. Ok, so now local user is also not able to login and get the same error. Check secpol.msc once again. Did I miss something ?

Yes..Found something - "Allow logon through terminal services". Added the user testuser1 into this and tried login.

Cool !! It went one step ahead. No more of the same error. But a new error came up. "User does not access to logon to this session". Did some googling and found that I need to add testuser1 to "Remote Desktiop users" group. Ok, added user to this group.

Tried logging in again as testuser1. Voila ! it worked. testuser1 who is the local user is now able to login using rdesktop.

Now, I got to get the same thing done for domain user.

Log on to machine A (domain controller) Added user user1 to "Allow logon through terminal services". Now add xyz\user1 to "Remote Desktop User" group - right ? Yes...

Open up the Start->Administrative Tools->Active Directory Users and Computers->Computers, right click on computer B,
click Manage Computer
Go to "System Tools" -> "Local Users and Groups" -> Groups
Open "Remote Desktop Users" group and click the "ADD" button and add the user as xyz\user1

Now login to machine B using the domain user name user1 into the xyz domain and it works !! .