Documentation

Generated on Thu Aug 31 00:02:30 2006

 

User.cpp

Go to the documentation of this file.
00001 
00002 // $Id: User.cpp,v 1.98 2005/07/23 19:57:17 klas Exp $
00003 //
00004 // Usage: Holds information about connected users.
00005 //
00006 //  A part of babyftpd, licensed under the GNU GPL, see the file
00007 //    LICENSE for complete information.
00009 
00010 #define USER_CPP
00011 #define NETINCLS
00012 #define BABY_CORE
00013 #include "User.h"
00014 
00015 User::User(int socket_id, struct sockaddr_in &addr) : Connection()
00016 {
00017   this->_root_dir = "/";
00018   this->_failed_logins = 0;
00019   this->_logged_in = NOT_LOGGED_IN;
00020   this->_data_id = 0;
00021   this->_rest_pos = 0;
00022   this->addr(addr);
00023   this->socket_id(socket_id);
00024   this->thread_id(pthread_self());
00025   this->host_name(inet_ntoa(this->addr().sin_addr));
00026   struct timeval tmp = {config->general_user.idle, 0};
00027   this->timeout(tmp);
00028 
00029   // setting the bitflags on mlst_facts... not to clean..
00030   for(int i = 0; i <= LAST_FACT; i++)
00031     this->settings(i, B_SET);
00032 }
00033 
00034 User::~User()
00035 {
00036   if(this->_data_id)
00037     close(this->_data_id);
00038 
00039   if(this->settings(PAM_DONE))
00040   {
00041     sem_wait(&comm.pam_lock);
00042     pam_close_session(this->_pamh, PAM_SILENT);
00043     pam_end(this->_pamh, PAM_SUCCESS);
00044     sem_post(&comm.pam_lock);
00045   }
00046 
00047   // killing off any ongoing data threads
00048   for(vector<Data*>::iterator data_it = data_vec.begin();
00049       data_it != data_vec.end(); data_it++)
00050     if(*data_it)
00051       pthread_cancel((*data_it)->thread_id());
00052 
00053   while(data_vec.size())
00054   {  }
00055 
00056   pthread_rwlock_wrlock(&user_list_lock);
00057   user_list.erase(get_user_it(this->thread_id()));
00058   logging->log_this(4, TYPE_INFO, "user thread " +
00059       util.itos(this->thread_id()) + " exiting, connected users:" +
00060       util.itos(user_list.size()));
00061   pthread_rwlock_unlock(&user_list_lock);
00062 }
00063 
00064 vector<User*>::iterator get_user_it(pthread_t thread_id)
00065 {
00066   vector<User*>::iterator user_it;
00067 
00068   BABY_RDLOCK(user_list_lock);
00069   for(user_it = user_list.begin(); user_it != user_list.end(); user_it++)
00070     if(pthread_equal((*user_it)->thread_id(), thread_id))
00071       break;
00072   BABY_UNLOCK(user_list_lock);
00073 
00074   return(user_it);
00075 }
00076 
00077 
00078 vector<Data*>::iterator User::get_data_it(pthread_t thread_id)
00079 {
00080   vector<Data*>::iterator data_it;
00081 
00082   BABY_RDLOCK(this->lock);
00083   for(data_it = this->data_vec.begin(); data_it != this->data_vec.end();
00084       data_it++)
00085     if(pthread_equal((*data_it)->thread_id(), thread_id))
00086       break;
00087   BABY_UNLOCK(this->lock);
00088 
00089   return(data_it);
00090 }
00091 
00092 bool User::data_vec_full()
00093 {
00094   if(data_vec.size() >=
00095       static_cast<size_t>(config->get_user(this->user_name()).sim_data))
00096     return(true);
00097   return(false);
00098 }
00099 
00100 bool User::login(void)
00101 {
00102   char pwdata[PWBUF_SIZE];
00103   struct passwd pwd, *pwd_ptr;
00104   this->logged_in(LOGGED_IN);
00105   getpwnam_r(this->user_name().c_str(), &pwd, pwdata, sizeof(pwdata),
00106       &pwd_ptr);
00107   uid_t uid = pwd.pw_uid;
00108   gid_t gid = pwd.pw_gid;
00109   if(config->get_user(this->user_name()).only_home)
00110     this->root_dir(pwd.pw_dir);
00111   this->current_dir(pwd.pw_dir);
00112   seteuid(0);
00113   setgid(gid);
00114   seteuid(uid); // dropping permissions...
00115   struct timeval tmp = {config->get_user(this->user_name()).idle, 0};
00116   this->timeout(tmp);
00117   return true;
00118 }
00119 
00120 User &User::operator>>(string &message)
00121 {
00122   char tmp_buf[210] = { 0 };
00123   fd_set rfd;
00124   FD_ZERO(&rfd);
00125   FD_SET(this->socket_id(), &rfd);
00126   timeval tv = this->timeout();
00127 
00128   if(!select(this->socket_id() + 1, &rfd, NULL, NULL, &tv))
00129   {
00130     *this << "421 Connection timed out("
00131       << util.itos(config->get_user(this->user_name()).idle)
00132       << " seconds). Disconnected.";
00133     if(this->logged_in())
00134       logging->log_this(3, TYPE_AUTH, "User " + this->user_name() +
00135           ", disconnected due to timeout.");
00136 
00137     this->settings(FAILURE, B_SET);
00138   }
00139   else
00140   {
00141     if(this->receive(tmp_buf, 200) > 0)
00142       message = tmp_buf;
00143     else
00144       this->settings(FAILURE, B_SET);
00145   }
00146   return *this;
00147 }
00148 
00149 void kill_user(void *user)
00150 {
00151   delete static_cast<User*>(user);
00152 }