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;
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
00030 act.sa_handler=signal_handling;
00031 sigemptyset(&act.sa_mask);
00032 act.sa_flags=0;
00033
00034
00035 for(;sinais[z] != -1; z++)
00036 sigaction(sinais[z],&act,&oldact);
00037
00038
00039 sessions = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_session);
00040
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
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
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
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
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
00095 contas = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_conta);
00096 maquinas = tabela_criar(HASHBASE, (LIBERTAR_FUNC)free_maquina);
00097
00098
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
00114 fclose(f_contas);
00115 fclose(f_maquinas);
00116 free(c_file);
00117 free(m_file);
00118
00119
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
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
00132 pthread_cond_signal(&cond);
00133 pthread_join(tid, NULL);
00134
00135
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
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
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
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
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
00250 alarm(0);
00251
00252
00253
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
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
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
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
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
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
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
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 }