Documentation

Generated on Thu Aug 31 00:02:36 2006

 

Commands Class Reference

#include <Commands.h>

List of all members.


Public Member Functions

bool user (User *user, string &argument, unsigned int flag)
bool pass (User *user, string &argument, unsigned int flag)
bool retr (User *user, string &argument, unsigned int flag)
bool stor (User *user, string &argument, unsigned int flag)
bool port (User *user, string &argument, unsigned int flag)
bool quit (User *user, string &argument, unsigned int flag)
bool list (User *user, string &argument, unsigned int flag)
bool help (User *user, string &argument, unsigned int flag)
bool mkd (User *user, string &argument, unsigned int flag)
bool rmd (User *user, string &argument, unsigned int flag)
bool cwd (User *user, string &argument, unsigned int flag)
bool dele (User *user, string &argument, unsigned int flag)
bool pasv (User *user, string &argument, unsigned int flag)
bool rname (User *user, string &argument, unsigned int flag)
bool opts (User *user, string &argument, unsigned int flag)
bool rest (User *user, string &argument, unsigned int flag)
bool abor (User *user, string &argument, unsigned int flag)
bool sim1 (User *user, string &argument, unsigned int flag)
bool sim2 (User *user, string &argument, unsigned int flag)
bool auth (User *user, string &argument, unsigned int flag)

Public Attributes

sem_t pam_lock

Private Member Functions

string parsedir (User *, string)
string mlsx (User *, string)
string list_file (string)
string mlst_string (User *)

Detailed Description

Definition at line 26 of file Commands.h.


Member Function Documentation

bool Commands::abor ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 102 of file Commands2.cpp.

Referenced by Handler::Handler().

00103 {
00104   string message = "226 ";
00105   if(user->data_vec.empty())
00106     message += "No Data Connections to cancel";
00107   else
00108   {
00109     for(vector<class Data*>::iterator data_it = user->data_vec.begin();
00110         data_it != user->data_vec.end(); data_it++)
00111       if(*data_it)
00112         pthread_cancel((*data_it)->thread_id());
00113     message += "All Data Connections Successfully closed.";
00114   }
00115   *user << message << ".\r\n";
00116   return(true);
00117 }

bool Commands::auth ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 1212 of file Commands2.cpp.

References B_SET, config, DENY, FAILURE, Configuration::get_user(), and TLS_PROT_D.

Referenced by Handler::Handler().

01213 {
01214   transform(argument.begin(), argument.end(), argument.begin(),
01215       (int(*)(int))toupper);
01216 
01217   if(argument == "TLS" || argument == "TLS-C" || argument == "SSL")
01218   {
01219     if(config->get_user(user->user_name()).encryption == DENY)
01220     {
01221       *user <<
01222         "421 Sorry, you are not allowed to use encryption, disconnecting.\r\n";
01223       user->settings(FAILURE, B_SET);
01224       return false;
01225     }
01226     *user << "234 Now starting encryption using TLS.\r\n";
01227     if(!user->engage_tls())
01228     { // failure =(
01229       user->settings(FAILURE, B_SET);
01230       *user << "421 Handshake failed. Disconnecting.\r\n";
01231     }
01232     else
01233     { // wee!
01234       if(argument == "SSL")
01235         user->settings(TLS_PROT_D, B_SET);
01236     }
01237   }
01238   else
01239     *user << "504 Sorry, I don't understand the mechanism '"
01240       << argument << "'.\r\n";
01241 
01242   return true;
01243 }

Here is the call graph for this function:

bool Commands::cwd ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 255 of file Commands2.cpp.

References COM_CDUP, Utilities::is_set(), and util.

Referenced by Handler::Handler().

00256 {
00257   struct stat stt;
00258   string message, new_dir;
00259   DIR *tmp_dir;
00260 
00261   if(util.is_set(flag, COM_CDUP))
00262     argument = "..";
00263 
00264   if((user->root_dir().size() > 1 && (user->current_dir().size() ==
00265           user->root_dir().size())) && (argument == ".." || argument == "."))
00266     new_dir = user->root_dir();
00267   else
00268     new_dir = this->parsedir(user, argument);
00269 
00270 
00271   lstat(new_dir.c_str(), &stt);
00272 
00273   if(S_ISLNK(stt.st_mode))
00274   {
00275     char real_name[65] = { 0 };
00276     int len;
00277 
00278     len = readlink(new_dir.c_str(), real_name, 60);
00279     real_name[len] = '\0';
00280 
00281     new_dir = this->parsedir(user, real_name);
00282   }
00283 
00284   if(!(tmp_dir = opendir(new_dir.c_str())))
00285   {
00286     if(errno == EACCES)
00287       message = "550 '" + new_dir + "' permission denied.";
00288     else
00289       message = "550 '" + new_dir + "' no such file or directory.";
00290   }
00291   else
00292   {
00293     if(util.is_set(flag, COM_CDUP))
00294       message = "200 'CDUP' command successful.";
00295     else // COM_CWD
00296       message = "250 'CWD' command successful.";
00297 
00298     user->current_dir(new_dir);
00299   }
00300   closedir(tmp_dir);
00301   *user << message << "\r\n";
00302   return(true);
00303 }

Here is the call graph for this function:

bool Commands::dele ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 744 of file Commands2.cpp.

Referenced by Handler::Handler().

00745 {
00746   string message, new_file = parsedir(user, argument);
00747 
00748   if(unlink(new_file.c_str()))
00749   {
00750     message = "550 ";
00751     if(errno == EPERM || errno == EACCES)
00752       message += "File access denied, not deleted.";
00753     else if(errno == EPERM)
00754       message += "File \"" + new_file + "\" is a directory.";
00755     else if(errno == ENOENT || errno == EISDIR)
00756       message += "File not found.";
00757     else
00758       message = "450 File not available.";
00759   }
00760   else
00761     message = "250 'DELE' command successful.";
00762 
00763   *user << message << "\r\n";
00764   return(true);
00765 }

bool Commands::help ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 212 of file Commands2.cpp.

References general_stru::admin_email, Handler::cmd_info, config, Configuration::general, and handler.

Referenced by Handler::Handler().

