20 nov 2007

Problems launching VirtualBox in headless mode with ssh

I recently installed a VirtualBox image to run remotely using ssh. My command was:

VBoxVRDP -startvm "GuestOS" >~/VBoxVRDP.log 2>&1 &

inside the ssh session.

Whenever closed the ssh session, the virtual machine was killed. I thought it was a problem of the terminal, so I tried out screen and dtach. But the problem was remaining. Googling around, I finally found:
http://www.virtualbox.de/ticket/722
In effect, I had shared clipboard enabled. After I disabled it, I could finally start VirtualBox using:
ssh -x zope@192.168.11.201 'VBoxVRDP -startvm "GuestOS" >~/VBoxVRDP.log 2>&1 &'

Now, I'm a bit happier.
Cheers.

14 nov 2007

NTLM Authentication in Django

Recently I had to integrate NTLM Intranet authentication into a Django application. The first problem was to get mod_ntlm [1] to work in Ubuntu Feisty [2]. After this was done I had to configure my Samba as a Primary Domain Controller (PDC) and add my vmplayer WinXP instance to that domain [3] [4].

After that was done, I wrote a Django authentication backend based on [5].

What I did:
  1. Add a link to my customized registration/login.html page which points to a special location which is protected by mod_ntlm, e.g.:
    <a href="./remote_user/?next={{next}}">Intranet authentication</a>

  2. Configure this location in Apache2 for mod_ntlm:


    #NTLM Auth
    AuthName NTAuth
    AuthType NTLM
    NTLMAuth on
    NTLMAuthoritative on
    NTLMDomain DOMAIN
    NTLMServer pdc.sercer
    NTLMBasicAuth off
    # NTLMBasicRealm SISAM
    NTLMLockfile /tmp/_my.lck
    # NTLMBackup
    Require valid-user
    # Satisfy all

    Here, I suppose that all django mod_python config is already included in /.

  3. Write the authentication backend and a view that captures the "REMOTE_USER" environment variable, authenticates and logs in the user. Here is my "remoteuser.py":

    """User auth based on REMOTE_USER.
    To make it work you need:
    - add RemoteUserAuthBackend en settings.py, en AUTHENTICATION_BACKENDS
    - add ('/login/remote_user/', 'sisamapp.auth.remoteuser.remote_user_login') to your urls.py
    - enable the apache module (e.g. mod_ntlm)
    - configure Apache /login/remote_user/, e.g. for mod_ntlm:

    #NTLM Auth
    AuthName NTAuth
    AuthType NTLM
    NTLMAuth on
    NTLMAuthoritative on
    NTLMDomain DOMAIN
    NTLMServer MACHINE or IP
    # NTLMBasicAuth off
    # NTLMBasicRealm SISAM
    NTLMLockfile /tmp/_my.lck
    # NTLMBackup
    Require valid-user
    # Satisfy all

    We suppose here that the / location has already all django stuff configured (i.e. PythonHandler)
    """
    from django.contrib.auth.models import User

    import sys
    log = sys.stderr.write

    # copied from http://code.djangoproject.com/attachment/ticket/689/remote_user_2.diff
    from django.contrib.auth.backends import ModelBackend
    class RemoteUserAuthBackend(ModelBackend):
    def authenticate(self, **credentials):
    """
    Authenticate user - RemoteUserAuth middleware passes REMOTE_USER
    as username. password param is not used, just added in case :)
    """
    try:
    type = credentials['type']
    if type == "remote_user":
    username = credentials['username']
    except:
    username = None
    if not username:
    return None
    user = None
    try:
    user = User.objects.get(username=username)
    except User.DoesNotExist:
    raise User.DoesNotExist, _T('User %s not configured in this application.') % username
    return user

    class NoRemoteUserInfoAvailable(Exception):
    pass


    from django.http import HttpResponseRedirect
    from django.shortcuts import render_to_response
    from django.template import RequestContext
    import re
    from django.utils.translation import ugettext as _T
    def render_notice(request, errornote, msg):
    return render_to_response('registration/notice.html',
    {'errornote': errornote, 'msg': msg },
    context_instance = RequestContext(request))

    def remote_user_login(request):
    error = """
    remote_user_login requires Django authentication middleware to be installed. (Include in MIDDLEWARE_CLASSES setting 'django.contrib.auth.middleware.AuthenticationMiddleware'.
    """
    msg = _T('Use the __standard login form__ to provide alternative credentials.')
    msg = re.sub('__(.*)__',r'<a href="../?next=%s">\1</a>' % request.GET.get('next',''), msg, re.UNICODE)
    try:
    username = request.META['REMOTE_USER']
    log("Got REMOTE_USER=%s\n" % username)
    except:
    return render_notice(request,
    errornote=_T('Server does not provide REMOTE_USER.'),
    msg=msg)
    if not username:
    return render_notice(request,
    errornote=_T('Could not get your credentials. Are you accessing from anywhere outside the domain or a browser that does not support intranet authentication?'),
    msg=msg)
    from django.contrib.auth import authenticate, login
    # AuthenticationMiddleware is required to create request.user
    assert hasattr(request, 'user'), self.error
    if request.user.is_anonymous():
    log("Request is anonymous. Trying to authenticate user %s\n" % username)
    try:
    user = authenticate(username=username, type="remote_user")
    except:
    user = None
    log("User is %s\n" % user)
    if user is not None:
    request.user = user # set request.user to the authenticated user
    login(request, user) # auto-login the user to Django
    return HttpResponseRedirect(request.GET.get('next','/'))
    return render_notice(request,
    errornote=_T('Your username (%s) is not registered here.') % username,
    msg=msg)
    # user is already authenticated, should logout first
    msg = _T('You have to logout first using __this link__ before logging in again.')
    msg = re.sub('__(.*)__',r'<a href="../../logout/">\1</a>', msg, re.UNICODE)
    return render_notice(request,
    errornote=_T('You are already authenticated.'),
    msg=msg)

    Some notes here:

    • remote_user 'authenticate' uses explicitly another signature as ModelBackend 'authenticate', i.e. it needs the 'type' argument. If you used the same signature (username, password) there is a possibility that a user authenticates without any password!
    • In my configuration, when I acces with Firefox/Linux /login/remote_user/, a browser authentication dialog pops up. I was not able to get rid of it.

    Links:
  1. http://modntlm.sourceforge.net/
  2. http://erny-rev.blogspot.com/2007/11/compiling-modntlm-for-apache2-in-ubuntu.html
  3. http://geeklab.wikidot.com/samba-pdc
  4. http://us1.samba.org/samba/docs/man/Samba-HOWTO-Collection/domain-member.html#machine-trust-accounts
  5. http://code.djangoproject.com/attachment/ticket/689/remote_user_2.diff

