Documentation

Generated on Thu Aug 31 00:02:31 2006

 

Commands.cpp File Reference

#include "Commands.h"

Include dependency graph for Commands.cpp:

Go to the source code of this file.


Defines

#define COMMANDS_CPP
#define NETINCLS
#define BABY_CORE

Functions

void * data_wrapper (void *void_data)
int pam_conversate (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)

Variables

Commands comm

Define Documentation

#define BABY_CORE

Definition at line 12 of file Commands.cpp.

#define COMMANDS_CPP

Definition at line 10 of file Commands.cpp.

#define NETINCLS

Definition at line 11 of file Commands.cpp.


Function Documentation

void* data_wrapper ( void *  void_data  ) 

Definition at line 17 of file Commands.cpp.

References Connection::addr(), ANONYMOUS, BINARY, config, Connection::engage_tls(), Connection::host_name(), Utilities::itos(), Log::log_this(), Configuration::logger, logging, my_data, Connection::packet_size(), PWBUF_SIZE, Connection::receive(), RETR_TRANS, Connection::send(), Connection::settings(), Connection::thread_id(), Utilities::time_string(), TLS_PROT_D, TYPE_DEBUG, TYPE_XFER, Data::user, Connection::user_name(), util, and log_stru::xferlog.

Referenced by Commands::retr(), and Commands::stor().

00018 {
00019   class Data *data = static_cast<class Data*>(void_data);
00020   string message;
00021   time_t start_time = time(NULL);
00022   size_t trans_size = 0; // will hold the total number of sent bytes
00023 
00024   data->thread_id(pthread_self());
00025 
00026   pthread_setspecific(my_data, void_data);
00027   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00028 
00029   data->host_name(inet_ntoa(data->addr().sin_addr));
00030 
00031   // I don't like it, but we need to drop permissions again...
00032   //   not true for new threads, need to look deeper into this.
00033   struct passwd pwd, *pwd_ptr;
00034   char pwdata[PWBUF_SIZE];
00035   getpwnam_r(data->user->user_name().c_str(), &pwd, pwdata, sizeof(pwdata),
00036       &pwd_ptr);
00037   uid_t uid = pwd.pw_uid;
00038   gid_t gid = pwd.pw_gid;
00039   setuid(uid);
00040   setgid(gid);
00041 
00042 #ifdef USE_TLS // handshakes etc
00043   if(data->settings(TLS_PROT_D))
00044     if(!data->engage_tls()) // failed handshake
00045       message =
00046         "451 Failed to negotiate TLS as was asked. Closing data connection.";
00047 #endif // USE_TLS
00048   while(message.empty())
00049   {
00050     char *read_buf = new char[data->packet_size()];
00051     size_t size = 0, size2 = 0;
00052     if(data->settings(RETR_TRANS))
00053     {
00054       size2 = read(data->file_id(), read_buf, data->packet_size());
00055       if(size2 > 0)
00056         size = data->send(read_buf, size2);
00057     }
00058     else // STOR_STRANS
00059       size = data->receive(read_buf, data->packet_size() - 1);
00060 
00061     trans_size += size;
00062     if(!data->settings(RETR_TRANS))
00063     {
00064       if(size != 0 && (write(data->file_id(), read_buf, size) == -1))
00065       {
00066         logging->log_this(3, TYPE_DEBUG, "Write failed to file: " +
00067             data->file_name() + " from host: " + data->host_name() +
00068             " with error %m");
00069         message = "451 File transfer failed.";
00070       }
00071       else if(size == 0)
00072       {
00073         if(close(data->file_id()) != 0)
00074           message = "550 Failed saving file.";
00075         else
00076           message = "226 Transfer complete.";
00077       }
00078     }
00079     else // RETR_TRANS
00080     {
00081       if(size != size2)
00082         message = "550 Transfer failed.";
00083       else if(size2 != data->packet_size())
00084         message = "226 Transfer complete.";
00085     }
00086     delete[] read_buf;
00087   }
00088 
00089   *data->user << message << "\r\n";
00090   if(config->logger.xferlog)
00091   {
00092     string time_string;
00093     util.time_string(time_string, "%a %b %d %H:%M:%S %Y ");
00094 
00095     // as ' ' separates fields in the xferlog we convert them to '_' here
00096     string temp_name = data->file_name();
00097     for(string::iterator name_it = temp_name.begin();
00098         name_it != temp_name.end(); name_it++)
00099       if(isspace(*name_it))
00100         *name_it = '_';
00101 
00102     // let us build a string!
00103     string xferlog = time_string;
00104     xferlog += util.itos(time(NULL) - start_time);
00105     xferlog += " " + data->host_name();
00106     xferlog += " " + util.itos(trans_size);
00107     xferlog += " " + temp_name + " ";
00108     xferlog += (data->settings(BINARY)?"b":"a");
00109     xferlog += " _ "; // we don't support any special-action to flag here.
00110     xferlog += (data->settings(RETR_TRANS)?"o":"i");
00111     xferlog += (data->user->settings(ANONYMOUS)? // a for anonymous, r for real
00112         " a " + data->user->anonymous_id(): // if the user is anonymous we log
00113         " r " + data->user->user_name()); // the id string, else the user name.
00114     xferlog += " FTP"; // maybe ftps for encrypted? no. IANA.
00115     xferlog += " 0"; // there should be more auth methods available here?
00116     xferlog += " *"; // or should this be uid?
00117 
00118     logging->log_this(1, TYPE_XFER, xferlog);
00119   }
00120 
00121   pthread_exit(NULL);
00122 }

Here is the call graph for this function:

int pam_conversate ( int  num_msg,
const struct pam_message **  msg,
struct pam_response **  resp,
void *  appdata_ptr 
)

Definition at line 171 of file Commands.cpp.

References pam_data::password, and pam_data::user_name.

Referenced by Commands::pass().

00173 {
00174   struct pam_response *reply = NULL;
00175   int count = 0;
00176   struct pam_data *auth_data = (static_cast<struct pam_data*>(appdata_ptr));
00177 
00178   for(int i = 0; i < num_msg; i++)
00179   {
00180     struct pam_response *reply_tmp;
00181     switch(msg[i]->msg_style)
00182     {
00183       case PAM_PROMPT_ECHO_ON:
00184       case PAM_PROMPT_ECHO_OFF:
00185         reply_tmp = (static_cast<struct pam_response*>
00186             (malloc(sizeof(struct pam_response) * (count + 1))));
00187         memcpy(reply_tmp, reply, count);
00188         if(reply)
00189           free(reply);
00190         reply = reply_tmp;
00191 
00192         // is this really how it should be done?
00193         if(msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
00194           reply[i].resp = strndup(auth_data->user_name.c_str(),
00195               auth_data->user_name.size());
00196         else
00197           reply[i].resp = strndup(auth_data->password.c_str(),
00198               auth_data->password.size());
00199 
00200         reply[count++].resp_retcode = PAM_SUCCESS;
00201         break;
00202 
00203       case PAM_TEXT_INFO:
00204         break;
00205 
00206       case PAM_ERROR_MSG:
00207       default:
00208         if(reply)
00209           free(reply);
00210         return PAM_CONV_ERR;
00211     }
00212   }
00213   *resp = reply;
00214   return PAM_SUCCESS;
00215 }


Variable Documentation

class Commands comm

Definition at line 15 of file Commands.cpp.

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