Thursday, December 26, 2013

ASUS USB-N10 Nano on OpenSuse 13.1 Linux

Today I bought myself a wifi adapter for my Opensuse desktop PC. I was tired of running a network cable across the carpet to my modem.

The model I bought was an ASUS USB-N10 Nano from PB Technologies in Henderson. It was less than $20 so I thought a good deal. When I bought it, I completely ignored all the printed garbage about support for Windows and Mac and figured, that it will be supported under linux.

It is supported under Linux but it was not too simple to set up on my Opensuse.

In the end and after much google-ing, I found this repository:
https://github.com/pvaret/rtl8192cu-fixes

The driver that ships with the kernel is not so hot. The network keeps dropping even though it appears to remain connected. With this version, things are much more stable.

Also it compiles nicely under the latest kernel. The proprietry driver from Realtek did not compile under the kernel shipped with Opensuse 13.1.

So here is what I ended up doing:

~ git clone https://github.com/pvaret/rtl8192cu-fixes.git
~ su - (become root)
# zypper in dkms kernel-devel kernel-headers gcc make
# cd /path/to/git/repo... (you get the picture)
# cd ../ (go to directory above tree) on my system I put this source tree under /usr/local/src/
# dkms add rtl8192cu-fixes
# dkms install 8192cu/1.8
# depmod -a
# cp blacklist-native-rtl8192.conf /etc/modprobe.d
# echo "options 8192cu rtw_power_mgnt=0 rtw_enusbss=0" > /etc/modprobe.d/50-8192cu.conf
# reboot

And that's it. Now if the kernel is ever updated during normal patching, dkms will recompile our driver.

EDIT:
I have made an RPM package for this driver. It's hosted on the openSUSE build service. Currently I have successfully managed to create rpm's for Centos, Redhat and Fedora (x86_64) only. The openSUSE one failed because the build environment does not have DKMS installed and so the install test fails at the very end.
Anyway - find the packages here: https://build.opensuse.org/package/show/home:linuxplayground/8192cu-1.8

so the openSUSE version is here: 8192cu-1.8-1.0.x86_64.rpm

These RPM packages will:
  • save the source in /usr/src/8192cu-1.8
  • Add the source tree to DKMS
  • Build the kernel module using dkms build ...
  • Install the kenrel module using dkms install ...

To uninstall the module and all the dkms source, builds and modules then just execute: #rpm -e 8192cu
:-)

Friday, December 20, 2013

Restrict Commands executed via pre-shared SSH keys

Introduction

Using pre-shared SSH keys is a great way to make logging into remote hosts quick and easy.  No pesky passwords to remember.  The downside is that if your organization relies on passwords for access control, the pre-shared key will negate any password control you have.  For example: If your organization rolls a password for a system account, and the new password is not shared with all the original people, then some people who should not have access any more will continue to have access via their pre-shared key.
Also, anyone with access to a user's account on a client host, could access the system account via the pre-shared key on the remote host.  This is not ideal.

Sometimes, it is neccessary to allow certain commands only to be executed over SSH from specified client hosts without a password.  Especially when thinking about automated tasks.

In my examples, I will demonstrate how we can create a simple remote procedure call type scenario using pre-shared keys and some built in linux security tools that lock things down.

These examples will use the "oracle" user which has been set up on both the client and remote hosts identically.
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

The Steps

Create the public private key on the private host

Use ssh-keygen to create a public/private key pair without a password.
[oracle@centos-dev-1 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/oracle/.ssh/id_rsa): [ENTER]
Created directory '/home/oracle/.ssh'.
Enter passphrase (empty for no passphrase): [ENTER]
Enter same passphrase again: [ENTER]
Your identification has been saved in /home/oracle/.ssh/id_rsa.
Your public key has been saved in /home/oracle/.ssh/id_rsa.pub.
The key fingerprint is:
64:cf:72:de:f7:85:af:fe:36:87:ce:8c:6e:31:8d:ed oracle@centos-dev-1.vbox.local
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|        o        |
|       o o       |
|        S +  +   |
|         + .+ o. |
|          . .+o..|
|            .=E++|
|           ooo*+*|
+-----------------+
[oracle@centos-dev-1 ~]$ ls -l .ssh/
total 8
-rw-------. 1 oracle oinstall 1675 Dec 20 10:33 id_rsa
-rw-r--r--. 1 oracle oinstall  412 Dec 20 10:33 id_rsa.pub

Share the public key to the remote host

