phaqphaq

“a geeks daily life”

Archive for January, 2008

Killing a Windows Terminal Session from remote

Friday, January 25th, 2008

Darn it!
Imagine what happens when a Windows box, which is configured for remote administrative terminal mode only, is left with two zombie terminal sessions.

Maybe you are lucky, and Terminal Services Manager does the job for you. In theory, one might connect another host for management purposes.
In case your administrative credentials are different from the ones on the destination host, Terminal Services Manager might throw an insufficient permissions error at you.

So it was in my case, which I worked around like this:

First I opened up a command shell (Start – Run – cmd + OK), from which I ran this command:

C:\\Documents and Settings\\Administrator>net use o: \\\\192.168.13.205\\c$ /user:Administrator

The password or user name is invalid for \\\\192.168.13.205c$.

Enter the password for 'Administrator' to connect to '192.168.13.205':

The command completed successfully.

This asked me for the credential of the remote system’s Administrator
and connected it’s shared C: drive to my system.
In fact, connecting the share isn’t required, everything else works too, as long as you’re prompted to enter the credentials for the remote systems.
In my experience, connecting a share proved to work out properly in most cases.

So afterwards, I ran this command to list the remote server’s terminal sessions:

C:\\Documents and Settings\\Administrator>qwinsta /server:192.168.13.205
 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 console                                     0  Conn    wdcon
 rdp-tcp                                 65536  Listen  rdpwd
 rdp-tcp#10        Administrator             2  Active  rdpwd
 rdp-tcp#16        Administrator             3  Active  rdpwd

So, to kill any or all of these sessions, run this command:

C:\\Documents and Settings\\Administrator>rwinsta rdp-tcp#10 /server:192.168.13.205

It’s also possible to kill a session by it’s ID, which works like this:

C:\\Documents and Settings\\Administrator>rwinsta 3 /server:192.168.13.205

Let’s check out if our zombie sessions are gone now:

C:\\Documents and Settings\\Administrator>qwinsta /server:192.168.13.205
 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 console                                     0  Conn    wdcon
 rdp-tcp                                 65536  Listen  rdpwd

So it looks good after all, the sessions are gone and I can reconnect the server using rdpclient as usual.

So let’s disconnect the share now, as in fact it wasn’t used for anything except to store the credential.

C:\\Documents and Settings\\Administrator>net use o: /delete
o: was deleted successfully.

By the way, if you don’t want to encounter these hassles over and over again, terminal server can be configured to automatically terminatate stale/inactive sessions.
Find more about this in the Microsoft Knowledge Base.

An AutoFS executable map to automount device nodes

Thursday, January 24th, 2008

For my company’s hard disk-based backup system I needed the ability to automount disk drives by their device name into a standard directory structure.

One possible approach would be to add some lines like these to fstab:

/dev/sda1       /mnt/sda1       ext3    defaults,noauto 0       0

This may be good enough in some cases, though it wasn’t sufficient for me, when there were dozens of device nodes which could get mounted eventually.

So I basically wanted something that would allow me to just access a directory, while the underlying disk was mounted automatically, then having it unmounted automatically if not in use, but still being dynamic in it’s nature so it would auto-adjust.

Now there’s a simple trick using an AutoFS feature called “executable maps”, which would allow me to achive this all.

The idea is, that all devices (let’s say /dev/sda1, /dev/sda2, /dev/sdb1, /dev/sdc1 as an example) will get mounted to /mnt/disks/[devicename].

First make sure, that AutoFS is installed. On Debian for example, it is installed like this:

apt-get install autofs

Then create a file called /etc/auto.disks with the following lines therein:

#!/bin/bash

# $1 is passed-over from automount
# key refers to the mount point we are looking for
key="$1"

# default mount options
opts="-fstype=ext3,rw"