00213 {
00214   string message;
00215   if(!argument.size())
00216   {
00217     int cmd = 0;
00218     message = "214-The following commands are understood:\r\n ";
00219     for(hash_map<const char*, struct command_info, hash<const char*>,
00220         Utilities::eqstr>::iterator cmd_it = handler->cmd_info.begin();
00221         cmd_it != handler->cmd_info.end(); cmd_it++)
00222     {
00223       if(!(*(cmd_it)).second.hlp_info.empty())
00224       {
00225         if(cmd != 0 && cmd % 8 == 0)
00226           message += "\r\n ";
00227         message += (*(cmd_it)).first;
00228         message += '\t';
00229         cmd++;
00230       }
00231     }
00232     message +=
00233       "\r\n214 if you have any trouble please contact the administrator at "
00234       + config->general.admin_email + ".";
00235   }
00236   else
00237   {
00238     // other help stuff here...
00239     message  = "214 Syntax: ";
00240     transform(argument.begin(), argument.end(), argument.begin(),
00241         (int(*)(int))toupper);
00242     hash_map<const char*, struct command_info, hash<const char*>, Utilities::
00243       eqstr>::iterator cmd_it = handler->cmd_info.find(argument.c_str());
00244 
00245     if(cmd_it != handler->cmd_info.end() &&
00246         !(*(cmd_it)).second.hlp_info.empty())
00247       message += ((*(cmd_it)).first + (*(cmd_it)).second.hlp_info);
00248     else
00249       message = "500 No help available for '" + argument + "'";
00250   }
00251   *user << message << "\r\n";
00252   return(true);
00253 }

bool Commands::list ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 418 of file Commands2.cpp.

References COM_LONG, COM_MLSD, COM_SHORT, Data::Data(), DATA_OPEN, Connection::engage_tls(), FAILURE, Utilities::is_set(), Connection::settings(), TLS_PROT_D, Data::user, and util.

Referenced by Handler::Handler().

00419 {
00420   struct stat stt;
00421   string failure;
00422 
00423   if(argument.size() == 0)
00424     argument = user->current_dir();
00425 
00426   string file = parsedir(user, argument);
00427 
00428   if((lstat(file.c_str(), &stt)) == -1 && ((util.is_set(flag, COM_LONG) ||
00429           util.is_set(flag, COM_MLSD)) && argument[0] == '-'))
00430   {
00431     class StringTokenizer *token = new StringTokenizer(argument, " ", false);
00432     token->nextToken();
00433     argument = token->restTokens();
00434     delete token;
00435     file = parsedir(user, argument);
00436     lstat(file.c_str(), &stt);
00437   }
00438 
00439   if(!S_ISDIR(stt.st_mode) && util.is_set(flag, COM_MLSD))
00440   {
00441     *user << "501 Argument to MLSD has to be a directory.\r\n";
00442     return false;
00443   }
00444 
00445   class Data *data = new Data(user);
00446 
00447   if(!data->settings(DATA_OPEN))
00448     failure = "425 Can't open data connection.";
00449   else
00450   {
00451     *user << "150 Opening ";
00452 #ifdef USE_TLS
00453     if(data->settings(TLS_PROT_D))
00454     {
00455       *user << "PROTECTED ASCII mode data connection for file list.\r\n";
00456       if(!data->engage_tls())
00457         failure =
00458           "451 Failed to negotiate TLS as was asked. Closing data connection.";
00459     }
00460     else
00461 #endif // USE_TLS
00462       *user << " ASCII mode data connection for file list.\r\n";
00463     if(S_ISDIR(stt.st_mode))
00464     {
00465       struct dirent dirstr, *dirptr;
00466       vector<string> dirlist;
00467 
00468       DIR *dirp = opendir(file.c_str());
00469       while((readdir_r(dirp, &dirstr, &dirptr) == 0) && dirptr != NULL)
00470       {
00471 #ifdef _DIRENT_HAVE_D_TYPE
00472         if((dirstr.d_type == DT_DIR) && util.is_set(flag, COM_SHORT))
00473           continue;
00474 #endif // _DIRENT_HAVE_D_TYPE
00475         dirlist.push_back(dirstr.d_name);
00476       }
00477 
00478       closedir(dirp);
00479 
00480       // sorting the directory so we output first things first
00481       sort(dirlist.begin(), dirlist.end());
00482       for(vector<string>::iterator dir_it = dirlist.begin();
00483           dir_it != dirlist.end(); dir_it++)
00484       {
00485         if(util.is_set(flag, COM_LONG))
00486           *data << list_file(file + "/" + *dir_it);
00487         else if(util.is_set(flag, COM_MLSD))
00488           *data << mlsx(user, file + "/" + *dir_it);
00489         else
00490           *data << *dir_it; // short list.
00491 
00492         *data << "\r\n";
00493         if(data->settings(FAILURE))
00494           break;
00495       }
00496     }
00497     else
00498     {
00499       if(util.is_set(flag, COM_LONG))
00500         *data << list_file(file);
00501       else // NLST
00502         *data << argument;
00503       *data << "\r\n";
00504     }
00505     if(data->settings(FAILURE))
00506       failure = "426 LIST transfer failed.";
00507   }
00508   if(failure.size() > 0)
00509     *user << failure << "\r\n";
00510   else
00511     *user << "226 Transfer complete.\r\n";
00512 
00513   delete data;
00514   return(true);
00515 }

Here is the call graph for this function:

string Commands::list_file ( string   )  [private]

Definition at line 517 of file Commands2.cpp.

References Utilities::itos(), Utilities::parse_perms_ls(), PWBUF_SIZE, Utilities::time_string(), and util.

00518 {
00519   char size[20], nlink[6], pwdbuf[PWBUF_SIZE], grpbuf[PWBUF_SIZE];
00520   string user_name, group_name, time_string;
00521   struct stat file_stat;
00522   struct passwd pwd, *pwd_ptr;
00523   struct group grp, *grp_ptr;
00524 
00525   lstat(file_name.c_str(), &file_stat);
00526 
00527   // number of hard links
00528   snprintf(nlink, 5, "%3d ", static_cast<int>(file_stat.st_nlink));
00529 
00530   if((getpwuid_r(file_stat.st_uid, &pwd, pwdbuf, sizeof(pwdbuf),
00531           &pwd_ptr)) == 0)
00532     user_name = pwd.pw_name;
00533   else
00534     user_name = util.itos(file_stat.st_uid);
00535 
00536   if((getgrgid_r(file_stat.st_gid, &grp, grpbuf, sizeof(grpbuf),
00537           &grp_ptr)) == 0)
00538     group_name = grp.gr_name;
00539   else
00540     group_name = util.itos(file_stat.st_gid);
00541 
00542   snprintf(size, 19, "%9d ", static_cast<int>(file_stat.st_size)); // filesize
00543 
00544   // modification time, either in new ls format, or old..
00545 #ifdef USE_NEWLS
00546   string time_format = "%Y-%m-%d %H:%M ";
00547 #else
00548   string time_format;
00549   // is the file over a year old?
00550   if((time(NULL) - file_stat.st_mtime) > (60 * 60 * 24 * 365))
00551     time_format = "%b %e  %Y ";
00552   else // if it's not, we display the time it was created as well.
00553     time_format = "%b %e %H:%M ";
00554 #endif // USE_NEWLS
00555 
00556   util.time_string(time_string, time_format, 25, file_stat.st_mtime);
00557 
00558   string message = (util.parse_perms_ls(file_stat.st_mode) + ' ')
00559     + nlink + user_name + '\t' + group_name + '\t' + size + time_string
00560     + basename(file_name.c_str()); // parsing everything on one line is neater.
00561 
00562   // if it's a link...
00563   if(S_ISLNK(file_stat.st_mode))
00564   {
00565     char real_name[55];
00566     int len = readlink(file_name.c_str(), real_name, 50);
00567     real_name[len] = '\0';
00568     message += " -> ";
00569     message += real_name;
00570   }
00571   return(message);
00572 }