You can use the ssh-copy-id tool or you could manually do it. I will use the ssh-copy-id tool to share the key.
[oracle@centos-dev-1 ~]$ ssh-copy-id -i /home/oracle/.ssh/id_rsa.pub oracle@centos-dev-2
The authenticity of host 'centos-dev-2 (192.168.56.102)' can't be established.
RSA key fingerprint is df:87:48:48:0a:15:fa:ca:e4:a7:41:8e:9e:af:19:b5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'centos-dev-2,192.168.56.102' (RSA) to the list of known hosts.
oracle@centos-dev-2's password: 
Now try logging into the machine, with "ssh 'oracle@centos-dev-2'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

[oracle@centos-dev-1 ~]$ ssh oracle@centos-dev-2
Last login: Thu Dec 19 13:38:03 2013 from centos-dev-1.vbox.local
[oracle@centos-dev-2 ~]$ hostname
centos-dev-2.vbox.local
[oracle@centos-dev-2 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-2 ~]$ exit
logout
Connection to centos-dev-2 closed.
At this point, we have successfully enabled transparent ssh logins using a pre-shared public key from centos-dev-1 to centos-dev-2 as the "oracle" user.


The result was a file created on the remote host called /home/oracle/.ssh/authorized_keys which looks like this:
[oracle@centos-dev-2 ~]$ hostname
centos-dev-2.vbox.local
[oracle@centos-dev-2 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-2 ~]$ cd /home/oracle/.ssh/
[oracle@centos-dev-2 .ssh]$ ls -l
total 4
-rw-------. 1 oracle oinstall 412 Dec 20 10:35 authorized_keys
[oracle@centos-dev-2 .ssh]$ cat authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqdZI3PbacEoZ4uIk1hIc9Tl2pmLZtv0Y1/ZowqNOLRRQV84ziiNXoUXa8y+x9DxMzIPxKHdyYy0k0HFl06oIjfP4l3P3GY9L0MM/oYxYNr0UaJz46hDy7p3cKVjmeY/Xn3PsepNY3kAdp4zdNb1Hfs9G/PiB70LTfseJZjqwBJ6edYAt7YztWuO9OgrmDoW7QAdsPTlQGF9iW0gUqH/1UA5hXtGePRq2My9ahXmXOu1hy3H1wFygCBZaxP7A3qohgvVIT76DQ1mxhgLDiQCVkTzxVhHgMmVi4A7C0vpr2G5WxpLblVHWpjnXn/eAdQBQLnFtj/pza1U5K3Dy/GDxMQ== oracle@centos-dev-1.vbox.local

Restrict the public key on the remote host

Here we edit the /home/oracle/.ssh/authorized_keys file that was created in the previous step to include some restrictions for the key. We prepend the following to the key:
from="centos-dev-1.vbox.local",command="/usr/local/bin/remote-commands.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty 
The key now looks like this:
from="centos-dev-1.vbox.local",command="/usr/local/bin/remote-commands.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqdZI3PbacEoZ4uIk1hIc9Tl2pmLZtv0Y1/ZowqNOLRRQV84ziiNXoUXa8y+x9DxMzIPxKHdyYy0k0HFl06oIjfP4l3P3GY9L0MM/oYxYNr0UaJz46hDy7p3cKVjmeY/Xn3PsepNY3kAdp4zdNb1Hfs9G/PiB70LTfseJZjqwBJ6edYAt7YztWuO9OgrmDoW7QAdsPTlQGF9iW0gUqH/1UA5hXtGePRq2My9ahXmXOu1hy3H1wFygCBZaxP7A3qohgvVIT76DQ1mxhgLDiQCVkTzxVhHgMmVi4A7C0vpr2G5WxpLblVHWpjnXn/eAdQBQLnFtj/pza1U5K3Dy/GDxMQ== oracle@centos-dev-1.vbox.local
The extra options are broken down as follows:

  • from="centos-dev-1" Only allow this key to be used when connections are made from centos-dev-1 host.
  • command="/usr/local/bin/remote-commands.sh" This is a script that will be executed by the owner of this key (oracle) whenever the key is used to establish an ssh connection. We will write the script soon.
  • no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty These options add extra security and prevent the key being used for anything other than running the command specified in command="".