# if a block device exists at /dev/[key]
# pass it back to automount
[ -b /dev/${key} ] && { echo "$opts \"; echo -e "t:/dev/${key}"; }

Don’t forget to chmod 755 /etc/auto.disks.

This script will create an automounter map dynamically as soon as it passed
a device node. It it finds it (e.g. while looking up /dev/sda1, which exists), it’ll
return the map to automount, which will cause the device node to be mounted.

In my case, the script didn’t need to be very sophisticated as I only have ext3-formatted disks, but it’s easy to script it for automatic file system recognition.

Btw, the script can be tested like this to see if it’s actually working:

satyr:~# bash /etc/auto.disks sda1
-fstype=ext3,rw
        :/dev/sda1
satyr:~# bash /etc/auto.disks sdx1

The first command returns the map for an existing device node /dev/sda1, while the second command returns nothing as /dev/sdx1 doesn’t exist on the system.

Now set AutoFS to use the executable map for /mnt/disks directory. Add this line to /etc/auto.master:

/mnt/disks  /etc/auto.disks --timeout=360

This will cause AutoFS to examine the executable map on all requested sub directories beneath /mnt/disks. So if you’re going to access /mnt/disks/sda1, /mnt/disks/sda2, /mnt/disks/sdb1, /mnt/disks/sdc1, the block devices corresponding to the directories are mounted automatically — as long as the devices exist of course.

The timeout value designates after how much time (of inactivity) an automounted file system expires and get’s unmounted.

Apple’s Safari violates RFC2616

Wednesday, January 23rd, 2008

Today I faced an issue, where HTTP redirections didn’t work out as expected on Apple’s Safari browser.

This came up while I was coding up some sort of web-based login redirector, which is stacked up in three layers:

  1. html login form
  2. login preprocessor (server side scripting)
  3. login processor (server side scripting)

This solution was required to implement a generic way to create branded login forms, which will send their login requests to a unique, centralized login preprocessor, which will – after doing some internal magic – redirect to the final login processor.

Now, the login preprocessor was set to do redirects to the final login processor using HTTP/1.1 temporary redirects (http reply code 307) to preserve already existing POST data.
While this was working out properly on most browser, I stumbled accross Safari, which will silently discard all POST data.

Checking out the access logs revealed some interesting facts.
The first excerpt shows the access as performed by Firefox:

192.168.0.2 - - [23/Jan/2008:16:32:02 +0100] "POST / HTTP/1.1" 307 20 "https://xyz/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"
192.168.0.2 - - [23/Jan/2008:16:32:05 +0100] "POST /some_other_location HTTP/1.1" 200 7934 "https://xyz/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"

As required by the 307 temporary redirect Firefox will resubmit to the new location using a POST request (preserving existing POST data).
The first request actually refers to stage 2 (login preprocessor), the second request reflects the resubmission to the final login processor (step 3).

Now this is was Safarie does:

192.168.0.3 - - [23/Jan/2008:16:31:26 +0100] "POST / HTTP/1.1" 307 20 "https://xyz" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE) AppleWebKit/523.15 (KHTML, like Gecko) Version/3.0 Safari/523.15"
192.168.0.3 - - [23/Jan/2008:16:31:26 +0100] "GET /some_other_location HTTP/1.1" 200 7931 "https://xyz" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE) AppleWebKit/523.15 (KHTML, like Gecko) Version/3.0 Safari/523.15"

As we can see, it also receives a 307 temporary redirect from the server and follows it (which is correct as of RFC2616) in the first request (again step 2 as outlined before).
However, the second request is resubmitted using GET, which means that all previously existing POST data is lost (this is step 3 as outlined before).

In this case, Safari clearly violates RFC2616, which states in Chapter 10.3.3 302 Found:


RFC 1945 and RFC 2068 specify that the client is not allowed
to change the method on the redirected request. However, most
existing user agent implementations treat 302 as if it were a 303
response, performing a GET on the Location field-value regardless
of the original request method. The status codes 303 and 307 have
been added for servers that wish to make unambiguously clear which
kind of reaction is expected of the client.

As a side note to this excerpt from the RFC I shall note, that status code 302 Found as referred-to by RFC2616 used to be
302 Moved Temporarily (as of RFC2068), which has been redefined to 307 Temporary Redirect.

As such, while status code 303 See Other clearly states, that GET should be used upon redirect, statements made in
RFC2616’s Chapter 10.3.3 302 Found also apply to 307 Temporary Redirect.

In this case it means, that Safari violates the standard when it changes the access request method to GET.