Here is the call graph for this function:

bool Commands::mkd ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 700 of file Commands2.cpp.

Referenced by Handler::Handler().

00701 {
00702   string message, new_dir = parsedir(user, argument);
00703 
00704   if(mkdir(new_dir.c_str(), 0755))
00705   {
00706     message = "550 ";
00707     if(errno == EEXIST)
00708       message += "File exists.";
00709     else if(errno == EACCES)
00710       message += "Write access denied.";
00711     else if(errno == (ENOTDIR || ENOENT))
00712       message += "Faulty pathname, directory not created.";
00713     else
00714       message += "Directory not created.";
00715   }
00716   else
00717     message = "257 \"" + argument + "\" created.";
00718 
00719   *user << message << "\r\n";
00720   return(true);
00721 }

string Commands::mlst_string ( User  )  [private]

Definition at line 1003 of file Commands2.cpp.

References FACT_MODIFY, FACT_PERM, FACT_SIZE, FACT_TYPE, FACT_U_GID, FACT_U_LINK, FACT_U_MODE, FACT_U_UID, FACT_UNIQUE, and user().

01004 {
01005   string message;
01006 
01007   message += ("Type"); message +=
01008     (user->settings(FACT_TYPE) ? "*;" : ";");
01009   message += ("Size"); message +=
01010     (user->settings(FACT_SIZE) ? "*;" : ";");
01011   message += ("Modify"); message +=
01012     (user->settings(FACT_MODIFY) ? "*;" : ";");
01013   message += ("Unique"); message +=
01014     (user->settings(FACT_UNIQUE) ? "*;" : ";");
01015   message += ("Perm"); message +=
01016     (user->settings(FACT_PERM) ? "*;" : ";");
01017   message += ("Unix.mode"); message +=
01018     (user->settings(FACT_U_MODE) ? "*;" : ";");
01019   message += ("Unix.uid"); message +=
01020     (user->settings(FACT_U_UID) ? "*;" : ";");
01021   message += ("Unix.gid"); message +=
01022     (user->settings(FACT_U_GID) ? "*;" : ";");
01023   message += ("Unix.link"); message +=
01024     (user->settings(FACT_U_LINK) ? "*;" : ";");
01025   return(message);
01026 }

Here is the call graph for this function:

string Commands::mlsx ( User ,
string   
) [private]

Definition at line 574 of file Commands2.cpp.

References FACT_MODIFY, FACT_PERM, FACT_SIZE, FACT_TYPE, FACT_U_GID, FACT_U_LINK, FACT_U_MODE, FACT_U_UID, FACT_UNIQUE, Utilities::is_set(), Utilities::itos(), Utilities::parse_perms_num(), parsedir(), PWBUF_SIZE, Utilities::time_string(), user(), and util.

00575 {
00576   char pwdbuf[PWBUF_SIZE], grpbuf[PWBUF_SIZE];
00577   struct passwd pwd, *pwd_ptr;
00578   struct group grp, *grp_ptr;
00579 
00580   struct stat stt;
00581   string message;
00582 
00583   lstat(file_name.c_str(), &stt);
00584 
00585   // type.
00586   if(user->settings(FACT_TYPE))
00587   {
00588     string type;
00589     if(S_ISREG(stt.st_mode))
00590       type = "file";
00591     else if(S_ISDIR(stt.st_mode))
00592     {
00593       if(file_name == user->current_dir())
00594       {
00595         type = "cdir";
00596         file_name += "/.";
00597       }
00598       else if(file_name == parsedir(user, user->current_dir() + "/.."))
00599         type = "pdir";
00600       else
00601         type = "dir";
00602     }
00603     else if(S_ISLNK(stt.st_mode))
00604       type = "OS.unix=slink";
00605     else if(S_ISCHR(stt.st_mode))
00606       type = "OS.unix=chr";
00607     else if(S_ISBLK(stt.st_mode))
00608       type = "OS.unix=blk";
00609     else if(S_ISFIFO(stt.st_mode))
00610       type = "OS.unix=fifo"; // or?
00611     else if(S_ISSOCK(stt.st_mode))
00612       type = "OS.unix=sock"; // or?
00613 
00614     message =  "Type=" + type + ";";
00615   }
00616 
00617   if(user->settings(FACT_SIZE))
00618     message += "Size=" + util.itos(stt.st_size) + ";";
00619   if(user->settings(FACT_MODIFY))
00620   {
00621     string tmp_time;
00622     util.time_string(tmp_time, "Modify=%Y%m%d%H%M%S;", 23, stt.st_mtime);
00623     message += tmp_time;
00624   }
00625   if(user->settings(FACT_UNIQUE))
00626     message += "Unique=" + util.itos(stt.st_dev) + "g" +
00627       util.itos(stt.st_ino) + ";";
00628   if(user->settings(FACT_PERM))
00629   {
00630     bool owner = false, group = false;
00631 
00632     if(getpwnam_r(user->user_name().c_str(), &pwd, pwdbuf, sizeof(pwdbuf),
00633           &pwd_ptr))
00634     {
00635       if(pwd.pw_uid == stt.st_uid)
00636         owner = true;
00637       else if(pwd.pw_gid == stt.st_gid)
00638         group = true;
00639     }
00640 
00641     if(!group && !owner)
00642     {
00643       if(getgrgid_r(stt.st_gid, &grp, grpbuf, sizeof(grpbuf), &grp_ptr))
00644         for(int i = 0; grp.gr_mem[i] != NULL; i++)
00645           if(user->user_name() == grp.gr_mem[i])
00646             group = true;
00647     }
00648 
00649     message += "Perm=";
00650     if(owner)
00651     {
00652       if(S_ISDIR(stt.st_mode))
00653       {
00654         if(util.is_set(stt.st_mode, S_IRUSR)) message += "l";
00655         if(util.is_set(stt.st_mode, S_IWUSR)) message += "cmp";
00656         if(util.is_set(stt.st_mode, S_IXUSR)) message += "e";
00657       }
00658       if(util.is_set(stt.st_mode, S_IRUSR)) message += "r";
00659       if(util.is_set(stt.st_mode, S_IWUSR)) message += "adfw";
00660     }
00661     else if(group)
00662     {
00663       if(S_ISDIR(stt.st_mode))
00664       {
00665         if(util.is_set(stt.st_mode, S_IRGRP)) message += "l";
00666         if(util.is_set(stt.st_mode, S_IWGRP)) message += "cmp";
00667         if(util.is_set(stt.st_mode, S_IXGRP)) message += "e";
00668       }
00669       if(util.is_set(stt.st_mode, S_IRGRP)) message += "r";
00670       if(util.is_set(stt.st_mode, S_IWGRP)) message += "adfw";
00671     }
00672     else
00673     {
00674       if(S_ISDIR(stt.st_mode))
00675       {
00676         if(util.is_set(stt.st_mode, S_IROTH)) message += "l";
00677         if(util.is_set(stt.st_mode, S_IWOTH)) message += "cmp";
00678         if(util.is_set(stt.st_mode, S_IXOTH)) message += "e";
00679       }
00680       if(util.is_set(stt.st_mode, S_IROTH)) message += "r";
00681       if(util.is_set(stt.st_mode, S_IWOTH)) message += "adfw";
00682     }
00683     message += ";";
00684   }
00685   if(user->settings(FACT_U_MODE))
00686     message += "Unix.mode=" + util.parse_perms_num(stt.st_mode) + ";";
00687   if(user->settings(FACT_U_UID))
00688     message += "Unix.uid=" + util.itos(stt.st_uid) + ";";
00689   if(user->settings(FACT_U_GID))
00690     message += "Unix.gid=" + util.itos(stt.st_gid) + ";";
00691   if(user->settings(FACT_U_LINK))
00692     message += "Unix.link=" + util.itos(stt.st_nlink) + ";";
00693   if(user->root_dir().size() > 1)
00694     file_name.erase(0, user->root_dir().size());
00695   message += " " + file_name;
00696 
00697   return(message);
00698 }

