#include <fcntl.h>
#include <getopt.h>
#include <grp.h>
+#include <limits.h>
#include <netinet/in.h>
#include <nss.h>
#include <pthread.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
-#include <afs/afs.h>
#include <afs/afsutil.h>
#include <afs/cellconfig.h>
#include <afs/com_err.h>
#include <afs/param.h>
#include <afs/ptclient.h>
#include <afs/pterror.h>
+#include <afs/ptuser.h>
#include <afs/stds.h>
#define HOMEDIR_AUTO 0
int afs_initialized = 0;
char cellname[MAXCELLNAMELEN];
-char homedir_prefix[MAXPATHLEN];
+char homedir_prefix[PATH_MAX];
+char cell_root[PATH_MAX];
int homedir_prefix_len=0;
char homedirs_method=0;
char shells_method=0;
+int init_afs ();
+
/**
* The cpstr() function copies a null-terminated string from str*
* (the first argument) into buf and updates both buf and buflen. If
/**
* Look up the name corresponding to uid, store in buffer.
*/
-enum nss_status ptsid2name(int uid, char **buffer, int *buflen) {
+enum nss_status ptsid2name(int uid, char **buffer, size_t *buflen) {
int ret, i;
idlist lid;
namelist lnames;
- init_afs();
+ if (init_afs()) return NSS_STATUS_UNAVAIL;
if (uid==AFS_MAGIC_ANONYMOUS_USERID) {
if (!cpstr("anonymous", buffer, buflen)) return NSS_STATUS_UNAVAIL;
lnames.namelist_val = 0;
lnames.namelist_len = 0;
- if (ubik_Call(PR_IDToName,pruclient,0,&lid,&lnames) != PRSUCCESS) {
+ if (ubik_PR_IDToName(pruclient,0,&lid,&lnames) != PRSUCCESS) {
+ perror("ubik_Call() in ptsid2name() failed\n");
pthread_mutex_unlock(&mutex);
return NSS_STATUS_UNAVAIL;
}
ret = NSS_STATUS_NOTFOUND;
for (i=0;i<lnames.namelist_len;i++) {
int delta = strlen(lnames.namelist_val[i]);
- if ( (delta < buflen) && islower(*(lnames.namelist_val[i])) ) {
+ if ( (delta < *buflen) && islower(*(lnames.namelist_val[i])) ) {
cpstr(lnames.namelist_val[i], buffer, buflen);
ret = NSS_STATUS_SUCCESS;
}
namelist lnames;
char uname[MAXUSERNAMELEN];
- init_afs();
+ if (init_afs()) return NSS_STATUS_UNAVAIL;
if (!strcmp(name,"anonymous")) {
*uid = AFS_MAGIC_ANONYMOUS_USERID;
strncpy(uname, name, MAXUSERNAMELEN);
lnames.namelist_len = 1;
- if (ubik_Call(PR_NameToID,pruclient,0,&lnames,&lid) != PRSUCCESS) {
+ if (ubik_PR_NameToID(pruclient,0,&lnames,&lid) != PRSUCCESS) {
+ perror("ubik_Call() in ptsname2id() failed\n");
pthread_mutex_unlock(&mutex);
return NSS_STATUS_UNAVAIL;
}
int init_afs() {
FILE *thiscell;
int len;
+ struct stat statbuf;
- if (afs_initialized) return 0;
+ char buf[6];
+ int fd;
+ int pos;
+
+ if (afs_initialized) {
+ /* wait until /afs/@cell/ appears as a proxy for "the network is up" */
+ if (stat(cell_root, &statbuf)) return -1;
+ return 0;
+ }
+ // check to make sure that we are running inside nscd
+ pos = 0;
+ fd = open("/proc/self/cmdline", O_RDONLY);
+ if (fd==-1) return -1;
+ while(1) {
+ int numread;
+ numread = read(fd, buf+pos, 1);
+ if (buf[ (pos+5)%6 ] == 'd' &&
+ buf[ (pos+4)%6 ] == 'c' &&
+ buf[ (pos+3)%6 ] == 's' &&
+ buf[ (pos+2)%6 ] == 'n' &&
+ (buf[(pos+1)%6 ] == '/' || pos==4) &&
+ (buf[(pos+0)%6 ] == 0 || numread==-1)
+ )
+ break;
+ pos = (pos+1)%6;
+ if (numread==0) { close(fd); return -1; }
+ }
+ close(fd);
+
if (pthread_mutex_lock(&mutex)) return -1;
do {
homedirs_method=HOMEDIR_PREFIX;
if (cellname[len-1] == '\n') len--;
cellname[len]='\0';
+
+ /* wait until /afs/@cell/ appears as a proxy for "the network is up" */
+ sprintf(cell_root,"/afs/%s/",cellname);
+ if (stat(cell_root, &statbuf)) break;
+
sprintf(homedir_prefix,"/afs/%s/user/",cellname);
homedir_prefix_len=strlen(homedir_prefix);
-
- if (pr_Initialize(0L,AFSDIR_CLIENT_ETC_DIRPATH, 0)) break;
+
+ /* time out requests after 5 seconds to avoid hanging things */
+ rx_SetRxDeadTime(5);
+
+ if (pr_Initialize(0L,AFSDIR_CLIENT_ETC_DIRPATH, 0)) {
+ perror("pr_Initialize() failed\n");
+ break;
+ }
afs_initialized = 1;
pthread_mutex_unlock(&mutex);
int temp;
char *b;
char* bufx = buf;
- int bufxlen = 256;
+ size_t bufxlen = 256;
b=*buffer;
switch (shells_method) {
result->gr_passwd=buffer;
- if (!cpstr("x",&buffer,&buflen)) break;
+ if (!cpstr("z",&buffer,&buflen)) break;
if (buflen < sizeof(char*)) break;
- result->gr_mem=buffer;
+ result->gr_mem=&buffer;
result->gr_mem[0] = NULL;
*errnop=errno;
int *errnop) {
result_buf->pw_name = name;
do {
- /* set the password to "x" */
+ /* set the password to "z"; we can't use "x" because of pam_unix.so */
result_buf->pw_passwd = buffer;
- if ( ! cpstr("x",&buffer, &buflen) ) break;
+ if ( ! cpstr("z",&buffer, &buflen) ) break;
/* the uid and gid are both the uid passed in */
result_buf->pw_uid = uid;
result_buf->pw_shell = buffer;
if ( get_shell(result_buf->pw_name,&buffer,&buflen) ) break;
+#ifdef LIMIT_USERNAME_CHARS
+ if ( strlen(result_buf->pw_name) > LIMIT_USERNAME_CHARS ) {
+ result_buf->pw_name[LIMIT_USERNAME_CHARS] = '\0';
+ buflen = buflen + ( buffer - &result_buf->pw_name[LIMIT_USERNAME_CHARS+1] );
+ buffer = &result_buf->pw_name[LIMIT_USERNAME_CHARS+1];
+ }
+#endif
+
*errnop = errno;
return NSS_STATUS_SUCCESS;
} while(0);
return temp;
}
-#ifdef LIMIT_USERNAME_CHARS
- if ( strlen(result_buf->pw_name) > LIMIT_USERNAME_CHARS ) {
- result_buf->pw_name[LIMIT_USERNAME_CHARS] = '\0';
- buflen = buflen + ( buffer - &result_buf->pw_name[LIMIT_USERNAME_CHARS+1] );
- buffer = &result_buf->pw_name[LIMIT_USERNAME_CHARS+1];
- }
-#endif
-
return fill_result_buf(uid, name, result_buf, buffer, buflen, errnop);
}