13 nov 2007

Compiling mod_ntlm for Apache2 in Ubuntu Feisty


  1. Do a checkout
    svn co https://modntlm.svn.sourceforge.net/svnroot/modntlm/trunk/mod_ntlm2

  2. install apache-developer files:
    sudo aptitude install apache2-prefork-devel 

  3. cd into mod_ntlm2 and edit Makefile:
    APXS=apxs2
    APACHECTL=apache2ctl

  4. edit mod_ntlm.c:
    replace
    apr_pool_sub_make(&sp,p,NULL);
    with
    apr_pool_create_ex(&sp,p,NULL,NULL);

    As of this post, apr_pool_sub_make is deprecated and was removed. Use apr_pool_create_ex instead.

  5. make (there's a warning about log function). Do not 'make install' here. (it doesn't find mod_ntlm.so and it adds LoadModule to httpd.conf instead of using new-style module loading mechanism.

  6. copy it to apache2 modules dir:
    sudo cp .libs/mod_ntlm.so /usr/lib/apache2/modules/

  7. create file /etc/apache2/mods-available with sudo:
    LoadModule ntlm_module /usr/lib/apache2/modules/mod_ntlm.so

  8. configure some location or directory which needs authentication:
           #NTLM Auth
    AuthName NTAuth
    AuthType NTLM
    NTLMAuth on
    NTLMAuthoritative on
    NTLMDomain DOMAIN
    NTLMServer your.dc.here # or IP
    NTLMLockfile /tmp/_my.lck
    # NTLMBackup your.dc-backup.here
    require valid-user

  9. reload apache2:
    sudo /etc/init.d/apache2 force-reload

See:

4 nov 2007

Hibernate with Ubuntu Feisty

Hibernate never worked for me using Ubuntu. Now, I'm using Dell Inspiron 8600 and upgraded recently to Ubuntu Feisty. What I did for hibernate to work:


  1. Make sure swap device works correctly. Now there isn't /dev/hd[x] anymore. This has been renamed to /dev/sd[x]. I recreated my swap partition:

    $ sudo swapoff -a # disable swap devices
    $ sudo mkswap /dev/sda3 # recreate my swap partition

    # edit /etc/fstab, make sure to use /dev/sd... My line is:
    /dev/sda3 none swap sw 0 0

    $ sudo swapon -a # enable swap again
    $ sudo swapon -s # see swap devices used
    Filename Type Size Used Priority
    /dev/sda3 partition 1044216 0 -1


  2. Install uswsusp. Kernel driver included in standard Linux 2.6.
    $ sudo apt-get install uswsusp


    You should see a configuration screen, but if it was already installed or no configuration appears, do a:
    $ sudo dpkg-reconfigure uswsusp


    1. The device node through which uswsusp can talk to the kernel: leave blank
    2. Perform checksum on image? No
    3. Compress Image? Yes
    4. Perform early write out? Yes
    5. Preferred maximum image size: proposed value (mine is 600 MB, depends on your RAM)
    6. Log level: Leave blank
    7. Maximal log level: Leave blank
    8. Encrypt image? No

    The config file /etc/uswsusp.conf is written and the initrd images are updated.
    Check this configuration file a see if resume device is accurate. If not, change it and do a:
    $ sudo update-initramfs -u -k all

    Now, s2disk should work correctly. This is the suspend 2 disk command. Try it! But, "hibernate" command and gnome "Log out" screen hibernate option may not work.

  3. Configure hibernate to use uswsusp. Edit the /etc/hibernate/hibernate.conf. Just comment out all lines except:
    TryMethod disk.conf

    Now hibernate may work. (You need sudo.) But gnome desktop utilities may not. Gnome signals through hal that it should hibernate the computer, but the default file /usr/lib/hal/scripts/linux/hal-system-power-hibernate-linux uses pmi (power management interface). As some links tell, you can replace it with a version that tries to use s2disk before any other option. Google for: "feisty hibernate hal" and you'll find alternate scripts.

    Now the gnome-power-manager and logoff screen "hibernate" option should work.

  4. If the power button does not work, do:
    $ sudo apt-get install --reinstall acpi-support



For me, at this point hibernate support is perfect.
Cheers.