securitas.c

Ir para a documentação deste ficheiro.
00001 
00011 #include "securitas.h"
00012 
00013 int global_status = OK_STATUS;
00014 
00015 int main(int argc, char* argv[])
00016   {
00017   HASHTABLE_T *sessions = NULL, *contas = NULL, *maquinas = NULL;
00018   FILE *f_contas = NULL, *f_maquinas = NULL;
00019   char *c_file = NULL, *m_file = NULL;   /* -1 indica fim de vector de sinais */
00020   int session_len = 0, porto = 0, sinais[] = {SIGINT, SIGALRM, SIGPIPE,-1}, z=0;
00021   t_args_processor *args_processor;
00022   t_args_monitor *args_thread;
00023   pthread_mutex_t mutex;
00024   pthread_cond_t cond;
00025   pthread_t tid;
00026   
00027   t_sigaction act,oldact;
00028   
00029   /* Iniciar e registar sinais */
00030   act.sa_handler=signal_handling;
00031   sigemptyset(&act.sa_mask);
00032   act.sa_flags=0;
00033   
00034                 /* sinais++ */
00035   for(;sinais[z] != -1; z++)
00036     sigaction(sinais[z],&act,&oldact);
00037     
00038   /* Iniciar variaveis */  
00039   sessions = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_session);
00040   /* Iniciar mutex e condicao*/
00041   if(pthread_mutex_init(&mutex, NULL) != 0)
00042     {
00043     tabela_destruir(&sessions);
00044     print_error_exit("Impossivel iniciar estruturas de controlo de thread.", "Impossivel iniciar o mutex.", ERROR_VAL);
00045     }
00046     
00047   if(pthread_cond_init(&cond, NULL) != 0)
00048     {
00049     pthread_mutex_destroy(&mutex);
00050     tabela_destruir(&sessions);
00051     print_error_exit("Impossivel iniciar estruturas de controlo de thread.", "Impossivel iniciar a condicao.", ERROR_VAL);
00052     }
00053      
00054   /* Efectuar parsing dos parametros de entrada */
00055   if(parse_args(argc, argv, &c_file, &m_file, &porto, &session_len) != ALL_GOES_WELL)
00056     {
00057     destroy_3_resources(&cond, &mutex, &sessions);
00058     print_error_exit("Argumentos invalidos.", "Erro na chamada ao cmdline_parser.", ERROR_VAL);
00059     }
00060     
00061   /* Validar o porto passado */
00062   if(porto < 0)
00063     {
00064     destroy_3_resources(&cond, &mutex, &sessions);
00065         print_error_exit("O porto especificado nao se encontra dentro dos limites.\nIndique valores superiores a 0 (zero)", "Passado ao Securitas um porto inferiror a 0", ERROR_VAL);
00066     }
00067     
00068   /* Validar caminhos passados por parametro */
00069   if(validate_path(c_file) != 0)
00070     {
00071    destroy_3_resources(&cond, &mutex, &sessions);
00072     print_error_exit("Caminho para ficheiro de contas invalido.", "Caminho para contas invalido.", ERROR_VAL);
00073     }
00074     
00075   if(validate_path(m_file) != 0)
00076     {
00077     destroy_3_resources(&cond, &mutex, &sessions);
00078     print_error_exit("Caminho para ficheiro de maquinas invalido.", "Caminho para maquinas invalido.", ERROR_VAL);
00079     }
00080   
00081   /* Abrir ficheiros */
00082   if(!(f_contas = fopen(c_file, "r")))
00083     {
00084     destroy_3_resources(&cond, &mutex, &sessions);
00085     print_error_exit("Erro ao abrir o ficheiro de contas", "fopen() falhou no ficheiro de contas.", ERROR_VAL);
00086     }
00087     
00088   if(!(f_maquinas = fopen(m_file, "r")))
00089     {
00090     destroy_3_resources(&cond, &mutex, &sessions);
00091     print_error_exit("Erro ao abrir o ficheiro de maquinas", "fopen() falhou no ficheiro de maquinas.", ERROR_VAL);
00092     }
00093     
00094   /* Criar hastables *//*This code is not to be 'speed user friendly' */
00095   contas = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_conta);
00096   maquinas = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_maquina);
00097   
00098   /* Efectuar parsing de ficheiros de configuracao */
00099   if(parse_contas(f_contas, contas) == ERROR_VAL)
00100     {
00101     destroy_5_resources(&cond, &mutex, &contas, &maquinas, &sessions);
00102     print_error_exit("Formato do ficheiro de contas invalido ou a funcao foi interrompida pelo sistema.",
00103       "O formato do ficheiro de contas nao esta correcto ou a funcao getline() falhou.", ERROR_VAL);
00104     }
00105     
00106   if(parse_maquinas(f_maquinas, maquinas) == ERROR_VAL)
00107     {
00108     destroy_5_resources(&cond, &mutex, &contas, &maquinas, &sessions);
00109     print_error_exit("Formato do ficheiro de maquinas invalido  ou a funcao foi interrompida pelo sistema.",
00110       "O formato do ficheiro de maquinas nao esta correcto ou a funcao getline() falhou.", ERROR_VAL);
00111     }
00112   
00113   /* Libertar os recursos que ja nao sao necessarios */
00114   fclose(f_contas);
00115   fclose(f_maquinas);
00116   free(c_file);
00117   free(m_file);
00118   
00119   /* Criar thread de monitorizacao */
00120   args_thread = create_args_monitor(sessions, session_len, &mutex, &cond);
00121   if(pthread_create(&tid, NULL, monitor_thread, args_thread) != 0)
00122     {
00123     destroy_final_resources(&cond, &mutex, &contas, &maquinas, &sessions, args_processor, args_thread);
00124     print_error_exit("Erro ao criar o sistema de monitorizacao.", "Impossivel criar a thread.", ERROR_VAL);
00125     }
00126 
00127   /* Iniciar o socket de comunicacao no porto especificado */
00128   args_processor = create_args_processor(sessions, contas, maquinas, session_len, &mutex);
00129   open_socket((uint16_t)porto, proc_pedido, args_processor, &global_status);
00130   
00131   /* Desbloquear a thread e esperar que ela termine para poder libertar os recursos */
00132   pthread_cond_signal(&cond);
00133   pthread_join(tid, NULL);
00134   
00135   /* Libertar recursos e sair */
00136   destroy_final_resources(&cond, &mutex, &contas, &maquinas, &sessions, args_processor, args_thread);
00137   printf("Securitas a terminar. Tenha um bom dia.");
00138   
00139   #ifdef SHOW_DEBUG
00140     DEBUG("Sair do main do Securitas");
00141   #endif
00142   return 0;
00143   }
00144   
00145 void signal_handling(int sig)
00146   {
00147   switch(sig)
00148     {
00149     case SIGINT:
00150       global_status = EXIT_STATUS;
00151       break;
00152     case SIGALRM:
00153       #ifdef SHOW_DEBUG
00154         DEBUG("Recebido o sinal SIGALRM");
00155       #endif
00156       break;
00157     case SIGPIPE:
00158       #ifdef SHOW_DEBUG
00159         DEBUG("Recebido o sinal SIGPIPE");
00160       #endif
00161       break;
00162     }
00163   }
00164 
00165 void *monitor_thread(void *args)
00166   {
00167   t_args_monitor *info = (t_args_monitor *)args;
00168   ITERADOR_T *it = NULL;
00169   LISTA_GENERICA_T *lista_elem = NULL;
00170   t_timespec time_speck;
00171   time_t tick;
00172   sigset_t set, oset;
00173   int cond_error = 0;
00174   
00175   time_speck.tv_nsec = 0;
00176   /* Bloquer a recepcao de sinais */
00177   sigemptyset(&set);
00178   sigemptyset(&oset);
00179   
00180   sigaddset(&set, SIGINT);
00181   sigaddset(&set, SIGALRM);
00182   sigaddset(&set, SIGPIPE);
00183   
00184   pthread_sigmask(SIG_BLOCK, &set, &oset);
00185   
00186   while(global_status)
00187     {
00188     /* Tendo em conta que o parametro 'tempo' se encontra em minutos */
00189     time(&tick);
00190     time_speck.tv_sec = tick + info->session_len * 60;
00191     pthread_mutex_lock(info->mutex);
00192     cond_error = pthread_cond_timedwait(info->cond, info->mutex, &time_speck);
00193     pthread_mutex_unlock(info->mutex);
00194     if(cond_error != ETIMEDOUT)
00195       continue;
00196 
00197     #ifdef SHOW_DEBUG
00198       DEBUG("Thread a acordar.");
00199     #endif
00200 
00201     pthread_mutex_lock(info->mutex);
00202     if(tabela_numero_elementos(info->sessions) != 0)
00203       {
00204       lista_elem = tabela_criar_lista_elementos(info->sessions);
00205       it = lista_criar_iterador(lista_elem);
00206       while(iterador_proximo_elemento(it))      
00207         if((time_speck.tv_sec - ((t_session *)it->actual->elem)->working_time) > info->session_len * 60)
00208           {
00209           #ifdef SHOW_DEBUG
00210           DEBUG("A remover a sessao: ^%s^", ((t_session *)it->actual->elem)->sessionid);
00211           #endif
00212           
00213           tabela_remover(info->sessions, ((t_session *)it->actual->elem)->sessionid);
00214           }
00215       }
00216     pthread_mutex_unlock(info->mutex);
00217     }
00218   pthread_exit(NULL);
00219   return NULL;
00220   }
00221  
00222 int proc_pedido(int fd, void *args, char *ip_cliente)
00223   {
00224   int state = 0, folder_count = 0;
00225   char mesg[MAX_MESSAGE_LEN + 1] = {'\0'}, *pasta = NULL, line[MAX_MESSAGE_LEN + 1] = {'\0'} , lixo[MAX_MESSAGE_LEN + 1] = {'\0'}, user_login[MAX_LOGIN_LEN + 1] = {'\0'}, 
00226     user_pass[MAX_PASS_LEN + 1] = {'\0'}, sessionid[MAX_SESSINON_ID + 1]= {'\0'};
00227   t_conta *user = NULL;
00228   t_session *session = NULL;
00229   t_maquina *maquina = NULL;
00230   ITERADOR_T *it = NULL;
00231   t_args_processor *info = (t_args_processor *)args;
00232   time_t acesso_actual;
00233   memset(line, 0, MAX_MESSAGE_LEN + 1);
00234   
00235   /* Cumprimentar o cliente */
00236   sprintf(mesg, "Bem vido ao Securitas. Ligacao OK\r\n");
00237   if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00238     return ERROR_VAL;
00239   do
00240     {
00241     /* Antes de activar o alarme garantir que a variavel de teste tem o valor correcto *//*One bit towards PARANOIA*/
00242     alarm(TIMEOUT);
00243     if(readline(fd, line, MAX_MESSAGE_LEN) <= 0)
00244       {
00245       DEBUG("Erro ao tentar ler informacaoes do socket. 'readline' falhou.");
00246       close(fd);
00247       return ERROR_VAL;
00248       }
00249     /* Desativar o alarme uma vez que ja foi efectuada uma leitura */
00250     alarm(0);
00251     /* O servidor nao admite mensagens de pedidos que nao sejam terminadas com CRLF 
00252      * no entanto admite um numero de CRLF indefenidos e, caso o cliente nao respeite o protocolo, 
00253      * lixo depois da mensagem correcta desde que exista um CRLF a separar os campos */
00254     trim_crlf(line);
00255     
00256     #ifdef SHOW_DEBUG
00257       DEBUG("A entrar no estado: %d", state);
00258     #endif
00259     
00260     switch(state)
00261       { 
00262       /* Espera por instrucao inicial, AUTENTICACAO, AUTORIZACAO ou LOGOUT */
00263       case LISTENING:
00264         if(strcmp(line, "AUTENTICACAO") == 0)
00265           state = LOGIN;
00266         else
00267           if(strcmp(line, "AUTORIZACAO") == 0)
00268             state = AUTORIZACAO;
00269           else
00270             if(strcmp(line, "LOGOUT") == 0)
00271               state = LOGOUT;
00272             else
00273               state = EXIT;
00274         break;
00275       /* Espera por LOGIN */
00276       case LOGIN:
00277         #ifdef SHOW_DEBUG
00278           DEBUG("A receber login, lido: ^%s^", line);
00279         #endif
00280       
00281         if(strncmp(line, "LOGIN|", 6) == 0)
00282           {
00283           sscanf(line, "%[^|]|%s", lixo, user_login);
00284           state = PASSWORD;
00285           }
00286         else
00287           state = EXIT;
00288         break;
00289       /* Espera por PASS */
00290       case PASSWORD:
00291         #ifdef SHOW_DEBUG
00292           DEBUG("A receber password, lido: %s", line);
00293         #endif
00294         
00295         if(strncmp(line, "PASW|", 5) == 0)
00296           {
00297           sscanf(line, "%[^|]|%s", lixo, user_pass);
00298           if((user = tabela_consultar(info->hash_contas, user_login)) && (strcmp(user_pass, user->password) == 0))
00299             {
00300             session = create_session(user_login);
00301             pthread_mutex_lock(info->mutex);
00302             tabela_inserir(info->hash_sessions, session->sessionid, session);
00303             pthread_mutex_unlock(info->mutex);
00304             sprintf(mesg, "SESSIONID|%s\r\n", session->sessionid);
00305             if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00306               return ERROR_VAL;
00307             }
00308           else
00309             {
00310             sprintf(mesg, "%s\r\n","LOGIN_FAILED");
00311             if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00312               return ERROR_VAL;
00313             }
00314           }
00315         state = EXIT;
00316         break;
00317       /* AUTORIZACAO */
00318       case AUTORIZACAO:
00319         if(strncmp(line, "SESSIONID|", 10) == 0)
00320           {
00321           #ifdef SHOW_DEBUG
00322             DEBUG("A efectuar a autorizacao.");
00323           #endif
00324           
00325           sscanf(line, "%[^|]|%s", lixo, sessionid);
00326           maquina = tabela_consultar(info->hash_maquinas, ip_cliente);   
00327           if(maquina)
00328             {
00329             pthread_mutex_lock(info->mutex);
00330             session = tabela_consultar(info->hash_sessions, sessionid);               
00331             if(session)
00332               {
00333               time(&acesso_actual);
00334               if((acesso_actual - session->working_time) < info->session_len * 60)
00335                 {
00336                 session->working_time = acesso_actual;
00337                 if(tabela_consultar(maquina->logins, session->login))
00338                   {
00339                   pthread_mutex_unlock(info->mutex);    
00340                   sprintf(mesg, "FOLDERS|%d\r\n", maquina->pastas->numero_elementos);
00341                   if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00342                     return ERROR_VAL;
00343                   it = lista_criar_iterador(maquina->pastas);
00344                   while((pasta = iterador_proximo_elemento(it)))
00345                     {
00346                     sprintf(mesg, "F%d|%s\r\n", ++folder_count, pasta);
00347                     if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00348                       {
00349                       iterador_destruir(&it);
00350                       return ERROR_VAL;
00351                       }
00352                     }
00353                   iterador_destruir(&it);
00354                   sprintf(mesg, "%s\r\n","END_FOLDERS");
00355                   if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00356                     return ERROR_VAL;
00357                   }
00358                 else
00359                   {
00360                   pthread_mutex_unlock(info->mutex);
00361                   sprintf(mesg, "%s\r\n", "ACCESS_DENIED");
00362                   if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00363                     return ERROR_VAL;
00364                   }
00365                 }
00366               else
00367                 {
00368                 pthread_mutex_unlock(info->mutex);
00369                 sprintf(mesg, "%s\r\n", "SESSION_EXPIRED");
00370                 if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00371                   return ERROR_VAL;
00372                 }
00373               }
00374             else
00375               {
00376               pthread_mutex_unlock(info->mutex);
00377               sprintf(mesg, "%s\r\n", "SESSION_EXPIRED");
00378               if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00379                 return ERROR_VAL;
00380               }
00381             }
00382           else
00383             {
00384             sprintf(mesg, "%s\r\n", "ACCESS_DENIED");
00385             if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00386               return ERROR_VAL;
00387             }
00388           }
00389         state = EXIT;
00390         break;
00391       /*ANULACAO*/
00392       case LOGOUT:
00393         if(strncmp(line, "SESSID|", 7) == 0)
00394           {
00395           #ifdef SHOW_DEBUG
00396             DEBUG("A efectuar o logout.");
00397           #endif
00398           
00399           sscanf(line, "%[^|]|%s", lixo, sessionid);
00400           if((session = tabela_consultar(info->hash_sessions, sessionid)))
00401             {
00402             pthread_mutex_lock(info->mutex);
00403             tabela_remover(info->hash_sessions, sessionid);
00404             pthread_mutex_unlock(info->mutex);
00405             sprintf(mesg, "%s\r\n", "SUCCESS");
00406             if(write_to_socket(fd, mesg, "Erro de escrita para o cliente.") != ALL_GOES_WELL)
00407               return ERROR_VAL;
00408             }
00409           else
00410             {
00411             sprintf(mesg, "%s\r\n", "LOGOUT_FAILED");
00412             if(write_to_socket(fd, mesg, "Erro de escrita para o cliente. Cliente teminado.") != ALL_GOES_WELL)
00413               return ERROR_VAL;
00414             
00415             #ifdef SHOW_DEBUG
00416               DEBUG("Pedido para fecho de uma sessao inexistente.");
00417             #endif
00418             }
00419           }
00420         state = EXIT;
00421         break;    
00422       default:
00423         /* Fechar ligacao ao cliente. *//*ESTAMOS A SER HACKADOS!*/
00424         DEBUG("Atingido estado de escuta indefinido.");
00425         state = EXIT;
00426       }
00427     }
00428   while(state != EXIT);
00429   close(fd);
00430   free(ip_cliente);
00431   return 0;
00432   }
00433 
00434 /* As funcoes seguintes permitem libertar os recursos reservados ate determinada altura da vida do servidor */
00435 void destroy_5_resources(pthread_cond_t *condicao, pthread_mutex_t *mutex, HASHTABLE_T **contas, HASHTABLE_T **maquinas, HASHTABLE_T **sessions)
00436   {
00437   pthread_mutex_destroy(mutex);
00438   pthread_cond_destroy(condicao);
00439   tabela_destruir(contas);
00440   tabela_destruir(maquinas);
00441   tabela_destruir(sessions);
00442   }
00443 
00444 void destroy_3_resources(pthread_cond_t *condicao, pthread_mutex_t *mutex, HASHTABLE_T **sessions)
00445   {
00446   pthread_mutex_destroy(mutex);
00447   pthread_cond_destroy(condicao);
00448   tabela_destruir(sessions);
00449   }
00450 
00451 void destroy_final_resources(pthread_cond_t *condicao, pthread_mutex_t *mutex, HASHTABLE_T **contas, HASHTABLE_T **maquinas, HASHTABLE_T **sessions, t_args_processor *args_processor, t_args_monitor *args_thread)
00452   {
00453   pthread_mutex_destroy(mutex);
00454   pthread_cond_destroy(condicao);
00455   tabela_destruir(contas);
00456   tabela_destruir(maquinas);
00457   tabela_destruir(sessions);
00458   free_args_processor(args_processor);
00459   free_args_monitor(args_thread);
00460   }

Gerado em Fri Nov 25 18:42:04 2005 para Securitas por  doxygen 1.4.4