None of this is very useful if the oracle user can simply log into the host using his password and edit this file. Use the chattr command to lock the file for editing as follows: (NOTE: Only the root user can do this)
[root@centos-dev-2 ~]# hostname
centos-dev-2.vbox.local
[root@centos-dev-2 ~]# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@centos-dev-2 ~]# lsattr /home/oracle/.ssh/authorized_keys 
-------------e- /home/oracle/.ssh/authorized_keys
[root@centos-dev-2 ~]# chattr +i /home/oracle/.ssh/authorized_keys 
[root@centos-dev-2 ~]# lsattr /home/oracle/.ssh/authorized_keys 
----i--------e- /home/oracle/.ssh/authorized_keys
[root@centos-dev-2 ~]# rm /home/oracle/.ssh/authorized_keys 
rm: remove regular file `/home/oracle/.ssh/authorized_keys'? y
rm: cannot remove `/home/oracle/.ssh/authorized_keys': Operation not permitted
[root@centos-dev-2 ~]# ls -l /home/oracle/.ssh/authorized_keys 
-rw-------. 1 oracle oinstall 551 Dec 20 10:41 /home/oracle/.ssh/authorized_keys
[root@centos-dev-2 ~]# su - oracle
[oracle@centos-dev-2 ~]$ cat .ssh/authorized_keys 
from="centos-dev-1.vbox.local",command="/usr/local/bin/remote-commands.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqdZI3PbacEoZ4uIk1hIc9Tl2pmLZtv0Y1/ZowqNOLRRQV84ziiNXoUXa8y+x9DxMzIPxKHdyYy0k0HFl06oIjfP4l3P3GY9L0MM/oYxYNr0UaJz46hDy7p3cKVjmeY/Xn3PsepNY3kAdp4zdNb1Hfs9G/PiB70LTfseJZjqwBJ6edYAt7YztWuO9OgrmDoW7QAdsPTlQGF9iW0gUqH/1UA5hXtGePRq2My9ahXmXOu1hy3H1wFygCBZaxP7A3qohgvVIT76DQ1mxhgLDiQCVkTzxVhHgMmVi4A7C0vpr2G5WxpLblVHWpjnXn/eAdQBQLnFtj/pza1U5K3Dy/GDxMQ== oracle@centos-dev-1.vbox.local
As you can see, once this attribute is set on the file, not even the root user can edit or delete it. The root user will first need to remove the "immutable" attribute with "chattr -i /home/oracle/.ssh/authorized_keys".

The oracle user can still read the file which is a requirement of the SSH daemon.

Write a command parser on the remote host

This script will parse the command sent by the ssh client and execute based on some simple tests.
[oracle@centos-dev-2 ~]$ ls -l /usr/local/bin/remote-commands.sh 
-rwxr-xr-x. 1 root root 315 Dec 19 13:30 /usr/local/bin/remote-commands.sh
[oracle@centos-dev-2 ~]$ cat /usr/local/bin/remote-commands.sh 
#!/bin/sh
#
if [ -z "${SSH_ORIGINAL_COMMAND}" ]; then
        echo "This script can only be executed via SSH remote calls"
        exit
fi

case "$SSH_ORIGINAL_COMMAND" in
  "get hosts")
    cat /etc/hosts
    ;;
  "get resolv.conf")
    cat /etc/resolv.conf
    ;;
  "get env")
        env
        ;;
  *)
   echo "Bad Command" 
    ;;
esac
exit
The script is owned by root:root but all users have read and execute permissions on the script.



That's it! We are ready to begin our tests now.

Test

The script we write allows clients to execute 3 commands:
  • get hosts
  • get resolv.conf
  • get env
Any other command will be rejected.

Using the key to establish an ssh connection without passing a command will be rejected. So logins are now disabled.
Executing the script from the local host will be rejected too. This script should only be called by remote hosts.

Test "get hosts"

