File pure-ftpd-1.0.20-oes_remote_server.patch of Package pure-ftpd
--- 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;