Here is the call graph for this function:

bool Commands::opts ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 952 of file Commands2.cpp.

References B_FLIP, FACT_MODIFY, FACT_PERM, FACT_SIZE, FACT_TYPE, FACT_U_GID, FACT_U_LINK, FACT_U_MODE, FACT_U_UID, FACT_UNIQUE, and StringTokenizer::StringTokenizer().

Referenced by Handler::Handler().

00953 {
00954   string command, message;
00955   class StringTokenizer *st;
00956 
00957   if(argument == "")
00958   {
00959     message += "500-Recognized OPTS arguments: \r\n";
00960     message += " MLST\r\n";
00961     message += "500 End.";
00962   }
00963   else
00964   {
00965     transform(argument.begin(), argument.end(), argument.begin(),
00966         (int(*)(int))toupper);
00967     st = new StringTokenizer(argument, " ", false);
00968     command = st->nextToken();
00969     argument = st->restTokens();
00970     delete st;
00971 
00972     if(command == "MLST")
00973     {
00974       string fact;
00975       st = new StringTokenizer(argument, ";", false);
00976 
00977       while(st->hasMoreTokens())
00978       {
00979         fact = st->nextToken();
00980         if(fact == "TYPE") user->settings(FACT_TYPE, B_FLIP);
00981         else if(fact == "SIZE") user->settings(FACT_SIZE, B_FLIP);
00982         else if(fact == "MODIFY") user->settings(FACT_MODIFY, B_FLIP);
00983         else if(fact == "UNIQUE") user->settings(FACT_UNIQUE, B_FLIP);
00984         else if(fact == "PERM") user->settings(FACT_PERM, B_FLIP);
00985         else if(fact == "UNIX.MODE") user->settings(FACT_U_MODE, B_FLIP);
00986         else if(fact == "UNIX.UID") user->settings(FACT_U_UID, B_FLIP);
00987         else if(fact == "UNIX.GID") user->settings(FACT_U_GID, B_FLIP);
00988         else if(fact == "UNIX.LINK") user->settings(FACT_U_LINK, B_FLIP);
00989       };
00990 
00991       message = "200 MLST string now showing: " + mlst_string(user);
00992       delete st;
00993     }
00994     else
00995       message = "501 " + command + " not known as argument to OPTS.";
00996   }
00997 
00998   *user << message << "\r\n";
00999 
01000   return(true);
01001 }

Here is the call graph for this function:

string Commands::parsedir ( User ,
string   
) [private]

Definition at line 127 of file Commands.cpp.

References StringTokenizer::countTokens(), StringTokenizer::hasMoreTokens(), StringTokenizer::nextToken(), StringTokenizer::StringTokenizer(), and user().

Referenced by mlsx().

00128 {
00129   string new_string;
00130 
00131   if(orig_string[0] != '/')
00132     orig_string = user->current_dir() + '/' + orig_string;
00133 
00134   class StringTokenizer *token = new StringTokenizer(orig_string, "/", false);
00135   vector<string> dir_array;
00136   dir_array.reserve(token->countTokens());
00137 
00138   while(token->hasMoreTokens())
00139   {
00140     dir_array.push_back(token->nextToken());
00141 
00142     if(dir_array.back().size() < 3)
00143     { // to save us from expensive string comparisons
00144       if(dir_array.back() == "..")
00145       {
00146         dir_array.pop_back();
00147         if(!dir_array.empty())
00148           dir_array.pop_back();
00149       }
00150       else if(dir_array.back() == ".")
00151         dir_array.pop_back();
00152     }
00153   }
00154   delete token;
00155 
00156   if(dir_array.empty())
00157     new_string = '/';
00158   else
00159     for(vector<string>::iterator dir_it = dir_array.begin();
00160         dir_it != dir_array.end(); dir_it++)
00161       new_string += '/' + *dir_it;
00162 
00163   if(user->root_dir().size() > 1)
00164     if(new_string.find(user->root_dir()) != 0)
00165       new_string = user->root_dir() + new_string;
00166 
00167 
00168   return(new_string);
00169 }

Here is the call graph for this function:

bool Commands::pass ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 119 of file Commands2.cpp.

References A_ENABLE, ANONYMOUS, general_stru::anonymous, B_SET, comm, config, Configuration::general, Log::log_this(), LOGGED_IN, logging, NOT_LOGGED_IN, pam_conversate(), PAM_DONE, pam_lock, PWBUF_SIZE, TYPE_INFO, general_stru::user, pam_data::user_name, and USER_SUPPLIED.

Referenced by Handler::Handler().