[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh centos-dev-2 get hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

Test "get resolv.conf"

[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh centos-dev-2  resolv.conf
; generated by /sbin/dhclient-script
search vbox.local
nameserver 192.168.56.1

Test "get env"

My fake oracle environment is nothing like what a real one would look like. This example is given just to prove that the remote script does execute with all of the expected environment variables.
[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh centos-dev-2 get env
SELINUX_ROLE_REQUESTED=
SHELL=/bin/bash
SSH_CLIENT=192.168.56.101 46697 22
SELINUX_USE_CURRENT_RANGE=
USER=oracle
PATH=/usr/local/bin:/bin:/usr/bin
MAIL=/var/mail/oracle
PWD=/home/oracle
LANG=en_US.UTF-8
SELINUX_LEVEL_REQUESTED=
HOME=/home/oracle
SHLVL=2
SSH_ORIGINAL_COMMAND=get env
LOGNAME=oracle
CVS_RSH=ssh
SSH_CONNECTION=192.168.56.101 46697 192.168.56.102 22
LESSOPEN=|/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=/bin/env

Test some bad commands

[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh centos-dev-2 userdel oracle
Bad Command
[oracle@centos-dev-1 ~]$ ssh centos-dev-2 "su -c \"userdel oracle\""
Bad Command
[oracle@centos-dev-1 ~]$ ssh centos-dev-2 rm -fr /*
Bad Command

Test logging in without a password

[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh centos-dev-2
PTY allocation request failed on channel 0
This script can only be executed via SSH remote calls
                                                     Connection to centos-dev-2 closed.

Using SSH to force the requirement for a password

Because a shared key exists, ssh will automatically try to use it for authentication. We now need to explicitly declare that no public private key should be used for authentication.
[oracle@centos-dev-1 ~]$ hostname
centos-dev-1.vbox.local
[oracle@centos-dev-1 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-1 ~]$ ssh -o PubkeyAuthentication=no centos-dev-2
oracle@centos-dev-2's password: 
Last login: Fri Dec 20 10:35:22 2013 from centos-dev-1.vbox.local
[oracle@centos-dev-2 ~]$ hostname
centos-dev-2.vbox.local
[oracle@centos-dev-2 ~]$ id
uid=500(oracle) gid=501(oinstall) groups=501(oinstall) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@centos-dev-2 ~]$ 

Thursday, December 12, 2013

Python suds (SOAP Library) does not support SSLv3

The Oracle Virtual Machine (OVM) manager exposes a SOAP (wsdl) web-service. At the time of writing this can be found here: (for version 3.2.x)

https://<hostname>:7002/ovm/core/wsapi/soap?wsdl

You can access this url in your web browser and will be prompted to accept the self signed cert etc.  (There is a way to add a real certificate but that's not what this article is about.)

In order to consume this webservice in python, I thought to try out the (now quite old) "suds" library.  Opensuse still ship this library and you can install it with:
zypper in python-suds
EDIT: I have added the forked library to github here: https://github.com/linuxplayground/suds-sslv3-fork
The problem I found was that when trying to connect to the service, I was receiving an exception error around SSL.

Here is how it looked...
The example code:
#!/usr/bin/python
from suds.client import Client
client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl')
print client
Output:
david.latham@davidpc:~/bin/ovm-webservices> python broken.py 
Traceback (most recent call last):
  File "broken.py", line 3, in 
    client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl')
  File "/usr/lib/python2.7/site-packages/suds/client.py", line 112, in __init__
    self.wsdl = reader.open(url)
  File "/usr/lib/python2.7/site-packages/suds/reader.py", line 152, in open
    d = self.fn(url, self.options)
  File "/usr/lib/python2.7/site-packages/suds/wsdl.py", line 136, in __init__
    d = reader.open(url)
  File "/usr/lib/python2.7/site-packages/suds/reader.py", line 79, in open
    d = self.download(url)
  File "/usr/lib/python2.7/site-packages/suds/reader.py", line 95, in download
    fp = self.options.transport.open(Request(url))
  File "/usr/lib/python2.7/site-packages/suds/transport/https.py", line 60, in open
    return  HttpTransport.open(self, request)
  File "/usr/lib/python2.7/site-packages/suds/transport/http.py", line 62, in open
    return self.u2open(u2request)
  File "/usr/lib/python2.7/site-packages/suds/transport/http.py", line 118, in u2open
    return url.open(u2request, timeout=tm)
  File "/usr/lib64/python2.7/urllib2.py", line 404, in open
    response = self._open(req, data)
  File "/usr/lib64/python2.7/urllib2.py", line 422, in _open
    '_open', req)
  File "/usr/lib64/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.7/urllib2.py", line 1222, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "/usr/lib64/python2.7/urllib2.py", line 1184, in do_open
    raise URLError(err)
urllib2.URLError: 
That last line, "SSL23_GET_SERVER_HELLO:unknown protocol" had me stuck for ages. Eventually I found a blog post that suggested this can be fixed by adding a new HTTPHandler to the URLLIB2 Opener.
Rather than mess with the urllib2 library, I decided to download the source for the suds library, and fix the library.
Download suds from here:
svn co http://svn.fedorahosted.org/svn/suds/trunk
In the source tree add the following httpsconnectionv3.py to /path/to/downloaded/source/suds/transport/httpsconnectionv3.py
#!/usr/bin/python
import httplib, ssl, urllib2, socket

class HTTPSConnectionV3(httplib.HTTPSConnection):
    def __init__(self, *args, **kwargs):
        httplib.HTTPSConnection.__init__(self, *args, **kwargs)
        
    def connect(self):
        sock = socket.create_connection((self.host, self.port), self.timeout)
        if self._tunnel_host:
            self.sock = sock
            self._tunnel()
        try:
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3)
        except ssl.SSLError, e:
            print("Trying SSLv3.")
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
            
class HTTPSHandlerV3(urllib2.HTTPSHandler):
    def https_open(self, req):
        return self.do_open(HTTPSConnectionV3, req)
Then update /path/to/downloaded/source/suds/transport/http.py with the following additions:
  • include the new library in the imports
    • from httpsconnectionv3 import *
  • Add the following line to the function "u2handlers" after the line "handlers.append(u2.ProxyHandler(self.proxy))"
    • handlers.append(HTTPSHandlerV3())
Now you are ready to test using this library instead of the default suds library that ships with your OS.
The example code but this time you place your example code in the downloaded source tree so that python uses the local library. OR You can make the above modifications to your installed library which should be somewhere in /usr/lib/python-2.7/site-packages/suds.
Up to you.
Example Code:
david.latham@davidpc:~/bin/ovm-webservices/ovm_wsapi> cat getVMList.py
#!/usr/bin/python
from suds.client import Client
client = Client(url='https://ovm:7002/ovm/core/wsapi/soap?wsdl')
username='admin'
password='xxxxxxxx'
loginResponse = client.service.login(username,password)
print "Logging in .... <%s>" % loginResponse
if loginResponse == True:
        vmlist = client.service.vmGetAll()
        for vm in vmlist:
                if vm.vmRunState == 'RUNNING' or vm.vmRunState == 'STOPPED':
                        print "%s | %s" % (vm.name, vm.vmRunState)
        logoutResponse = client.service.logout()
        print "Logging out ... <%s>" % logoutResponse
else:
        print "login failure"
Output:
david.latham@davidpc:~/bin/ovm-webservices/ovm_wsapi> ./getVMList.py 
Logging in .... 
puppetmaster | RUNNING
ksplice-test | RUNNING
zimbra-test-el6 | STOPPED
ksplice-client | RUNNING
DB2_Server_RHEL58 | STOPPED
ora133 | STOPPED
secret_host_1 | STOPPED
zimbra-test | RUNNING
sqlsandpit | RUNNING
secret_host_2 | STOPPED
repo_server | RUNNING
Logging out ... 
So that fixes suds for sslv3

Tuesday, July 2, 2013

Simple symmetric / Shared key encryption tutorial

I was looking for a way to explain cryptography to my 8 year old son this evening and we devised a simple share key encryption / decryption method.  The key is symmetrical because both sides have the same key  and the same key is used for both encrypting and decrypting.

We took a simple ceasar cipher and extended it slightly by creating a stronger key.  Something like this:

Plain Text = HELLO WORLD
Key = [2, -5, 3, 7]
to encrypt we take the positional value for each letter and apply the replacement for the next key bit in turn.  For example:

Start at keybit = 1 [2]
H = 8, H + 2 = 10, 10 = J
keybit = 2 [-5]
E = 5, E - 5 = 0 (26), 26 = Z
keybit = 3 [3]
L = 12, 12 + 3 = 15, 15 = O
keybit = 4 [7]
L = 12, 12 + 7 = 19, 19 = S

Now start at key bit =1 
O = 15, 15 + 2 = 17, 17 = Q
and so on.

So long as the same key is used for decryption the thing works a treat.

So I explained that simple key can be made and shared between friends then private messages can be sent to and fro and only those with the key will know what the messages mean.

To demonstrate I made a program that he can use to make the process a bit quicker...
#!/usr/bin/python

import sys

alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ',',','.','!','?','\'','#','@','$','%','^','&','(',')','-','_','=','+',']','[','{','}','\\','|','/','"',':',';','<','>','`','~','1','2','3','4','5','6','7','8','9','0']

def encrypt(key, message):
    ciphertext = []
    pos = 0
    for c in message:
        i = alphabet.index(c)
        j = (i + key[pos]) % len(alphabet)
        ciphertext.append(alphabet[j])
        pos += 1
        if pos > len(key)-1: pos = 0
    return "".join(ciphertext)


if __name__ == '__main__':
    key = [3,-6,2,-7,23435363, -3243543, 324]
    for line in sys.stdin:
        encrypted = encrypt(key, line.strip())
        print encrypted

# vim:expandtab:ts=4:softtabstop=4:autoindent
And test it as follows
dave@davidpc:~/bin/simpleenc> echo "Hello World" | ./encrypt.py 
KYneJ9!dave@davidpc:~/bin/simpleenc> echo "Hello World" | ./encrypt.py 
KYneJ9!rlnWrlnW
The Decrypt program is almost identical (and really shouldn't be a separate programme at all)
#!/usr/bin/python

import sys

alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ',',','.','!','?','\'','#','@','$','%','^','&','(',')','-','_','=','+',']','[','{','}','\\','|','/','"',':',';','<','>','`','~','1','2','3','4','5','6','7','8','9','0']

def decrypt(key, message):
    plaintext = []
    pos = 0
    for c in message:
        i = alphabet.index(c)
        j = (i - key[pos]) % len(alphabet)
        plaintext.append(alphabet[j])
        pos += 1
        if pos > len(key)-1: pos = 0
    return "".join(plaintext)
        

if __name__ == '__main__':
    key = [3,-6,2,-7,23435363, -3243543, 324]
    for line in sys.stdin:
        decrypted = decrypt(key, line.strip())
        print decrypted

# vim:expandtab:ts=4:softtabstop=4:autoindent
And the test...
dave@davidpc:~/bin/simpleenc> cat << EOF | ./decrypt.py 
> KYneJ9!rlnW
> EOF
Hello World

Thursday, May 16, 2013

Samba4 Windows AND Linux authentication

Introduction

This post describes all the millions of configuration files you need to set up on a CLIENT LINUX server / machine in order to ssh to it with your domain credentials. I have this working in a LAB environment with the following caveats:

  1. SELINUX disabled (work on this required)
  2. Firewall Disabled (not hard to fix this if required)
  3. DNS Setup not working completely for Forwarding to external Nameserver by Samba4.  Don't know why. (more investigation required)
  4. You will need to have a user called binduser which has permissions in AD to look up other users.  I am sure there is documentation on this around somewhere :)

Install packages

yum -y install samba-winbind pam_ldap pam_krb5 nss-pam-ldapd oddjob-mkhomedir bind-utils

Configure openldap (/etc/openldap/ldap.conf)

[root@linuxclient ~]# cat /etc/openldap/ldap.conf 
#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE   dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-master.example.com:666

#SIZELIMIT      12
#TIMELIMIT      15
#DEREF          never

TLS_CACERTDIR /etc/openldap/cacerts
URI ldap://pdc.vbox.local/
BASE dc=vbox,dc=local

Configure PAM_LDAP (/etc/pam_ldap.conf)

[root@linuxclient ~]# cat /etc/pam_ldap.conf 
uri ldap://pdc.vbox.local/
base dc=vbox,dc=local
binddn cn=binduser,cn=Users,dc=vbox,dc=local
bindpw SECRET
scope sub
nss_base_passwd cn=Users,dc=vbox,dc=local
nss_base_shadow cn=Users,dc=vbox,dc=local
nss_base_group cn=Users,dc=vbox,dc=local
nss_map_objectclass posixAccount user
nss_map objectclass shadowAccount user
nss_map objectclass posixGroup group
nss_map_attribute homeDirectory unixHomeDirectory
nss_map_attribute uniqueMember member
nss_map_attribute shadowLastChange pwdLastSet
pam_login_attribute uid
pam_filter objectClass=user
pam_password md5
pam_member_attribute member
ssl no
tls_cacertdir /etc/openldap/cacerts
am_sasl_mech DIGEST-MD5

Configure KRB5 (/etc/krb5.conf)

[root@linuxclient ~]# cat /etc/krb5.conf 
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/admind.log

[libdefaults]
 default_realm = VBOX.LOCAL
 dns_lookup_realm = true
 dns_lookup_kdc = true

[domain_realm]
.vbox.local = VBOX.LOCAL
vbox.local = VBOX.LOCAL

[appdefaults]
pam = {
debug = false
ticket_lifetime = 36000
renew_lifetime = 36000
forwardable = true
krb4_convert = false
validate = false
}

[realms]
VBOX.LOCAL = {
}

VBOX.LOCAL = {
}

Configure the NSLC Daemon (/etc/nslcd.conf)

[root@linuxclient ~]# cat /etc/nslcd.conf                                                                                                                                                       
binddn cn=binduser,cn=Users,dc=vbox,dc=local                                                                                                                                                  
bindpw SECRET                                                                                                                                                                                
scope sub                                                                                                                                                                                       
base dc=vbox,dc=local                                                                                                                                                                           
scope  group  sub                                                                                                                                                                               
scope  hosts  sub                                                                                                                                                                               
pagesize 1000                                                                                                                                                                                   
referrals off
filter passwd (&(objectClass=user)(!(objectClass=computer)))
map    passwd uid              sAMAccountName
map    passwd homeDirectory    unixHomeDirectory
map    passwd gecos            displayName

filter shadow (&(objectClass=user)(!(objectClass=computer))(uidNumber=*)(unixHomeDirectory=*))
map    shadow shadowLastChange pwdLastSet
map    shadow uid              sAMAccountName

filter group (&(objectClass=group)(gidNumber=*))
map group uniqueMember member

uid nslcd
gid ldap
uri ldap://pdc.vbox.local/
ssl no
tls_cacertdir /etc/openldap/cacerts

Configure Authconfig for SSH (/etc/sysconfig/authconfig)

set: USEKERBEROS=yes
[root@linuxclient ~]# cat /etc/sysconfig/authconfig 
IPADOMAINJOINED=no
USEMKHOMEDIR=yes
USEPAMACCESS=no
CACHECREDENTIALS=yes
USESSSDAUTH=no
USESHADOW=yes
USEWINBIND=no
USESSSD=no
USEDB=no
FORCELEGACY=no
USEFPRINTD=no
USEHESIOD=no
FORCESMARTCARD=no
USELDAPAUTH=no
IPAV2NONTP=no
USELDAP=yes
USECRACKLIB=yes
USEIPAV2=no
USEWINBINDAUTH=yes
USESMARTCARD=no
USELOCAUTHORIZE=yes
USENIS=no
USEKERBEROS=yes
USESYSNETAUTH=no
PASSWDALGORITHM=sha512
USEPASSWDQC=no

Update authconfig

authconfig --updateall

Check PAM Configuration

[root@linuxclient ~]# cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        sufficient    pam_krb5.so use_first_pass
auth        sufficient    pam_winbind.so use_first_pass
auth        required      pam_deny.so

account     required      pam_unix.so broken_shadow
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     [default=bad success=ok user_unknown=ignore] pam_krb5.so
account     [default=bad success=ok user_unknown=ignore] pam_winbind.so
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3 type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    sufficient    pam_krb5.so use_authtok
password    sufficient    pam_winbind.so use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     optional      pam_oddjob_mkhomedir.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
session     optional      pam_krb5.so

Configure DNS Settings

You need various AD names to resolve. Especially for kerberos... Note: There is a problem here. The Domain controller must FORWARD dns traffic it knows nothing about.
[root@linuxclient ~]# cat /etc/resolv.conf 
#nameserver must be the IP address of the domain controller.
domain vbox.local
nameserver 192.168.56.101

Reboot

A reboot is required to make sure everything works.

Thursday, May 2, 2013

Disable the touch pad while typing on Linux

The Problem:

If you have a Synaptics touch-pad like the one I have on my HP ProBook 6560b, you might want to learn how to disable the touch-pad while typing. This particular laptop has a touch-pad that is positioned poorly so it is common for your palm to be in contact with the pad while you type. The solution is to disable it for 2 seconds while typing. It is a minor inconvenience to have to wait two seconds to use it again but at least your typing is uninterrupted which could be a major inconvenience. 

The solution:

Use the syndaemon tool that ships with the synaptics packages. In my case they shipped by default. You could always try the gui...
david.latham@davepc:~> cat bin/touchpad.sh
#!/bin/bash
syndaemon -k -i 2 -d
Now just configure your desktop manager to run this script on start up. It is a trivial thing to do in KDE under system settings -> Sartup and Shutdown, Add Script...

Friday, March 29, 2013

Firewall Script for openSuSE and others

openSuSE and, I guess, Fedora have introduced their own firewall (iptables) configuration guis and services that try to make the job of configuring iptables easy.  While that might be useful in a standard desktop environment, I found that it didn't do much for my Virtualbox nat.

I couldn't create the masqerade rules very easily and I didn't want all the extensive rules governing types of ICMP traffic and logging.  As the SuSEfirewall2 service GUI didn't help and the configuration files were too complicated for this old school blogger, I decided to roll my own script.

On my system, I simply disable the SuSEfirewall2 service and then call this script on boot.

You can find this script and any changes I make to it on my github.  Of course, I won't be putting every rule I have in place online, that would be a crazy security risk.  I just wanted to show the basics that can be easily extended by adding more rules into the filter section.

#!/bin/bash
IPT=/usr/sbin/iptables

# Stop the system firewall
systemctl stop SuSEfirewall2.service

# Reset all
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X

# set default policies
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD DROP 

$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# filter all all related and established (reply traffic)
$IPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# filter allow all traffic from vboxnet0 including new traffic.
$IPT -A INPUT -i vboxnet0 -j ACCEPT

# filter custom rules
$IPT -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT

# forward traffic to and from vboxnet0
$IPT -A FORWARD -i vboxnet0 -j ACCEPT
$IPT -A FORWARD -o vboxnet0 -j ACCEPT

# postrouting so traffic from vboxnet appears to be from these devices.
$IPT -t nat -A POSTROUTING -s 192.168.56.0/24 -j MASQUERADE

# final rule to block inbound traffic
$IPT -A INPUT -j DROP
$IPT -A FORWARD -j DROP

# turn on ip_forward
sysctl net.ipv4.ip_forward=1

# turn on dnsmasq
systemctl start dnsmasq

Saturday, February 9, 2013

Reset the Oracle XE database password for OVM 3.1.1.

You have installed Oracle OVM with the bundled XE database and after a time, you find that you can no longer log into the OVM Admin console.

You get an error similar to: Unexpected Error logging in.  Consult logs...

What has probably happened is that the ovs database password has expired in XE.  Now using the XE environment is unsupported and for demo purposes only.  In fact the new version of OVM ships with a bundled MySQL database and no longer the XE.  Even better, the bundled MySQL database is supported in production environments.  So this post is obsolete even before I finish writing it.

To be sure you are facing this problem, grep for OVMDS in /u01/app/oracle/ovm-manager-3/machine1/base_adf_domain/servers/AdminServer/logs/AdminServer.log

####<Jan 28, 2013 12:19:51 PM NZDT> <Warning> <JDBC> <ovm.e-it.co.nz> <AdminServer> <Odof Tcp Client Thread: /127.0.0.1:54321/128430> <<anonymous>> <> <0000JcuiwIkCslYFLrfP8A1GSLRc000002> <1359328791693> <WL-001129> <Received exception while creating connection for pool "OVMDS": ORA-28001: the password has expired

OK so the XE Database password needs resetting.

First some environment variables:

[root@ovm logs]# echo $ORACLE_HOME
/u01/app/oracle/product/11.2.0/xe
[root@ovm logs]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/u01/app/oracle/product/11.2.0/xe:/u01/app/oracle/product/11.2.0/xe/bin
[root@ovm logs]# echo $ORACLE_SID
XE

Now use sqlplus as follows: (OldPassWord is the one you used when you installed OVMM. The OVMM installer either prompted for this or you selected the option to use the same password for everything during install... Remember?)

[root@ovm bin]# sqlplus ovs/OldPassWord

SQL*Plus: Release 11.2.0.2.0 Production on Sat Feb 9 10:38:48 2013

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

ERROR:
ORA-28001: the password has expired


Changing password for ovs
New password: NewPassw0rd
Retype new password: NewPassw0rd
 

Password changed

Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> exit

Now you need to update the password stored in Weblogic that is used to connect to the database.  Happily there is an admin tool for this:
It's found in:   /u01/app/oracle/ovm-manager-3/bin

[root@ovm bin]# ./ovm_admin --modifyds XE localhost 1521

Oracle VM Manager Release 3.1.1 Admin tool

Please enter the Oracle VM Manager database schema : ovs

Please enter the schema password for ovs : NewPassw0rd
Please re-enter the password : NewPassw0rd


Please enter the password for weblogic : <password you used when you installed ovmm>

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

Connecting to WebLogic server ...

Connected ...
Modifying Oracle VM Manager Data Store 'OVMDS'...
Modified Data Store successfully ...
Exiting...
Restart of Oracle VM Manager is required for Data Store change to take effect ...


Now restart OVMM.  I like to allow a minute between stop and start.  This takes a while on my test environment...

[root@ovm bin]# /etc/init.d/ovmm stop && sleep 60 && /etc/init.d/ovmm start

Finally you should be able to log into ovm console as you used to.  Same username and password you always used.

This process updates the backend XE database password only.  Thankfully this should all be old news as the new version ships with MySQL and password resets in MySQL are much simpler.  The big question and one which I have not yet figured out the answer to is: Will the new OVMM support an external MySQL database...  In Production...

Edit...
I had to edit the error message found in the AdminServer log on this blog because of the xml being interpreted instead of displayed... Fixed now thanks to: http://entities.online-toolz.com/tools/text-html-entities-convertor.php