[OpenAFS] Re: unix owner/group of files in AFS

Adam Megacz megacz@cs.berkeley.edu
Fri, 23 Mar 2007 16:43:09 -0700


FB <fbo2@gmx.net> writes:
>> How hard would it be to fake shell info as well, say by creating 
>> shell.zsh, shell.bash, etc PTS groups and putting a pts user in one?

> Shouldn't be complicated. But maybe it's a better idea to evaluate a file
> or a symlink in the user's home-volume.

Here's a somewhat-hackish patch to use the contents of $HOME/.shell
(which should be world-readable) and default to bash if $HOME/.shell
can't be read.

  /afs/megacz.com/debian/patches/libnss-pts-use-shell-file-patch

  - a

--- libnss-ptdb-1.0.5/nss_ptdb.c	2004-11-13 11:03:10.000000000 -0800
+++ libnss-ptdb-1.0.5/nss_ptdb.c	2007-03-23 16:39:00.000000000 -0700
@@ -1,12 +1,15 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <pwd.h>
 #include <nss.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <unistd.h>
+#include <string.h>
 
 extern int ptsid2name(int uid,char **buffer,int *buflen);
 extern int ptsname2id(char *name,uid_t *uid,char **buffer);
@@ -90,6 +93,7 @@
 */
 enum nss_status _nss_ptdb_getpwuid_r (uid_t uid, struct passwd *result_buf,
  char *buffer, size_t buflen, int *errnop ) {
+  char scratch[1024];
 	if ( pathprefixlen == 0 ) {
 		read_cellname();
 		if ( pathprefixlen == 0 ) {
@@ -131,21 +135,36 @@
           return NSS_STATUS_TRYAGAIN;
         }
 
-	// Set the homedirectory
-	result_buf->pw_dir = buffer;
-	if ( ! get_homedir(result_buf->pw_name,&buffer,&buflen) ) {
-		*errnop = ERANGE;
-		return NSS_STATUS_TRYAGAIN;
-	}
-
-    /* our favorite shell--not very powerful be easy to document */
-    result_buf->pw_shell = buffer;
-    if ( ! cpstr("/bin/bash",&buffer, &buflen ) )
+    // Set the homedirectory
+    result_buf->pw_dir = buffer;
+    if ( ! get_homedir(result_buf->pw_name,&buffer,&buflen) ) {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+    
+    strcpy(scratch, result_buf->pw_dir);
+    strcat(scratch, "/.shell");
+    int fd = open(scratch, O_RDONLY);
+    if (fd != -1) {
+      int count = 0;
+      result_buf->pw_shell = buffer;
+      while(1) {
+        int result = read(fd, buffer, buflen);
+        if (result<=0) break;
+        buffer += result;
+        buflen -= result;
+      }
+      buffer[0] = '\0';
+      buffer++;
+    } else {
+      result_buf->pw_shell = buffer;
+      if ( ! cpstr("/bin/bash",&buffer, &buflen ) )
         {
           /* if ( log ) { fprintf(log,"%d:%d ERANGE, TRYAGAIN on shell\n",getpid(),uid ); fclose(log); } */
           *errnop = ERANGE;
           return NSS_STATUS_TRYAGAIN;
         }
+    }
 
     *errnop = errno;
     /* if ( log ) { fprintf(log,"%d:%d SUCCESS(%d)\n",getpid(),uid,NSS_STATUS_SUCCESS ); fclose(log); } */