00120 {
00121   // before everything else, lets check if it is really time for pass...
00122   if(user->logged_in() != USER_SUPPLIED)
00123   {
00124     string message;
00125     if(user->logged_in() == NOT_LOGGED_IN)
00126       message = "503 Login with 'USER' first.";
00127     else if(user->logged_in() == LOGGED_IN)
00128       message = "503 You are already logged in!";
00129 
00130     *user << message << "\r\n";
00131     return(false);
00132   }
00133 
00134   // is anonymous login enabled?
00135   if(config->general.anonymous >= A_ENABLE &&
00136       user->user_name() == "anonymous")
00137   {
00138     char pwdbuf[PWBUF_SIZE];
00139     struct passwd pwd, *pwd_ptr;
00140     getpwuid_r(config->general.user, &pwd, pwdbuf, sizeof(pwdbuf), &pwd_ptr);
00141     user->user_name(pwd.pw_name);
00142 
00143     // maybe we should do some rudimentary checking of the adress? no?
00144     logging->log_this(3, TYPE_INFO, "anonymous login from " + user->host_name()
00145         + " with email " + argument + ".");
00146     *user << "230 Anonymous login successful.\r\n";
00147     user->login();
00148     user->settings(ANONYMOUS, B_SET);
00149     user->anonymous_id(argument);
00150     return(true);
00151   }
00152 
00153   seteuid(0); // we need to become root to check the user
00154   // pam stuff
00155   struct pam_data *auth_data = new struct pam_data;
00156   struct pam_conv pamconv = { &pam_conversate, auth_data };
00157   int pam_error = 0;
00158   pam_handle_t *tmp_pamh = user->pamh();
00159 
00160   auth_data->user_name = user->user_name();
00161   auth_data->password = argument;
00162   argument.clear();
00163 
00164   sem_wait(&comm.pam_lock);
00165   pam_error = pam_start("babyftpd", user->user_name().c_str(),
00166       &pamconv, &tmp_pamh);
00167   user->pamh(tmp_pamh);
00168 
00169   if(pam_error == 0)
00170   {
00171     pam_error = pam_authenticate(user->pamh(), 0);
00172     if(pam_error == 0)
00173     {
00174       pam_error = pam_acct_mgmt(user->pamh(), 0);
00175       if(pam_error == 0)
00176         pam_error = pam_setcred(user->pamh(), PAM_ESTABLISH_CRED);
00177     }
00178   }
00179   if(pam_error != 0)
00180   {
00181     pam_end(user->pamh(), pam_error);
00182     sem_post(&pam_lock);
00183     seteuid(config->general.user); // and back to some other user..
00184   }
00185 
00186   delete auth_data;
00187 
00188   if(pam_error == 0)
00189   {
00190     pam_open_session(user->pamh(), PAM_SILENT);
00191     user->settings(PAM_DONE, B_SET);
00192 
00193     const char *pam_username;
00194     pam_get_item(user->pamh(), PAM_USER,
00195         (reinterpret_cast<const void**>(&pam_username)));
00196     sem_post(&pam_lock);
00197     if(user->user_name() != pam_username)
00198     {
00199       logging->log_this(3, TYPE_INFO, "PAM changed username of " +
00200           user->user_name() + " to " + pam_username);
00201       user->user_name(pam_username);
00202     }
00203 
00204       *user << "230 Password accepted, proceeding.\r\n";
00205     user->login();
00206     return(true);
00207   }
00208   *user << "530 Login denied.\r\n";
00209   return(false);
00210 }

Here is the call graph for this function:

bool Commands::pasv ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 845 of file Commands2.cpp.

References B_SET, COM_EPSV, COM_PASV, EPSV_ONLY, Utilities::is_set(), Utilities::itos(), StringTokenizer::nextToken(), PASSIVE, PROT_IPV4, StringTokenizer::StringTokenizer(), and util.

Referenced by Handler::Handler().

