Enable xdmcp in RHEL 5.1

If you want to be able of exporting your X system in another computer, you should keep an eye on this:
vi /etc/gdm/custom.conf

[xdmcp]
Enable=true
[security]
DisallowTCP=true
AllowRemoteRoot=true

After adding up the above lines:

# gdm-restart

Now in your client:

X -query :1

Somehow it can be unsafe to leave available the root access , so I won’t make that decision for you. : )

WPA roaming

Sometimes I go to visit my parents ( I’m a good son ), so that they have their own wireless network and I have mine. Whether you want to connect both just doing one
configuration keep an eye on the following steps:
/etc/wpa_supplicant/wpa_supplicant.conf

network={
ssid=”MyParentsNet”
key_mgmt=WPA-PSK
proto=WPA
pairwise=TKIP
group=TKIP
psk=”passowrd_parents”
id_str=”work” # Tha’ts an ID.
}

network={
ssid=”Home”
key_mgmt=WPA-PSK
proto=WPA2
pairwise=TKIP
group=TKIP
psk=”password_home”
id_str=”home” # And that’s another ID
}

Adding a few lines to the next file:
/etc/network/interfaces

auto wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface home inet dhcp
iface work inet dhcp

It’s important to set the interface to manual, don’t forget to give an “id_str” for each network, you can add a static configuration instead of dhcp :

iface work inet static
address 10.10.20.2
gateway 10.10.20.1
netmask 255.255.255.0

If you get some problem, please take a look in /usr/share/doc/, it’s really useful because it’s always there, you do not need memorize almost anything.

Catalyst XL2900: Setting up password

If you don’t set a password for your switch, you will not be able of getting in, so in a few steps:
Take your favorite client, I normally work with minicom:

# minicom -s ( Setting up serial cable: 9600 8N1 )
Some useful commands:
– CTRL-A Q Exit minicom
– CTRL-A F Send break

myswitch> enable
myswitch#configure
myswitch(config)#line vty 0 4
myswitch(config-line)#password mypasswd
myswitch(config-line)#login
myswitch(config-line)#exit
myswitch(config)#service password-encryption
myswitch(config)#exit
myswitch#write

The last line is the most important, if you forget this line you will not be able of doing telnet. Now you can do telnet your switch.

LVM: Mirroring /home

I usually have my home directory in a different partition.Last week I had to reinstall my Debian, so I decided to add a little bit of security for data losing. I used two disks and afterwards I migrated the data from the old home to the mirror.

I encourage recommend people do this, because is easier than it seems, and will not take more than ten minutes.

Before doing anything , it is needed download lvm2 package, and that is easy with Debian:

hlab:# aptitude install lvm2

Now it should be prepared two hard drives with exactly the same partition table, so here is the way :

hlab:# sfdisk -d /dev/sda | sfdisk /dev/sdb

This will make the second disk’s partition table /dev/sdb identical to the the first hard drive /dev/sdb.

hlab:/mnt/vdata# sfdisk -d /dev/sda
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
# partition table of /dev/sda
unit: sectors

/dev/sda1 : start= 63, size=976768002, Id= 5
/dev/sda2 : start= 0, size= 0, Id= 0
/dev/sda3 : start= 0, size= 0, Id= 0
/dev/sda4 : start= 0, size= 0, Id= 0
/dev/sda5 : start= 126, size=238275954, Id=83
/dev/sda6 : start=238276143, size=738491922, Id=83

  1. Physical volumes

  2. The first thing is to add physical volumes , and by physical I mean, either partitions or whole disks, here is the way:

    hlab:# pvcreate /dev/sda5 /dev/sdb6
    It’s suitable to check the results:
    hlab:#pvdisplay

    — Physical volume —
    PV Name /dev/sda5
    VG Name volhome
    PV Size 113.62 GB / not usable 1.68 MB
    Allocatable yes
    PE Size (KByte) 4096
    Total PE 29086
    Free PE 926
    Allocated PE 28160
    PV UUID 1ZPA7A-gXwn-O0G6-my3b-PUVt-mk9o-0A4sW1

    — Physical volume —
    PV Name /dev/sdc5
    VG Name volhome
    PV Size 113.62 GB / not usable 1.68 MB
    Allocatable yes
    PE Size (KByte) 4096
    Total PE 29086
    Free PE 926
    Allocated PE 28160
    PV UUID 0DfPHc-tXBn-dcYR-yKag-EL7j-RI4A-K9Eo0j

  3. Volumes groups

  4. The above step is just a conventionality ( I see it like that) for telling that you have available some partitions or disks. Now you can create some volumes, which will appear in /dev/volname, just take a look to the command:

    hlab:# vgcreate -A y vols /dev/sda5 /dev/sdb5
    -A y indicates we want to use autobackup functionality.
    As usual in the above examples , you can list the result with vgdisplay

    If you are familiarized with ZFS, at this point we have like zfs pool.

  5. Logical volumes

  6. Now is the time for setting the mirror. Here is the command

    hlab:# lvcreate -m1 (–nosync) -L 110G –mirror-log core -n home vols

    -m1: indicates mirror
    –nosyn: if there is data, no sync.
    -L: size of partition
    –mirror-log core:But default you need a third partition for keeping the logs, so instead of creating another partition, I decide to do not do it.
    -n: name of the the logical volume.
    vols: name of the volume group.

    At this point is possible to show the created mirror, so here is the command:

    hlab:# lvs -a -o +devices
    LV VG Attr LSize Origin Snap% Move Log Copy% Convert Devices
    home vols mwi-ao 110.00G 100.00 home_mimage_0(0),home_mimage_1(0)
    [home_mimage_0] vols iwi-ao 110.00G /dev/sda5(0)
    [home_mimage_1] vols iwi-ao 110.00G /dev/sdc5(0)

    The interesting part here, is the meaning of the attributes, you can make it out by means of “man”:

    m: mirror, if the letter was capitalized it would mean that was used the option –nosync. In this case I had not any data.
    w: indicates the volume is writable. If it appears a “r” the volume is read-only.
    ao: Partition is actived(a). Device is open(o).

  7. Data migration

  8. Well, this is the last point, and know only is needed to copy the home data and add a line to /etc/fstab for getting the mirror working out. Instead of using a command such as cp -R I prefer using tar, because is cleaner and will copy absolutely all the files, here is the command:

    First move your old home
    hlab:# mv /home /home_tmp
    Second mount the partition
    /etc/fstab
    /dev/vols/home /home auto rw
    hlab:# mount -a; cd /home_tmp
    hlab:# tar cvf – . (cd /home; tar xvf -)

    In resume, having a mirror with LVM is cheap and pretty straightforward. Besides you never know when Murphy’s law can act, so it is better being one step ahead.

Perl script for pam_authz

There is a good explanation about how to use pam_authz. Basically, in HP-UX systems if you have initialized a client against a LDAP server, and you’d like following server policies instead of local policies, you should keep on reading this article.
Let’s go to the issue!!

  1. File /etc/opt/ldapux/pam_authz.policy.master
    This file is read by the script, which looks for the variable $[GTIMEZULU] and substitutes for a timestamp.

    # pam_authz.policy.master
    deny:ldap_filter:(accountUnlockTime>=$[GTIMEZULU])
    # Allow all users other than those denied above
    allow:other

    In my case, I only needed to check if the user was locked or not.
    Inside the indicated document previously there is a bash script that solves that issue, I just decided try with Perl.

  2. The script
  3. 
    use English;
    use strict;
    use warnings;
    use Fcntl qw(:flock :seek);
    
    my $time="";
    my $template="/etc/opt/ldapux/pam_authz.policy.master";
    my $policy="/etc/opt/ldapux/pam_authz.policy";
    
    # It should appear a system call and create the file referenced in $policy but
    # this plugin does not  seem to be working out.
    
    &test_last_command();
    chmod(0700,"$policy");
    
    &update_time();
    
    sub test_last_command(){
        if ( $? != 0){
    	print "Error creating file\n";
    	exit -1;
        }
    }
    
    sub update_time(){
    
        my $line="";
        open POLICY_FILE, ">$policy" or die $!;
    
        while(1){
    	open TEMPLATE_FILE, "<$template" or die $!;
    	flock(POLICY_FILE, LOCK_EX);
    	seek(POLICY_FILE,0,SEEK_SET);
    
    	$time=`TZ=UTC;date "+%Y%m%d%H%M%SZ"`;
    	chop($time);
    	while(<TEMPLATE_FILE>){
    	    $line=$_;
    	    $line=~ s/\$\[GTIMEZULU\]/$time/g;
    	    print POLICY_FILE $line;
    	}
    
    	sleep 2;
    	close  TEMPLATE_FILE;
    
        }
    }
    

There was some strange problem with the highlight syntax plugin and I could not add a line. However, you can download the script directly.

PAM modules: pam_mkhomedir for Solaris

There is a PAM module available for creating home directories on fly, and this module is pam_mkhomedir.so. This is quite useful if you have a LDAP server ( in this case Directory Server 6.3) and you are inserting users but their home directories were not created. To my surprise, this module it was not available for Solaris, but I found an interesting link with useful information about this.
First of all , you’ll need to download the files Linux-PAM-80. For compiling this I did a little script, after reading the above article:

#!/bin/bash

PATH=/usr/sfw/bin:/usr/ccs/bin:$PATH;export PATH

gcc -c -g -O2 -D_REENTRANT -DPAM_DYNAMIC -Wall

-fPIC -I../../libpam/include \

-I../../libpamc/include   \

-I../pammodutil/include pam_mkhomedir.c

After compiling the module was not working, so  What should I do now? Well, I tried to debug why the module was not working, somehow I tried differents methods, the first I actived debug mode in syslog daemon, you only need to add

*.debug /var/adm/pam_log

in the /etc/syslog.conf . But here is what I found:

ay 18 10:27:25 des-to16-d sshd[26177]: [ID 547715 auth.debug] PAM[26177]: load_function: successful load of pam_sm_setcred
May 18 10:27:25 des-to16-d sshd[26177]: [ID 482737 auth.debug] PAM[26177]: pam_open_session(8a828, 0)
May 18 10:27:25 des-to16-d sshd[26177]: [ID 926797 auth.debug] PAM[26177]: load_modules(8a828, pam_sm_open_session)=/usr/lib/security/pam_mkhomedir.so

Nothing special that points me out how to solve this, so I tried another way. I tried to log with a ldap’s user, first with ssh but I was always getting out from the system, so that something interesting and annoying was happening. I thought to use telnet and I got this:

login: user1
Password:
ld.so.1: login: fatal: relocation error: file /usr/lib/security/pam_mkhomedir.so: symbol _pammodutil_getpwnam: referenced symbol not found
Connection to localhost closed by foreign host.

That told me more!! I opened pam_mkhomedir.c and I found the name of four functions :

_pammodutil_getpwnam
_pammodutil_read
_pammodutil_write
_pammodutil_cleanup

that there are no available in Solaris 10 ( of course neither above versions ). What did I do? I put all these functions together in the same file, and I added some includes, so this is all the code you need to add pam_mkhomedir.c before compiling:

/***** These includes are needed ********/

#include <security/pammodutil.h>
#include <errno.h>
#include <limits.h>

/*********** Functions ***************/
void _pammodutil_cleanup(pam_handle_t *pamh, void *data, int error_status)
{
    if (data) {
	/* junk it */
	(void) free(data);
    }
}
int _pammodutil_read(int fd, char *buffer, int count)
{
       int block, offset = 0;

       while (count > 0) {
               block = read(fd, &amp;amp;amp;amp;buffer[offset], count);

               if (block < 0) {
                       if (errno == EINTR) continue;
                       return block;
               }
               if (block == 0) return offset;

               offset += block;
               count -= block;
       }

       return offset;
}
int _pammodutil_write(int fd, const char *buffer, int count)
{
       int block, offset = 0;

       while (count > 0) {
               block = write(fd, &amp;amp;amp;amp;buffer[offset], count);

               if (block < 0) {
                       if (errno == EINTR) continue;
                       return block;
               }
               if (block == 0) return offset;

               offset += block;
               count -= block;
       }

       return offset;
}

struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
{
#ifdef HAVE_GETPWNAM_R

    void *buffer=NULL;
    size_t length = PWD_INITIAL_LENGTH;

    do {
	int status;
	void *new_buffer;
	struct passwd *result = NULL;

	new_buffer = realloc(buffer, sizeof(struct passwd) + length);
	if (new_buffer == NULL) {

	    D(("out of memory"));

	    /* no memory for the user - so delete the memory */
	    if (buffer) {
		free(buffer);
	    }
	    return NULL;
	}
	buffer = new_buffer;

	/* make the re-entrant call to get the pwd structure */
	errno = 0;
	status = getpwnam_r(user, buffer,
			    sizeof(struct passwd) + (char *) buffer,
			    length, &amp;amp;amp;amp;result);
	if (!status &amp;amp;amp;amp;&amp;amp;amp;amp; (result == buffer)) {
	    char *data_name;
	    const void *ignore;
	    int i;

	    data_name = malloc(strlen("_pammodutil_getpwnam") + 1 +
	    		       strlen(user) + 1 + intlen(INT_MAX) + 1);
	    if ((pamh != NULL) &amp;amp;amp;amp;&amp;amp;amp;amp; (data_name == NULL)) {
	        D(("was unable to register the data item [%s]",
	           pam_strerror(pamh, status)));
		free(buffer);
		return NULL;
	    }

	    if (pamh != NULL) {
	        for (i = 0; i < INT_MAX; i++) {
	            sprintf(data_name, "_pammodutil_getpwnam_%s_%d", user, i);
	            _pammodutil_lock();
		    status = PAM_NO_MODULE_DATA;
	            if (pam_get_data(pamh, data_name, &amp;amp;amp;amp;ignore) != PAM_SUCCESS) {
		        status = pam_set_data(pamh, data_name,
					      result, _pammodutil_cleanup);
		    }
	            _pammodutil_unlock();
		    if (status == PAM_SUCCESS) {
		        break;
		    }
		}
	    } else {
	        status = PAM_SUCCESS;
	    }

	    free(data_name);

	    if (status == PAM_SUCCESS) {
		D(("success"));
		return result;
	    }

	    D(("was unable to register the data item [%s]",
	       pam_strerror(pamh, status)));

	    free(buffer);
	    return NULL;

	} else if (errno != ERANGE &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; errno != EINTR) {
                /* no sense in repeating the call */
                break;
        }

	length <<= 2;

    } while (length < PWD_ABSURD_PWD_LENGTH);

    D(("pwd structure took %u bytes or so of memory",
       length+sizeof(struct passwd)));

    free(buffer);
    return NULL;

#else /* ie. ifndef HAVE_GETPWNAM_R */

    /*
     * Sorry, there does not appear to be a reentrant version of
     * getpwnam(). So, we use the standard libc function.
     */

    return getpwnam(user);

#endif /* def HAVE_GETPWNAM_R */
}

/**************** end ****************/

Obiously I hope nobody tries to C&P, I think it would better to look for the functions in the include files and then copy and paste, just because I could made some mistakes coping these lines.After compiling you can copy pam_mkhomedir.so to /usr/lib/security and do not forget to add the following line to the “/etc/pam.conf”

other session required pam_mkhomedir.so skel=/etc/skel umask=0022

Now you can try to log in the system with a ldap’s user:

ssh -l user5 localhost
Password:
Creating directory ‘/export/home/user5′.

Last login: Thu May 14 17:16:21 2009 from localhost
-bash-3.00$

You also can try to access by telnet. The is also backward compability among different versions of Solaris, so that means, it will work out in Solaris 8,9 as well. I hope this information can be useful for somebody.