File pure-ftpd-1.0.20-oes_remote_server.patch of Package pure-ftpd.import4353

--- src/ftpd.c	2004-07-17 18:58:22.000000000 +0530
+++ src/ftpd.c	2009-05-07 14:12:45.000000000 +0530
@@ -38,6 +38,20 @@
 # include <dmalloc.h>
 #endif
 
+#include <ldap.h>
+LDAP* ldapHandle;
+     
+
+// remote server navigation constants
+#define MAX_SERVER_SIZE 100
+#define MAX_PATH_SIZE 1000
+const char MOUNT_PATH[] = "/var/opt/novell/nclmnt";
+const int MOUNT_PATH_SIZE = 22;
+	
+char userFDN[512];
+static const char *getlocalhostname();
+	  
+
 #ifndef HAVE_SYS_FSUID_H
 void disablesignals(void)
 {
@@ -1496,6 +1510,9 @@ void dopass(char *password)
         /* Clear password from memory, paranoia */        
         register volatile char *password_ = (volatile char *) password;
         
+	if(remote_server == 1 )
+		edir_login(account,password,authresult.uid);
+
         while (*password_ != 0) {
             *password_++ = 0;
         }
@@ -1843,6 +1860,31 @@ void docwd(const char *dir)
         addreply(550, MSG_SANITY_FILE_FAILURE, where);
         return;
     }
+
+	char server[MAX_SERVER_SIZE],nss_loc[MAX_PATH_SIZE];
+	if(remote_server ==1 )
+	{	
+		// Not allowed to move inside the folder NCPVolForFTP
+		if (strstr(where,"nclmnt") != NULL)
+			goto cd_success;
+
+		getcwd(wd, sizeof wd - (size_t) 1U);
+
+		// cd .. is not allowed from base remote dir
+		if( (wd != NULL) && (strcmp(where,"..") == 0))
+		{	
+			if(strncmp(wd,MOUNT_PATH,MOUNT_PATH_SIZE) ==0)
+			{
+				if(strstr(wd+MOUNT_PATH_SIZE+1+strlen(account)+1,"/") == NULL )
+					goto cd_success;
+			}
+		}
+
+		//mount remote server
+		if ( mount_remote_server(where,nss_loc,server) == 0 )	
+			where = nss_loc;	
+
+	} 	
     if (chdir(where) != 0) {
         
 #ifdef WITH_DIRALIASES
@@ -1886,6 +1928,9 @@ void docwd(const char *dir)
     failures = 0UL;
     dobanner(1);
 #endif
+
+cd_success:
+    
     if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {
         if (*dir == '/') {
             if (SNCHECK(snprintf(wd, sizeof wd, "%s", dir), sizeof wd)) { /* already checked */
@@ -1899,6 +1944,10 @@ void docwd(const char *dir)
             }
         }
     }
+
+	if(remote_server ==1 )
+		get_remote_server_path(wd);
+
     addreply(250, MSG_CURRENT_DIR_IS, wd);
 }
 
@@ -3244,6 +3293,7 @@ void domkd(char *name)
 #endif
         error(550, MSG_MKD_FAILURE);
     } else {
+	get_remote_server_path(name);
         addreply(257, "\"%s\" : " MSG_MKD_SUCCESS, name);
     }
 #ifdef QUOTAS
@@ -4914,6 +4964,11 @@ int main(int argc, char *argv[])
             no_ipv4 = 1;
             break;
         }
+	case '9': {
+	    remote_server = 1;
+	    break;
+	}			     
+		  
         case '1': {
             log_pid = LOG_PID;
             break;
@@ -5560,3 +5615,242 @@ int main(int argc, char *argv[])
 
     return 0;
 }
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+
+int (*namGetUserFDNfromUID)    (int uid, char * userFDN);
+
+static const char *getlocalhostname()
+{
+	static char buf[1025];
+
+	if (gethostname(buf, sizeof buf - 1U) != 0) {
+		return NULL;
+	}
+	return buf;
+}
+
+int edir_login(const char* user,const char* passwd,int uid)
+{
+	int index =0,openCount = 0;
+	char tmp[MAX_PATH_SIZE+100];
+	FILE* fd = NULL;
+	char fdn[512];fdn[0] = '\0' ;	
+
+	const char* hostname = getlocalhostname();
+	
+	// get the FDN of user from pam_nam.so
+	void * lumHandle =  dlopen("/lib64/security/pam_nam.so", RTLD_LAZY);
+	if (lumHandle == NULL)
+		lumHandle =  dlopen("/lib/security/pam_nam.so", RTLD_LAZY);
+	if(lumHandle != NULL)
+	{
+		namGetUserFDNfromUID = (int (*)(int, char *))dlsym(lumHandle, "namGetUserFDNfromUID");
+		if(namGetUserFDNfromUID != NULL)
+		{	 
+			namGetUserFDNfromUID(uid, fdn);
+		} else			
+			logfile(LOG_ERR,"Function namGetUserFDNfromUID not found");
+		dlclose(lumHandle);
+	} else
+		logfile(LOG_ERR,"PAM library not found");
+
+	//copy user name provided by the ftp client incase pam_nam.so does not provide FDN of user
+	if (fdn[0] == '\0')
+		strncpy(fdn,user,sizeof(fdn));
+
+	//Convert . separared user FDN to ldap formated(, separated) user FDN
+	while (fdn[index] != '\0')
+	{	
+		if(fdn[index] != ',')
+			userFDN[index] = fdn[index];
+		else	
+			userFDN[index] = '.';
+		++index;
+	}
+	userFDN[index] = '\0';
+		
+	/*
+	   do nwlogin the local server.Same nw connection is reused for connecting to different machine.
+	 */  
+        snprintf(tmp,sizeof(tmp),"sudo -u %s nwlogin -s %s -u %s -p %s -c x > /dev/null",user,hostname,userFDN,passwd );
+        system(tmp);
+        
+	//create directories to store no of simultaneous logins by same user
+	mkdir("/var/opt/novell/pure-ftpd/",0777);
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s",account);
+	mkdir(tmp, 0777);
+	
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"r+");
+	
+	openCount = 1;
+	if(fd != NULL)
+	{
+		if(fread(&openCount,sizeof(int),1,fd) > 0)
+		{
+			if(openCount >= 0)
+				++openCount;
+			else
+				openCount = 1;
+		} else
+			 openCount = 1;
+		fclose(fd);	
+	} else
+		openCount = 1;
+	sprintf(tmp,"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"w+");
+	if(fd != NULL)
+	{
+		fwrite(&openCount,sizeof(int),1,fd);
+		fclose(fd);	
+	}
+
+        ldapHandle = ldap_init("127.0.0.1", 389);
+        if (ldapHandle == NULL)
+        {
+		logfile(LOG_ERR, "ldap init failed");
+		return 0;
+	}
+	ldap_simple_bind(ldapHandle,fdn,passwd);
+					  
+
+	
+	return 0;
+}
+
+int mount_remote_server(const char* where,char* nss_loc,char* remote_server)
+{
+	char tmp[MAX_PATH_SIZE+100],path[MAX_PATH_SIZE];
+	char* str1,*server;
+	int err;
+	struct hostent *he;
+	struct in_addr ipv4addr;
+	
+	if((where != NULL ) &&(strncmp(where,"//",2 ) ==0))
+	{
+		//Get the remote oes server path excluding server name
+		snprintf(path,sizeof(path),index(where+2, '/'));
+		
+		//Get the server name from remote oes path
+		str1 = (char*) where+2;
+		server = strtok(str1,"/");
+
+		/*
+		 * nwlogin as logged in ftp user. 
+		 * nwlogin does not require password here. novell client reuses exising connection
+		 */		
+		sprintf(tmp,"sudo -u %s nwlogin -s %s -u %s -p x -c x > /dev/null",account,server,userFDN);
+		err= system(tmp);
+
+		if(err !=0 )
+		{
+			snprintf(tmp,sizeof(tmp),"Novell Client Login Failed with error %d ",err);
+			logfile(LOG_ERR,tmp);
+			return -1;
+		}
+
+		/*
+			nwlogin mounts the remote server to dir with name "hostname"
+			ip address is converted to hostname
+		*/   
+		
+		if(inet_pton(AF_INET, server, &ipv4addr) > 0)
+		{	
+			he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
+			if(he != NULL)
+				server = strtok(he->h_name,".");
+		}
+		
+		if(nss_loc != NULL)
+			snprintf(nss_loc,MAX_PATH_SIZE,"%s/%s/%s/%s",MOUNT_PATH,account,server,path);
+		if(remote_server != NULL )
+			strncpy(remote_server,server, MAX_SERVER_SIZE);
+	
+		return 0;
+	}  else
+		return -1;	
+}
+
+
+int umount_remote_server()
+{
+	char tmp[MAX_PATH_SIZE+100];
+	int openCount = 0;
+	FILE* fd = NULL;
+	
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"r+");
+	if(fd != NULL)
+	{
+		if(fread(&openCount,sizeof(int),1,fd) > 0)
+		{
+			if (openCount > 0  )
+				--openCount;
+			else
+				openCount = 0;
+		} else
+			openCount = 0;
+			
+		fclose(fd);	
+		
+		fd = fopen(tmp,"w+");
+		fwrite(&openCount,sizeof(int),1,fd);
+		fclose(fd);	
+	} else	
+		logfile(LOG_ERR,"File Open failed");
+		
+	//nwlogout is not called when same ftp user is logged in more than once
+	if(openCount <= 0)	
+	{	
+		snprintf(tmp,sizeof(tmp),"sudo -u %s nwlogout -f -a > /dev/null",account);
+		system(tmp); 
+	}	
+	return 0;
+}
+
+int get_remote_server_path(char* path)
+{	
+	char tmp[MAX_PATH_SIZE];
+	
+	if (path == NULL)
+		return -1;
+
+	// Send the remote dir location as reply	
+	if( strncmp(path,MOUNT_PATH,MOUNT_PATH_SIZE) == 0)
+	{
+		snprintf(tmp,sizeof(tmp),"//%s",path+MOUNT_PATH_SIZE+1+strlen(account)+1);
+		strncpy(path,tmp,MAX_PATH_SIZE);
+	}	
+	return 0;
+}		
+int do_list_servers()
+{
+         //create server list
+         char* attrs[]={"cn",NULL};
+         char* ldapDN;
+         LDAPMessage* entry = NULL;
+         LDAPMessage* searchResult = NULL;
+
+        if (ldapHandle == NULL)
+        {
+                 logfile(LOG_ERR, "LDAP connection failed ");
+                 return -1;
+        }
+        int rc = ldap_search_ext_s(ldapHandle,"",LDAP_SCOPE_SUBTREE,"(&(objectclass=NCP Server))",
+		attrs,  0,NULL, NULL, 0, LDAP_NO_LIMIT, &searchResult);
+		
+	if(rc == LDAP_SUCCESS )
+	{
+		for(entry = ldap_first_entry(ldapHandle,searchResult) ; entry != NULL ;
+			entry = ldap_next_entry(ldapHandle,entry))
+	        {
+		        if(ldapDN = ldap_get_dn(ldapHandle,entry))
+				addreply_noformat(0, ldapDN);
+		}
+	} else
+		addreply_noformat(0, "");
+	return 0;
+}
+	   
--- src/ftpd_p.h	2004-03-01 03:19:28.000000000 +0530
+++ src/ftpd_p.h	2009-05-05 10:57:16.000000000 +0530
@@ -61,6 +61,7 @@ struct reply {
 
 static const char *GETOPT_OPTIONS =
     "0146Aa:bc:"
+    "9"
 #ifndef NO_STANDALONE
     "BC:"
 #endif
@@ -110,6 +111,7 @@ static struct option long_options[] = {
     { "logpid", 0, NULL, '1' },
     { "ipv4only", 0, NULL, '4' },
     { "ipv6only", 0, NULL, '6' },    
+    { "remoteserver", 0, NULL, '9' },    
     { "chrooteveryone", 0, NULL, 'A' },
     { "trustedgid", 1, NULL, 'a' },
     { "brokenclientscompatibility", 0, NULL, 'b' },
--- src/ftp_parser.c	2004-06-06 16:10:28.000000000 +0530
+++ src/ftp_parser.c	2009-05-05 10:57:17.000000000 +0530
@@ -16,6 +16,8 @@
 # include <dmalloc.h>
 #endif
 
+#define MAX_PATH_SIZE 1000
+
 static void antiidle(void)
 {
     if (noopidle == (time_t) -1) {
@@ -294,6 +296,8 @@ void parser(void)
             }
             dopass(arg);
         } else if (!strcmp(cmd, "quit")) {
+	    if(remote_server == 1)	
+	    	 umount_remote_server();	
             addreply(221, MSG_GOODBYE,
                      (unsigned long long) ((uploaded + 1023ULL) / 1024ULL),
                      (unsigned long long) ((downloaded + 1023ULL) / 1024ULL));
@@ -407,6 +411,10 @@ void parser(void)
             } else if (!strcmp(cmd, "cdup") || !strcmp(cmd, "xcup")) {
                 docwd("..");
             } else if (!strcmp(cmd, "retr")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
                     doretr(arg);
                 } else {
@@ -422,12 +430,20 @@ void parser(void)
                 }
                 goto wayout;
             } else if (!strcmp(cmd, "dele")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
                     dodele(arg);
                 } else {
                     addreply_noformat(501, MSG_NO_FILE_NAME);
                 }
             } else if (!strcmp(cmd, "stor")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
                     dostor(arg, 0, autorename);
@@ -435,6 +451,10 @@ void parser(void)
                     addreply_noformat(501, MSG_NO_FILE_NAME);
                 }
             } else if (!strcmp(cmd, "appe")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ((remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
                     dostor(arg, 1, 0);
@@ -447,6 +467,10 @@ void parser(void)
 #endif
 #ifndef DISABLE_MKD_RMD
             } else if (!strcmp(cmd, "mkd") || !strcmp(cmd, "xmkd")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ((remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
                     domkd(arg);
@@ -454,6 +478,10 @@ void parser(void)
                     addreply_noformat(501, MSG_NO_DIRECTORY_NAME);
                 }
             } else if (!strcmp(cmd, "rmd") || !strcmp(cmd, "xrmd")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
                     dormd(arg);
                 } else {
@@ -575,6 +603,8 @@ void parser(void)
                         }
                     }
 # endif
+		} else if (!strcasecmp(arg, "slist")) {
+		    do_list_servers();
                 } else if (*arg != 0) {
                     addreply(500, "SITE %s " MSG_UNKNOWN_EXTENSION, arg);
                 } else {
--- src/globals.h	2004-03-01 03:19:28.000000000 +0530
+++ src/globals.h	2009-05-05 10:57:19.000000000 +0530
@@ -29,6 +29,7 @@ GLOBAL(int datafd, -1);                 
 GLOBAL0(struct sockaddr_storage ctrlconn);    /* stdin/stdout, for using the same ip number */
 GLOBAL0(signed char v6ready);                    /* IPv6 supported or not */
 GLOBAL0(signed char no_ipv4);                    /* IPv4 disabled or not */
+GLOBAL0(signed char remote_server);                    /* OES remote server supported or not*/
 GLOBAL(const size_t cmdsize, MAXPATHLEN + 16U);
 GLOBAL0(char cmd[MAXPATHLEN + 32U]);        /* command line - about 30 chars for command */
 GLOBAL0(char wd[MAXPATHLEN + 1U]);            /* current working directory */
--- src/ls.c	2004-03-01 03:19:27.000000000 +0530
+++ src/ls.c	2009-05-05 10:57:16.000000000 +0530
@@ -12,6 +12,8 @@
 # include <dmalloc.h>
 #endif
 
+#define MAX_PATH_SIZE 1000
+
 static void wrstr(const int f, const char *s)
 {
     static char outbuf[CONF_TCP_SO_SNDBUF];
@@ -171,6 +173,7 @@ static void addfile(const char *name, co
     if (!name || !suffix) {
         return;
     }
+		    
     if (matches >= max_ls_files) {
         return;
     }
@@ -332,6 +335,11 @@ static int listfile(const PureFileInfo *
             if ((alloca_nameline = ALLOCA(sizeof_nameline)) == NULL) {
                 return 0;
             }
+	    char remote_file_name[MAX_PATH_SIZE];
+	    strncpy(remote_file_name,name,MAX_PATH_SIZE);
+	    if(remote_server == 1) 
+	    	get_remote_server_path(remote_file_name);
+		       
 #ifdef WITH_LARGE_FILES
             if (SNCHECK(snprintf(alloca_nameline, sizeof_nameline,
                                  "%s %4d %s %s %8llu %s %2d %s %s", 
@@ -339,7 +347,7 @@ static int listfile(const PureFileInfo *
                                  getgroup(st.st_gid), 
                                  (unsigned long long) st.st_size,
                                  months[t->tm_mon],
-                                 t->tm_mday, timeline, name),
+                                 t->tm_mday, timeline, remote_file_name),
                         sizeof_nameline))
 #else
             if (SNCHECK(snprintf(alloca_nameline, sizeof_nameline,
@@ -348,7 +356,7 @@ static int listfile(const PureFileInfo *
                                  getgroup(st.st_gid), 
                                  (unsigned long) st.st_size,
                                  months[t->tm_mon],
-                                 t->tm_mday, timeline, name),
+                                 t->tm_mday, timeline, remote_file_name),
                         sizeof_nameline))
 #endif
             {
@@ -796,6 +804,11 @@ void donlist(char *arg, const int on_ctr
 
         justone = 1;            /* just one argument, so don't print dir name */
 
+	// support full remote server path
+ 	 char nss_loc[MAX_PATH_SIZE];
+ 	if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+		arg = nss_loc;
+
         do {
             glob_t g;
             int a;