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;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;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;result);
if (!status &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; (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;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; 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.
2 comments ↓
How soon will you update your blog? I’m interested in reading some more information on this issue.
I’ll try as soon as possible, but not only focused on this topic. Thanks for your comment.
Leave a Comment