Port to Debian Buster and OpenAFS 1.8
[hcoop/debian/libnss-afs.git] / nss_afs.c
index e05f53a..a9326d4 100644 (file)
--- a/nss_afs.c
+++ b/nss_afs.c
@@ -40,6 +40,7 @@
 #include <fcntl.h>
 #include <getopt.h>
 #include <grp.h>
+#include <limits.h>
 #include <netinet/in.h>
 #include <nss.h>
 #include <pthread.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
@@ -87,12 +88,14 @@ extern struct ubik_client *pruclient;
 
 int  afs_initialized = 0;
 char cellname[MAXCELLNAMELEN];
-char homedir_prefix[MAXPATHLEN];
-char cell_root[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
@@ -111,12 +114,12 @@ int cpstr( char *str, char **buf, size_t *buflen) {
 /**
  * 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;
@@ -130,7 +133,8 @@ enum nss_status ptsid2name(int uid, char **buffer, int *buflen) {
   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;
   }
@@ -138,7 +142,7 @@ enum nss_status ptsid2name(int uid, char **buffer, int *buflen) {
   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;
     }
@@ -161,7 +165,7 @@ enum nss_status ptsname2id(char *name, uid_t* uid) {
   namelist lnames;
   char uname[MAXUSERNAMELEN];
 
-  init_afs();
+  if (init_afs()) return NSS_STATUS_UNAVAIL;
   
   if (!strcmp(name,"anonymous")) {
     *uid = AFS_MAGIC_ANONYMOUS_USERID;
@@ -177,7 +181,8 @@ enum nss_status ptsname2id(char *name, uid_t* uid) {
   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;
   }
@@ -197,11 +202,35 @@ int init_afs() {
   int len;
   struct stat statbuf;
 
+  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 {
@@ -237,7 +266,10 @@ int init_afs() {
     /* time out requests after 5 seconds to avoid hanging things */
     rx_SetRxDeadTime(5);    
 
-    if (pr_Initialize(0L,AFSDIR_CLIENT_ETC_DIRPATH, 0)) break;
+    if (pr_Initialize(0L,AFSDIR_CLIENT_ETC_DIRPATH, 0)) {
+      perror("pr_Initialize() failed\n");
+      break;
+    }
     
     afs_initialized = 1;
     pthread_mutex_unlock(&mutex);
@@ -296,7 +328,7 @@ int get_shell(char *name, char **buffer, size_t *buflen) {
   int temp;
   char *b;
   char* bufx = buf;
-  int bufxlen = 256;
+  size_t bufxlen = 256;
   b=*buffer;
 
   switch (shells_method) {
@@ -359,10 +391,10 @@ enum nss_status _nss_afs_getgrgid_r (gid_t gid,
 
     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;
@@ -385,9 +417,9 @@ enum nss_status fill_result_buf(uid_t uid,
                                 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;