00846 {
00847   string message;
00848 
00849   if(util.is_set(flag, COM_EPSV) && argument.size() > 0)
00850   {
00851     transform(argument.begin(), argument.end(), argument.begin(),
00852         (int(*)(int))toupper);
00853     if(argument == "ALL" && util.is_set(flag, COM_EPSV))
00854     {
00855       user->settings(EPSV_ONLY, B_SET);
00856       message = "200 Now only accepting 'EPSV'";
00857     }
00858     else
00859       message = "501 '" + argument + "' is not a valid argument to 'EPSV'.";
00860   }
00861   else
00862   {
00863     struct sockaddr_in tmp_addr = {0}, tmp_addr1 = {0}, tmp_addr2 = {0};
00864     socklen_t len = sizeof(tmp_addr);
00865 
00866     if(user->data_id())
00867       close(user->data_id());
00868 
00869     user->data_id(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
00870     tmp_addr.sin_family = AF_INET;
00871     tmp_addr.sin_addr.s_addr = INADDR_ANY;
00872     bind(user->data_id(), reinterpret_cast<struct sockaddr*>
00873         (&tmp_addr), sizeof(tmp_addr));
00874     user->data_addr(tmp_addr);
00875     listen(user->data_id(), 1);
00876     getsockname(user->data_id(), reinterpret_cast<struct sockaddr*>
00877         (&tmp_addr1), &len);
00878     getsockname(user->socket_id(), reinterpret_cast<struct sockaddr*>
00879         (&tmp_addr2), &len);
00880     user->settings(PASSIVE, B_SET);
00881 
00882     unsigned int p = ntohs(tmp_addr1.sin_port);
00883 
00884     if(util.is_set(flag, COM_PASV))
00885     {
00886       if(user->settings(EPSV_ONLY))
00887         message =
00888           "501 Only 'EPSV' may be used after the issuing of 'EPSV ALL'";
00889 
00890       else
00891       {
00892         class StringTokenizer *token =
00893           new StringTokenizer(inet_ntoa(tmp_addr2.sin_addr), ".", false);
00894 
00895         message = "227 Entering Passive Mode (";
00896         message += token->nextToken() + ",";
00897         message += token->nextToken() + ",";
00898         message += token->nextToken() + ",";
00899         message += token->nextToken() + ",";
00900         message += util.itos(p / 256) + ","
00901           + util.itos(p % 256) + ").";
00902 
00903         delete token;
00904       }
00905     }
00906     else if(util.is_set(flag, COM_EPSV))
00907     {
00908       if(argument.size() > 0)
00909         if(argument != util.itos(PROT_IPV4))
00910           message = "522 Network protocol not supported, use (1)";
00911 
00912       if(message.size() == 0)
00913         message = "229 Entering Extended Passive Mode (|||" +
00914           util.itos(p) + "|)";
00915     }
00916   }
00917   *user << message << "\r\n";
00918   return(true);
00919 }

Here is the call graph for this function:

bool Commands::port ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 767 of file Commands2.cpp.

References B_RESET, COM_EPRT, COM_PORT, config, EPSV_ONLY, Configuration::get_user(), Utilities::is_set(), Utilities::itos(), PASSIVE, PROT_IPV4, and util.

Referenced by Handler::Handler().

00768 {
00769   string tmp_adress, message;
00770   int port = -1;
00771 
00772   if(user->settings(EPSV_ONLY))
00773     message = "501 Only 'EPSV' may be used after the issuing of 'EPSV ALL'";
00774 
00775   else if((config->get_user(user->user_name()).only_passive))
00776     message =
00777       "501 Sorry, active data transfers are disabled for your account.";
00778 
00779   else if(util.is_set(flag, COM_PORT))
00780   {
00781     class StringTokenizer *token = new StringTokenizer(argument, ",", false);
00782 
00783     if(token->countTokens() != 6)
00784       message = "501 Illegal 'PORT' command.";
00785 
00786     else
00787     {
00788       tmp_adress = token->nextToken() + ".";  // if we do this on one line
00789       tmp_adress += token->nextToken() + "."; // it builds the string from
00790       tmp_adress += token->nextToken() + "."; // the wrong direction, it's
00791       tmp_adress += token->nextToken();       // weird.
00792 
00793       port = atoi((token->nextToken()).c_str()) * 256 +
00794           atoi((token->nextToken()).c_str());
00795     }
00796     delete token;
00797   }
00798   else if(util.is_set(flag, COM_EPRT))
00799   {
00800     class StringTokenizer *token =
00801       new StringTokenizer(argument, argument.substr(0, 1), false);
00802 
00803     if(token->countTokens() != 3 ||
00804         argument[argument.size() - 1] != argument[0])
00805       message = "501 Illegal 'EPRT' command.";
00806 
00807     else
00808     {
00809       if(token->nextToken() == util.itos(PROT_IPV4))
00810       {
00811         tmp_adress = token->nextToken();
00812         port = atoi(token->nextToken().c_str());
00813       }
00814       else
00815         message = "522 Network protocol not supported, use (1)";
00816     }
00817     delete token;
00818   }
00819 
00820   if(message.empty())
00821   {
00822     struct sockaddr_in temp_addr;
00823     if((inet_aton(tmp_adress.c_str(), &temp_addr.sin_addr)) == 0)
00824     {
00825       message = "501 Illegal '";
00826       message += (util.is_set(flag, COM_PORT) ? "PORT" : "EPRT");
00827       message += "' command.";
00828     }
00829     else
00830     {
00831       temp_addr.sin_port = htons(port);
00832       temp_addr.sin_family = AF_INET;
00833       user->settings(PASSIVE, B_RESET);
00834       message += "200 '";
00835       message += (util.is_set(flag, COM_PORT) ? "PORT" : "EPRT");
00836       message += "' command successful.";
00837     }
00838     user->data_addr(temp_addr);
00839   }
00840 
00841   *user << message << "\r\n";
00842   return(true);
00843 }

Here is the call graph for this function:

bool Commands::quit ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 15 of file Commands2.cpp.

References B_SET, and FAILURE.

Referenced by Handler::Handler().

00016 {
00017   *user << "221 Goodbye. You transfered a total of "
00018     << user->transfered() << " bytes." << "\r\n";
00019 
00020   user->settings(FAILURE, B_SET);
00021   return(true);
00022 }

bool Commands::rest ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 400 of file Commands2.cpp.

References Data::user.

Referenced by Handler::Handler().

00401 {
00402   char *endptr;
00403   string message;
00404 
00405   off_t fpos = strtoul(argument.c_str(), &endptr, 0);
00406   if(!*endptr)
00407   {
00408     user->rest_pos(fpos);
00409     message = "350 Restarting at " + argument + ". Send STOR or RETR.";
00410   }
00411   else
00412     message = "501 Restart point not in numeric format.";
00413 
00414   *user << message << "\r\n";
00415   return(true);
00416 }

bool Commands::retr ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 305 of file Commands2.cpp.

References BINARY, Data::Data(), DATA_OPEN, User::data_vec, User::data_vec_full(), data_wrapper(), Utilities::itos(), Connection::lock, Connection::settings(), Data::user, and util.

Referenced by Handler::Handler().

00306 {
00307   struct stat stt;
00308 
00309   string file_name = parsedir(user, argument);
00310   stat(file_name.c_str(), &stt);
00311   if(!S_ISREG(stt.st_mode))
00312   {
00313     *user << "550 \"" << argument << "\" is not a regular file.\r\n";
00314     return(false);
00315   }
00316 
00317   int file_id = open(file_name.c_str(), O_RDONLY);
00318   if(user->rest_pos() > 0)
00319   {
00320     lseek(file_id, user->rest_pos(), SEEK_SET);
00321     user->rest_pos(0);
00322   }
00323 
00324   *user << "150 Opening " << (user->settings(BINARY)?"BINARY":"ASCII")
00325       << " mode data connection for \"" << argument << "\" ("
00326       << util.itos(stt.st_size) << " bytes).\r\n";
00327 
00328   class Data *data = new Data(user, file_id, file_name, 1);
00329   if(!data->settings(DATA_OPEN) || user->data_vec_full())
00330   {
00331     *user << "425 Can't open data connection.\r\n";
00332     delete data;
00333     return(false);
00334   }
00335 
00336   BABY_WRLOCK(user->lock);
00337   user->data_vec.push_back(data);
00338   BABY_UNLOCK(user->lock);
00339   pthread_t temp_id;
00340   pthread_create(&temp_id, NULL, data_wrapper,
00341       static_cast<void*>(data));
00342   return(true);
00343 }

Here is the call graph for this function:

bool Commands::rmd ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 723 of file Commands2.cpp.

Referenced by Handler::Handler().

00724 {
00725   string message, new_dir = parsedir(user, argument);
00726 
00727   if(rmdir(new_dir.c_str()))
00728   {
00729     message = "550 ";
00730     if(errno == EACCES)
00731       message += "Write access denied.";
00732     else if(errno == (ENOTDIR || ENOENT))
00733       message += "Faulty pathname, directory not removed.";
00734     else
00735       message += "Directory not removed.";
00736   }
00737   else
00738     message = "250 \"" + argument + "\" removed.";
00739 
00740   *user << message << "\r\n";
00741   return(true);
00742 }

bool Commands::rname ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 922 of file Commands2.cpp.

References COM_FROM, COM_TO, Utilities::is_set(), and util.

Referenced by Handler::Handler().

00923 {
00924   string file_name, message;
00925 
00926   file_name = parsedir(user, argument);
00927 
00928   if(util.is_set(flag, COM_FROM))
00929   {
00930     user->temp_buf(file_name);
00931     message = "350 Command OK, waiting for RNTO.";
00932   }
00933   else if(util.is_set(flag, COM_TO))
00934   {
00935     if(user->temp_buf().size() == 0)
00936       message = "503 RNTO must come after RNFR.";
00937     else
00938     {
00939       if(!(rename(user->temp_buf().c_str(), file_name.c_str())))
00940         message = "250 " + user->temp_buf() + " renamed to " + file_name + ".";
00941       else if(errno == EACCES)
00942         message = "550 Access denied.";
00943       else
00944         message = "553 Rename failed.";
00945       user->temp_buf("");
00946     }
00947   }
00948   *user << message << "\r\n";
00949   return(true);
00950 }

Here is the call graph for this function:

bool Commands::sim1 ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 1029 of file Commands2.cpp.

References B_RESET, B_SET, BINARY, COM_CCC, COM_CONF, COM_ENC, COM_FEAT, COM_MIC, COM_MODE, COM_NOOP, COM_PBSZ, COM_PROT, COM_PWD, COM_STRU, COM_SYST, COM_TYPE, config, Configuration::general, Utilities::is_set(), general_stru::os, TLS_ENABLED, TLS_PBSZ, TLS_PROT_D, and util.

Referenced by Handler::Handler().

01030 {
01031   string message;
01032 
01033   transform(argument.begin(), argument.end(), argument.begin(),
01034       (int(*)(int))toupper);
01035 
01036   if(util.is_set(flag, COM_NOOP))
01037     message = "200 'NOOP': Command successful.";
01038 
01039   else if(util.is_set(flag, COM_PWD))
01040   {
01041     string dir = user->current_dir();
01042     if(user->root_dir().size() > 1)
01043       dir.erase(0, user->root_dir().size());
01044     if(dir == "")
01045       dir = "/";
01046     message = "257 \"" + dir + "\" is current directory.";
01047   }
01048 
01049   else if(util.is_set(flag, COM_SYST))
01050     message = "215 " + config->general.os + " Type: L8";
01051 
01052   else if(util.is_set(flag, COM_FEAT))
01053   {
01054     message =  "211-Extensions supported:\r\n";
01055     message += " SIZE\r\n";
01056     message += " MDTM\r\n";
01057     message += " MLST " + mlst_string(user) + "\r\n";
01058     message += " REST STREAM\r\n";
01059     message += " EPRT\r\n";
01060     message += " EPSV\r\n";
01061 #ifdef USE_TLS
01062     message += " AUTH TLS\r\n";
01063     message += " PBSZ\r\n";
01064     message += " PROT\r\n";
01065     message += " CCC\r\n";
01066 #endif // USE_TLS
01067     message += "211 End.";
01068   }
01069 
01070   else if(util.is_set(flag, COM_TYPE))
01071   {
01072     if(argument == "A" || argument == "A N")
01073     {
01074       message = "200 Type set to " + argument + ".";
01075       user->settings(BINARY, B_RESET);
01076     }
01077     else if(argument == "I" || argument == "L 8")
01078     {
01079       message = "200 Type set to " + argument + ".";
01080       user->settings(BINARY, B_SET);
01081     }
01082     else
01083       message = "504 'TYPE " + argument + "' not understood.";
01084   }
01085 
01086   else if(util.is_set(flag, COM_MODE))
01087   {
01088     if(argument == "S")
01089     {
01090       message = "200 Stream MODE enabled.";
01091     }
01092     else
01093       message = "504 'MODE " + argument + "' not understood.";
01094   }
01095 
01096   else if(util.is_set(flag, COM_STRU))
01097   {
01098     if(argument == "F")
01099       message = "200 Structure set to F.";
01100     else
01101       message = "504 'STRU " + argument + "' not understood.";
01102   }
01103 #ifdef USE_TLS
01104   else if(util.is_set(flag, COM_PBSZ))
01105   {
01106     if(user->settings(TLS_ENABLED))
01107     {
01108       if(argument == "0")
01109       {
01110         message = "200 PBSZ set for stream transfer.";
01111         user->settings(TLS_PBSZ, B_SET);
01112       }
01113       else
01114         message = "501 PBSZ has to be set to 0 for use with TLS.";
01115     }
01116     else
01117       message =
01118         "503 AUTH must be issued and negotiated before PBSZ can be used.";
01119   }
01120 
01121   else if(util.is_set(flag, COM_PROT))
01122   {
01123     if(!user->settings(TLS_ENABLED) || !user->settings(TLS_PBSZ))
01124       message =
01125         "503 AUTH and PBSZ has to be issued and negotiated before PROT.";
01126     else
01127       switch(argument[0])
01128       {
01129         case 'C':
01130           message = "200 Data connection set to CLEAR level.";
01131           user->settings(TLS_PROT_D, B_RESET);
01132           break;
01133         case 'P':
01134           message = "200 Data connection set to PRIVATE level.";
01135           user->settings(TLS_PROT_D, B_SET);
01136           break;
01137         case 'S':
01138         case 'E':
01139           message = "536 Only CLEAR and PRIVATE level is available with TLS.";
01140           break;
01141         default:
01142           message = "504 Protection level '" + argument + "' not understood.";
01143       }
01144   }
01145   else if(util.is_set(flag, COM_CCC)) // Clear Command Channel
01146   {
01147     if(!user->settings(TLS_ENABLED))
01148       message =
01149         "533 CCC can only be issued on a protected control connection.";
01150     else // code for disallowing CCC should be above, containing a 534
01151     {
01152       *user << "200 Disabling TLS, control connection is now CLEAR.\r\n";
01153       user->disengage_tls();
01154     }
01155   }
01156   else if(util.is_set(flag, COM_CONF | COM_MIC | COM_ENC))
01157   {
01158     // note, if we implement som other security messure than TLS we might
01159     // need these commands, for now they reside here and only return
01160     // a 503 or 537.
01161     string command;
01162     if(util.is_set(flag, COM_CONF))
01163       command = "CONF";
01164     else if(util.is_set(flag, COM_MIC))
01165       command += "MIC";
01166     else
01167       command += "ENC";
01168 
01169     if(!user->settings(TLS_ENABLED))
01170       message = "503 Command " + command
01171         + " can not be issued before a valid security exchange.";
01172     else
01173       message = "537 Command " + command + " not used in TLS mode.";
01174   }
01175 #endif // USE_TLS
01176 
01177   if(message.size() > 0)
01178     *user << message << "\r\n";
01179   return(true);
01180 }

Here is the call graph for this function:

bool Commands::sim2 ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 1182 of file Commands2.cpp.

References COM_MDTM, COM_MLST, COM_SIZE, Utilities::is_set(), Utilities::itos(), Utilities::time_string(), and util.

Referenced by Handler::Handler().

01183 {
01184   string file_name, message;
01185   struct stat stt;
01186 
01187   file_name = parsedir(user, argument);
01188   if(!(stat(file_name.c_str(), &stt)))
01189   {
01190     if(util.is_set(flag, COM_SIZE))
01191       message = "213 " + util.itos(stt.st_size);
01192 
01193     else if(util.is_set(flag, COM_MDTM))
01194       util.time_string(message, "213 %Y%m%d%H%M%S", 19, stt.st_mtime);
01195 
01196     else if(util.is_set(flag, COM_MLST))
01197     {
01198       message  = "250-Listing " + argument + "\r\n";
01199       message += mlsx(user, file_name) + "\r\n";
01200       message += "250 End.";
01201     }
01202   }
01203   else
01204     message = "550 \"" + argument + "\": No such file or directory.";
01205 
01206   *user << message << "\r\n";
01207   return(true);
01208 }

Here is the call graph for this function:

bool Commands::stor ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 345 of file Commands2.cpp.

References BINARY, COM_STOR, Data::Data(), DATA_OPEN, User::data_vec, User::data_vec_full(), data_wrapper(), Utilities::is_set(), Connection::lock, Connection::settings(), Data::user, and util.

Referenced by Handler::Handler().

00346 {
00347   int file_id;
00348 
00349   string file_name = parsedir(user, argument);
00350 
00351   if(util.is_set(flag, COM_STOR))
00352     file_id = open(file_name.c_str(), O_WRONLY|O_CREAT|O_TRUNC,
00353         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
00354   else // com_type == COM_APPE
00355     file_id = open(file_name.c_str(), O_WRONLY|O_APPEND|O_TRUNC,
00356         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
00357 
00358   if(file_id == -1)
00359   {
00360     string message;
00361     if(errno == EEXIST)
00362       message = "550 File " + file_name + " already exists.";
00363     else if(errno == EISDIR)
00364       message = "550 " + file_name + " is a directory.";
00365     else if(errno == EACCES)
00366       message = "550 Access to " + file_name + " denied.";
00367     else
00368       message = "550 File operation failed.";
00369     *user << message << "\r\n";
00370     return false;
00371   }
00372 
00373   // shouldn't try to restart an appending :p
00374   if(user->rest_pos() > 0 && util.is_set(flag, COM_STOR))
00375   {
00376     lseek(file_id, user->rest_pos(), SEEK_SET);
00377     user->rest_pos(0);
00378   }
00379 
00380   *user << "150 Opening " << (user->settings(BINARY)?"BINARY":"ASCII")
00381       << " mode data connection for \"" << argument << "\".\r\n";
00382 
00383   class Data *data = new Data(user, file_id, file_name, 0);
00384   if(!data->settings(DATA_OPEN) || user->data_vec_full())
00385   {
00386     *user << "425 Can't open data connection.\r\n";
00387     delete data;
00388     return(false);
00389   }
00390 
00391   BABY_WRLOCK(user->lock);
00392   user->data_vec.push_back(data);
00393   BABY_UNLOCK(user->lock);
00394   pthread_t temp_id;
00395   pthread_create(&temp_id, NULL, data_wrapper,
00396       static_cast<void*>(data));
00397   return(true);
00398 }

Here is the call graph for this function:

bool Commands::user ( User user,
string &  argument,
unsigned int  flag 
)

Definition at line 24 of file Commands2.cpp.

References A_ENABLE, A_ONLY, general_stru::anonymous, B_SET, config, DENY, users_stru::encryption, FAILURE, FORCE, FORCE_CERT, Configuration::general, Configuration::get_user(), LOGGED_IN, users_stru::noftp, TLS_ENABLED, users_stru::user_limit, user_list, user_list_lock, and USER_SUPPLIED.

Referenced by Handler::Handler(), mlst_string(), mlsx(), and parsedir().

00025 {
00026   string message;
00027   bool ret = true, bad = false;
00028   if(user->logged_in() == LOGGED_IN)
00029   {
00030     message = "503 You are already logged in!";
00031     ret = false;
00032   }
00033   else
00034   {
00035     int current_connections = 0;
00036     pthread_rwlock_rdlock(&user_list_lock);
00037     for(vector<User*>::iterator user_it = user_list.begin();
00038         user_it != user_list.end(); user_it++)
00039       if((*user_it)->user_name() == argument)
00040         current_connections++;
00041     pthread_rwlock_unlock(&user_list_lock);
00042 
00043     user->user_name(argument);
00044     user->logged_in(USER_SUPPLIED);
00045 
00046     if(config->get_user(argument).noftp == true)
00047     {
00048       message = "421 Sorry, you are not allowed to use ftp. disconnecting.";
00049       bad = true;
00050     }
00051     else if(current_connections >= config->get_user(argument).user_limit){
00052       message =
00053         "421 You have reached your maximum number of control connections.";
00054       bad = true;
00055     }
00056 #ifdef USE_TLS
00057     else if(config->get_user(argument).encryption == DENY &&
00058         user->settings(TLS_ENABLED))
00059     {
00060       message =  "421 Sorry, you are not allowed to connect with"
00061         "encryption enabled, disconnecting.";
00062       bad = true;
00063     }
00064     else if(user->settings(TLS_ENABLED) && user->verify_cert())
00065     {
00066       message = "230 Logged in as " + argument + ".";
00067       user->login();
00068     }
00069     else if(config->get_user(argument).encryption == FORCE_CERT)
00070     {
00071       message = "421 You must supply a valid certificate to login.";
00072       bad = true;
00073     }
00074     else if(config->get_user(argument).encryption == FORCE &&
00075         !user->settings(TLS_ENABLED))
00076     {
00077       message =
00078         "421 You must enable encryption before logging in, disconnecting.";
00079       bad = true;
00080     }
00081 #endif // USE_TLS
00082     else if(config->general.anonymous >= A_ENABLE &&
00083         user->user_name() == "anonymous")
00084       message = "331 Anonymous login. Please, provide your email as password.";
00085     else if(config->general.anonymous == A_ONLY)
00086     {
00087       message = "421 All logins except anonymous disabled, disconnecting.";
00088       bad = true;
00089     }
00090     else
00091       message = "331 Password required for " + argument + ".";
00092   }
00093   *user << message << "\r\n";
00094   if(bad)
00095   {
00096     user->settings(FAILURE, B_SET);
00097     ret = false;
00098   }
00099   return(ret);
00100 }

Here is the call graph for this function:


Member Data Documentation

Definition at line 54 of file Commands.h.

Referenced by exit_baby(), main(), pass(), and User::~User().


The documentation for this class was generated from the following files: