Posts

Tool of the day : etckeeper

February 9, 2010 - No comment

http://joey.kitenet.net/code/etckeeper/

etckeeper is a collection of tools to let /etc be stored in a git, mercurial, darcs, or bzr repository. It hooks into apt (and other package managers including yum and pacman-g2) to automatically commit changes made to /etc during package upgrades. It tracks file metadata that revison control systems do not normally support, but that is important for /etc, such as the permissions of /etc/shadow. It's quite modular and configurable, while also being simple to use if you understand the basics of working with revision control.

Under Debian Lenny :

Install :

apt-get install etckeeper

Set ut the git repository (git is the default repository system, see /etc/etckeeper/etckeeper.conf if you want to change that) :

cd /etc
etckeeper init
etckeeper commit "initial import"

We’re done with the initial setup..

If you install a package through apt-get or aptitude, changes will be automatically commited.

If you made changes to files under /etc, commit them by doing :

git commit -a

Also, you can install trac-git, which provides a user friendly web interface to browse your git repository.

Asterisk Wake Up call application

February 2, 2010 - 2 comments

If you want to be awaken by your Asterisk PBX, here’s a simple bit of code to add in your dial plan.

Basically, you would call 9253 followed by the time the phone should ring, for exemple if you want to be awaken at 06:30am you would call 92530630 (on your dialpad WAKE0610).

This code only allows to set ONE alarm.

If you want to delete -for exemple the 0630am- alarm, you would call 6692530610 (on dialpad NOWAKE0610).

Asterisk will create a call file and put it under /var/spool/asterisk/outgoing/
How does Asterisk know when to call you ? It will check the timestamp of the call files.

Make sure you enable func_strings.so module, it is required for STRFTIME.

[Context-This-Code-Should-Go-In]

; WAKE + hour + minute : sets a wake up call
exten => _9253XXXX,1,Answer()
exten => _9253XXXX,n,Set(wakeuptime=${EXTEN:4:4})
exten => _9253XXXX,n,Set(today=${STRFTIME(${EPOCH},,%Y%m%d)})
exten => _9253XXXX,n,Set(tomorrow=${STRFTIME($[${EPOCH} + 86400],,%Y%m%d)})
exten => _9253XXXX,n,Set(now=${STRFTIME(${EPOCH},,%Y%m%d%H%M)})
exten => _9253XXXX,n,System(echo -e "Channel: SIP/${CALLERID(num)}\\nContext: WakeUp\\nExtension: 92531" > /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n,GotoIf($["${today}${wakeuptime}" < "${now}"]?tomorrow:today)
exten => _9253XXXX,n(today),NoOp(Scheduling wake up call for ${CALLERID(num)} today at ${wakeuptime} / )
exten => _9253XXXX,n,System(touch -t ${today}${wakeuptime} /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n,Goto(move)
exten => _9253XXXX,n(tomorrow),NoOp(Scheduling wake up call for ${CALLERID(num)} tomorrow at ${wakeuptime} / )
exten => _9253XXXX,n,System(touch -t ${tomorrow}${wakeuptime} /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n(move),System(mv /tmp/${UNIQUEID}.call /var/spool/asterisk/outgoing/${wakeuptime}.${UNIQUEID}.call)
exten => _9253XXXX,n,Wait(1)
exten => _9253XXXX,n,SayNumber(${wakeuptime})
exten => _9253XXXX,n,Hangup()

; NOWAKE + hour + minute : deletes a wake up call
exten => _669253XXXX,1,Answer()
exten => _669253XXXX,n,Set(wakeuptime=${EXTEN:6:4})
exten => _669253XXXX,n,NoOp(Deleting alarm set at ${wakeuptime})
exten => _669253XXXX,n,System(rm -f /var/spool/asterisk/outgoing/${wakeuptime}*)
exten => _669253XXXX,n,Wait(1)
exten => _669253XXXX,n,Background(auth-thankyou)
exten => _669253XXXX,n,Hangup()

[WakeUp]
;;; Context for outgoing wake up calls only, well you can always call 92531 but it's rather pointless
exten => 92531,1,Answer()
exten => 92531,n,Wait(1)
exten => 92531,n,Background(hello-world)
exten => 92531,n,Wait(1)
exten => 92531,n,Hangup()

A basic OpenLDAP server in under 15 minutes

January 28, 2010 - 2 comments

Tested under Debian Lenny

This howto is basic, as in “no security involved”. I may come up with a second part to this guide about securing OpenLDAP with TLS, if I ever find the time.
Meanwhile see http://www.openldap.org/doc/admin23/security.html for the security aspect of things.

In this example, I’ll create a tree following this scheme : dc=my,dc=domain,dc=tld.
It’s really up to you how you organize your tree, it’s really for organizational purposes. You can limit your tree to a single root branch, for example dc=myname.

Install OpenLDAP server and some useful utilities :

# apt-get install slapd ldap-utils

You should be prompted for a password, if not create it from the command line :

# slappasswd
New password:
Re-enter new password:
{SSHA}vFk3EP4SSW0RDm4yEKD

Edit /etc/ldap/slapd.conf :

You should copy the password obtained with slappasswd under the rootpw option.

include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd/slapd.args
loglevel        none
modulepath	/usr/lib/ldap
moduleload	back_hdb
sizelimit 500
tool-threads 1
backend		hdb
database        hdb
suffix          "dc=my,dc=domain,dc=tld"
rootdn          "cn=admin,dc=my,dc=domain,dc=tld"
rootpw		"{SSHA}vFk3EP4SSW0RDm4yEKD"
directory       "/var/lib/ldap"
dbconfig set_cachesize 0 2097152 0
dbconfig set_lk_max_objects 1500
dbconfig set_lk_max_locks 1500
dbconfig set_lk_max_lockers 1500
index           objectClass eq
lastmod         on
checkpoint      512 30
access to attrs=userPassword,shadowLastChange
        by dn="cn=admin,dc=my,dc=domain,dc=tld" write
        by anonymous auth
        by self write
        by * none
access to dn.base="" by * read
access to *
        by dn="cn=admin,dc=my,dc=domain,dc=tld" write
        by * read

“cn=admin,dc=my,dc=domain,dc=tld” is the database admin. This is what you will use as credential when you need to modify something in the database.

Then edit /etc/ldap/ldap.conf :

This is the configuration for the LDAP client.

HOST 127.0.0.1
BASE dc=my,dc=domain,dc=tld
URI ldap://localhost

Now create a directory that will contain some initial configuration files.

# mkdir /etc/ldap/LDIF

In this directory create the following files :

1_base.ldif (the base of our LDAP tree) :

dn: dc=my,dc=domain,dc=tld
dc: my
objectClass: domain

2_group.ldif (this will be the branch that will host our groups) :

dn: ou=Groups,dc=my,dc=domain,dc=tld
ou: Groups
objectClass: organizationalUnit

3_dev.ldif (this is our first group) :

dn: cn=dev,ou=Groups,dc=my,dc=domain,dc=tld
cn: dev
gidNumber: 30000
memberUid: user1
objectClass: posixGroup
objectClass: top
description: developers

4_people.ldif (this is the branch hosting users) :

dn: ou=People,dc=my,dc=domain,dc=tld
ou: People
objectClass: organizationalUnit

5_user1.ldif (this is our first user) :

dn: uid=user1,ou=People,dc=my,dc=domain,dc=tld
uid: user1
cn: John Doe
displayName: John Doe
givenName: Doe
sn: Doe
objectClass: inetOrgPerson
userPassword: pass
mail: johndoe@domain.tld

When we are done, we can restart OpenLDAP and create the tree and import some data :

# /etc/init.d/slapd restart
# cd /etc/ldap/LDIF
# for i in `ls`; do ldapadd -x -D "cn=admin,dc=my,dc=domain,dc=tld" -W -f $i ; done

You should be prompted for the admin password as much as you have LDIF files in the directory.
If you didn’t name your file 1_base.ldif, 2_group.ldif, etc. the command may fail as it may try to add a group or user before creating its branch.

Now you should be able to query the LDAP tree :

# ldapsearch -x
# extended LDIF
#
# LDAPv3
# base <dc=my,dc=domain,dc=tld> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# my.domain.tld
dn: dc=my,dc=domain,dc=tld
dc: my
objectClass: domain

# Groups, my.domain.tld
dn: ou=Groups,dc=my,dc=domain,dc=tld
ou: Groups
objectClass: organizationalUnit

# People, my.domain.tld
dn: ou=People,dc=my,dc=domain,dc=tld
ou: People
objectClass: organizationalUnit

# user1, People, my.domain.tld
dn: uid=user1,ou=People,dc=my,dc=domain,dc=tld
uid: user1
cn: John Doe
displayName: John Doe
givenName: Doe
sn: Doe
objectClass: inetOrgPerson
mail: johndoe@domain.tld

# dev, Groups, my.domain.tld
dn: cn=dev,ou=Groups,dc=my,dc=domain,dc=tld
cn: dev
gidNumber: 30000
memberUid: user1
objectClass: posixGroup
objectClass: top
description: developers

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 5

This command requires /etc/ldap/ldap.conf. If you don’t have ldap.conf configured you’d have to type the whole command :

# ldapsearch -x -b "dc=my,dc=domain,dc=tld" -H ldap://server

Now, you can authenticate several services against your new LDAP server.
For example, web authentication in Apache.. Take a look at http://www.wains.be/index.php/2010/01/26/apache-simple-authentication-and-ldap-authentication-examples/

You also may want to install PHP LDAP Admin for managing your LDAP database through a web GUI :

# apt-get install phpldapadmin

Then go to http://server/phpldapadmin and authentify with cn=admin,dc=my,dc=domain,dc=tld and your rootpw.

Apache : simple authentication and LDAP authentication examples

January 26, 2010 - No comment

Simple authentication :

Users credentials are stored in a file created with htpasswd command

<Location /dir/>
AuthType Basic
AuthName "Authentication"
AuthUserFile /etc/apache2/passwd-file
Require user username1 username2
</Location>

If we want to allow all users in passwd-file, use :
Require valid-user

LDAP user authentication :

We allow user1 and user2 found in the branch ou=People,dc=domain,dc=tld

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
Require ldap-user user1 user2
</Location>

LDAP group authentication :

We allow all users in the group “support”, users are defined in that group under the memberUid field

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
AuthLDAPGroupAttribute memberUid
AuthLDAPGroupAttributeIsDN off
Require ldap-group cn=support,ou=Groups,dc=domain,dc=tld
</Location>

Combination of users and group :

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
AuthLDAPGroupAttribute memberUid
AuthLDAPGroupAttributeIsDN off
Require ldap-group cn=support,ou=Groups,dc=domain,dc=tld
Require ldap-attribute gidNumber=10000
Require ldap-user user1 user3 user5
</Location>

See also :

- Conditional web authentication : http://www.wains.be/index.php/2007/01/27/apache-conditional-http-authentication/

- Source for this post : http://www.linux.com/archive/feature/120050?theme=print

Keith in his post is wrong about the “Satisfy Any” option, as explained in Apache documentation : http://httpd.apache.org/docs/2.0/mod/core.html#satisfy :

This directive is only useful if access to a particular area is being restricted by both username/password and client host address. In this case the default behavior (All) is to require that the client passes the address access restriction and enters a valid username and password. With the Any option the client will be granted access if they either pass the host restriction or enter a valid username and password.

He seems to explain that the “Satisfy Any” option is necessary when using several “Require” arguments. That’s incorrect, all Require arguments are evaluated by default and must pass checks to give access to the resource.

Local user authentication with FreeRADIUS

January 25, 2010 - No comment

This one is a bit less complex than http://www.wains.be/index.php/2009/09/13/wpa2-freeradius-eap-tls/

This is actually the most basic RADIUS configuration ever, useful for quick tests. I can only recommend checking the post mentioned above if you want to do something serious.

# apt-get install freeradius

# vim /etc/freeradius/users

login     Cleartext-Password := "password"
login2     Cleartext-Password := "password2"
#vim /etc/freeradius/clients.conf

client localhost {
	ipaddr = 127.0.0.1
        secret = radiuspassword
}

client router {
	ipaddr = 10.0.0.1
        secret = radiuspassword
}

# /etc/init.d/freeradius restart

Check if RADIUS is working :

# radtest login password localhost 1812 radiuspassword
Sending Access-Request of id 222 to 127.0.0.1 port 1812
User-Name = "login"
User-Password = "password"
NAS-IP-Address = 127.0.1.1
NAS-Port = 1812
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=222, length=20

# radtest login2 password2 localhost 1812 radiuspassword
Sending Access-Request of id 1 to 127.0.0.1 port 1812
User-Name = "login2"
User-Password = "password2"
NAS-IP-Address = 127.0.1.1
NAS-Port = 1812
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=1, length=20

We expect Access-Accept from the server, not Access-Reject…

Configure your wireless access point :

Usually found under Security tab (or RADIUS, 802.1X, etc.)
Configure your device at 10.0.0.1 to authenticate against the Radius server with password radiuspassword.
Try to connect to your wireless access point using login and password.

Next Page »