int lmtp_handle_connection(client_sock *c) { ClientSession_T *session = client_session_new(c); client_session_set_timeout(session, server_conf->login_timeout); reset_callbacks(session); send_greeting(session); return 0; }
int tims_handle_connection(client_sock *c) { ClientSession_T *session = client_session_new(c); session->state = CLIENTSTATE_NON_AUTHENTICATED; client_session_set_timeout(session, server_conf->login_timeout); send_greeting(session); reset_callbacks(session); return 0; }
int pop3_handle_connection(client_sock *c) { ClientSession_t *session = client_session_new(c); session->state = CLIENTSTATE_INITIAL_CONNECT; client_session_set_timeout(session, server_conf->login_timeout); reset_callbacks(session); send_greeting(session); return 0; }
int tims(ClientSession_t *session) { /* returns values: * 0 to quit * -1 on failure * 1 on success */ char *arg; size_t scriptlen = 0; int ret; char *script = NULL, *scriptname = NULL; sort_result_t *sort_result = NULL; clientbase_t *ci = session->ci; TRACE(TRACE_DEBUG,"[%p] [%d][%s]", session, session->command_type, commands[session->command_type]); switch (session->command_type) { case TIMS_LOUT: ci_write(ci, "OK \"Bye.\"\r\n"); session->state = QUIT; return 1; case TIMS_STLS: ci_write(ci, "NO\r\n"); return 1; case TIMS_CAPA: send_greeting(session); return 1; case TIMS_AUTH: /* We currently only support plain authentication, * which means that the command we accept will look * like this: Authenticate "PLAIN" "base64-password" * */ session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; arg = (char *)session->args->data; if (strcasecmp(arg, "PLAIN") == 0) { int i = 0; u64_t useridnr; if (! g_list_next(session->args)) return tims_error(session, "NO \"Missing argument.\"\r\n"); session->args = g_list_next(session->args); arg = (char *)session->args->data; char **tmp64 = NULL; tmp64 = base64_decodev(arg); if (tmp64 == NULL) return tims_error(session, "NO \"SASL decode error.\"\r\n"); for (i = 0; tmp64[i] != NULL; i++) ; if (i < 3) tims_error(session, "NO \"Too few encoded SASL arguments.\"\r\n"); /* The protocol specifies that the base64 encoding * be made up of three parts: proxy, username, password * Between them are NULLs, which are conveniently encoded * by the base64 process... */ if (auth_validate(ci, tmp64[1], tmp64[2], &useridnr) == 1) { ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ACT); ci_write(ci, "OK\r\n"); session->state = AUTH; session->useridnr = useridnr; session->username = g_strdup(tmp64[1]); session->password = g_strdup(tmp64[2]); client_session_set_timeout(session, server_conf->timeout); } else { ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ERR); g_strfreev(tmp64); return tims_error(session, "NO \"Username or password incorrect.\"\r\n"); } g_strfreev(tmp64); } else return tims_error(session, "NO \"Authentication scheme not supported.\"\r\n"); return 1; case TIMS_PUTS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; session->args = g_list_next(session->args); assert(session->args); script = (char *)session->args->data; scriptlen = strlen(script); TRACE(TRACE_INFO, "Client sending script of length [%ld]", scriptlen); if (scriptlen >= UINT_MAX) return tims_error(session, "NO \"Invalid script length.\"\r\n"); if (dm_sievescript_quota_check(session->useridnr, scriptlen)) return tims_error(session, "NO \"Script exceeds available space.\"\r\n"); /* Store the script temporarily, * validate it, then rename it. */ if (dm_sievescript_add(session->useridnr, "@!temp-script!@", script)) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Error inserting script.\"\r\n"); } sort_result = sort_validate(session->useridnr, "@!temp-script!@"); if (sort_result == NULL) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Error inserting script.\"\r\n"); } else if (sort_get_error(sort_result) > 0) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Script error: %s.\"\r\n", sort_get_errormsg(sort_result)); } /* According to the draft RFC, a script with the same * name as an existing script should [atomically] replace it. */ if (dm_sievescript_rename(session->useridnr, "@!temp-script!@", scriptname)) return tims_error(session, "NO \"Error inserting script.\"\r\n"); ci_write(ci, "OK \"Script successfully received.\"\r\n"); break; case TIMS_SETS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } scriptname = NULL; session->args = g_list_first(session->args); if ((session->args && session->args->data)) scriptname = (char *)session->args->data; if (strlen(scriptname)) { if (! dm_sievescript_activate(session->useridnr, scriptname)) ci_write(ci, "NO \"Error activating script.\"\r\n"); else ci_write(ci, "OK \"Script activated.\"\r\n"); } else { ret = dm_sievescript_get(session->useridnr, &scriptname); if (scriptname == NULL) { ci_write(ci, "OK \"No scripts are active at this time.\"\r\n"); } else { if (! dm_sievescript_deactivate(session->useridnr, scriptname)) ci_write(ci, "NO \"Error deactivating script.\"\r\n"); else ci_write(ci, "OK \"All scripts deactivated.\"\r\n"); g_free(scriptname); } } return 1; case TIMS_GETS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; if (! strlen(scriptname)) return tims_error(session, "NO \"Script name required.\"\r\n"); ret = dm_sievescript_getbyname(session->useridnr, scriptname, &script); if (script == NULL) { return tims_error(session, "NO \"Script not found.\"\r\n"); } else if (ret < 0) { g_free(script); return tims_error(session, "NO \"Internal error.\"\r\n"); } else { ci_write(ci, "{%u+}\r\n", (unsigned int)strlen(script)); ci_write(ci, "%s\r\n", script); ci_write(ci, "OK\r\n"); g_free(script); } return 1; case TIMS_DELS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; if (! strlen(scriptname)) return tims_error(session, "NO \"Script name required.\"\r\n"); if (! dm_sievescript_delete(session->useridnr, scriptname)) return tims_error(session, "NO \"Error deleting script.\"\r\n"); else ci_write(ci, "OK \"Script deleted.\"\r\n", scriptname); return 1; case TIMS_SPAC: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } // Command is in format: HAVESPACE "scriptname" 12345 // TODO: this is a fake if (dm_sievescript_quota_check(session->useridnr, 12345) == DM_SUCCESS) ci_write(ci, "OK (QUOTA)\r\n"); else ci_write(ci, "NO (QUOTA) \"Quota exceeded\"\r\n"); return 1; case TIMS_LIST: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } GList *scriptlist = NULL; if (dm_sievescript_list (session->useridnr, &scriptlist) < 0) { ci_write(ci, "NO \"Internal error.\"\r\n"); } else { if (g_list_length(scriptlist) == 0) { /* The command hasn't failed, but there aren't any scripts */ ci_write(ci, "OK \"No scripts found.\"\r\n"); } else { scriptlist = g_list_first(scriptlist); while (scriptlist) { sievescript_info_t *info = (sievescript_info_t *) scriptlist->data; ci_write(ci, "\"%s\"%s\r\n", info->name, (info-> active == 1 ? " ACTIVE" : "")); if (! g_list_next(scriptlist)) break; scriptlist = g_list_next(scriptlist); } ci_write(ci, "OK\r\n"); } g_list_destroy(scriptlist); } return 1; default: return tims_error(session, "NO \"What are you trying to say here?\"\r\n"); } if (sort_result) sort_free_result(sort_result); return 1; }
/* * Communicates with the given client socket. */ static void communicate(socket_t socket) { char* cmd = NULL; char* new_cmd; int cmd_len = 0; int tries = 0; int max_smtp_command_length; delivery_status_t delst; int looping = 1; /* initialize the delivery status structure even if this will be done later * again when the MAIL command is parsed because it is possible to get * commands which use it before the MAIL command - probably in error */ memset(&delst, 0, sizeof(delivery_status_t)); /* get maximum command length value */ max_smtp_command_length = atoi(script_get_var("max-smpt-command-length", "1024")); if (max_smtp_command_length < 512) max_smtp_command_length = 512; /* send the initial greeting */ if (!send_greeting(socket)) return; /* command loop */ while (looping) { char buff[1024]; int bytes_read; int i; /* try to read some data */ bytes_read = read(socket, buff, sizeof(buff)); if (bytes_read == 0) { /* connection closed, let's break */ break; } if (bytes_read == -1) { /* something went wrong, let's retry a few times and break later*/ if (++tries == 32) break; continue; } tries = 0; /* process the data */ for (i=0; i<bytes_read; i++) { if (buff[i] == '\n') { /* found a newline \n */ new_cmd = realloc(cmd, cmd_len + 1); if (!new_cmd) { /* out of memory, abort */ send_string(socket, "451 I've ran out of memor... what?\r\n"); looping = 0; break; } cmd = new_cmd; cmd[cmd_len] = 0; /* parse the command */ parse_smtp_command(socket, &delst, cmd, cmd_len); /* prepare for a new one */ free(cmd); cmd = NULL; cmd_len = 0; } else if (buff[i] == '\r') { /* ignore CRs */ } else { /* found... something else - put it in the command, as long as * the command's length is not as large as the maximum value */ if (max_smtp_command_length > cmd_len) { new_cmd = realloc(cmd, cmd_len + 1); if (!new_cmd) { /* out of memory, abort */ send_string(socket, "451 I've ran out of memo... who are you?\r\n"); looping = 0; break; } cmd = new_cmd; cmd[cmd_len++] = buff[i]; } } } } delst_release(&delst); free(cmd); }
int main(int argc, char** argv) { if(argc != 4){ printf("Usage: %s <server-ip> <port> <directory\n", argv[0]); return 0; } char buffer[(1<<16)+1]; buffer[0] = '\0'; DIR *dir; struct dirent *ent; if ((dir = opendir (argv[3])) != NULL) { //read all files in the directory specified while ((ent = readdir (dir)) != NULL) { // send_stuffed_msg(con, ent->d_name); // if(!receive_ack(con)){ // printf("The server don't seem to support our protocol\n"); // close_connection(con); // return EXIT_FAILURE; // } // bytesTransfered += strlen(ent->d_name)+1; // bytesTransfered += ACK_LEN; if(ent->d_name[0] != '.'){ sprintf(buffer, "%s%s\n", buffer, ent->d_name); } } closedir (dir); } else { printf("We couldn't open the specified directory\n"); return EXIT_FAILURE; } char* address = argv[1]; int port = atoi(argv[2]); Connection* con = connect_to_server(address, port); if(con == NULL){ printf("Couldn't connect to the server. Is the address correct? (only ip addesses are supported)\n"); return EXIT_FAILURE; } struct timespec beginTime, endTime; int bytesTransfered = 0; send_greeting(con); if(!receive_greet_ack(con)){ printf("The server don't seem to support our protocol\n"); close_connection(con); return EXIT_FAILURE; } send_stuffed_msg(con, argv[3]); if(!receive_ack(con)){ printf("The server don't seem to support our protocol\n"); close_connection(con); return EXIT_FAILURE; } clock_gettime(CLOCK_REALTIME, &beginTime); send_stuffed_msg(con, buffer); if(!receive_ack(con)){ printf("The server don't seem to support our protocol\n"); close_connection(con); return EXIT_FAILURE; } bytesTransfered = strlen(buffer); clock_gettime(CLOCK_REALTIME, &endTime); send_farewell(con); close_connection(con); double ellapsedTime = (endTime.tv_sec - beginTime.tv_sec) + (endTime.tv_nsec - beginTime.tv_nsec) / 1E9; printf("The file names were successfully sent %d B to server in %f seconds at %f B/s.\n", bytesTransfered, ellapsedTime, (bytesTransfered/ellapsedTime)); return 0; }
int main(int argc, char *argv[]) { char *progname = NULL; srand(time(NULL)); /* Obtain the program name without the full path */ progname = (progname = strrchr(argv[0], '/')) ? progname + 1 : *argv; /* Sanity check */ if (getuid() == 0) { fprintf(stderr, "%s should not be run as root\n", progname); exit(EXIT_FAILURE); } /* Parse options */ if (parse_options(progname, argc, argv)) { usage(progname); exit(EXIT_FAILURE); } /* Obtain start server time in TWAMP format */ TWAMPTimestamp StartTime = get_timestamp(); int listenfd; listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { perror("Error opening socket"); exit(EXIT_FAILURE); } /* Set Server address and bind on the TWAMP port */ struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(SERVER_PORT); used_sockets++; if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) < 0) { perror("Error on binding"); exit(EXIT_FAILURE); } /* Start listening on the TWAMP port for new TWAMP-Control connections */ if (listen(listenfd, MAX_CLIENTS)) { perror("Error on listen"); exit(EXIT_FAILURE); } FD_ZERO(&read_fds); FD_SET(listenfd, &read_fds); fd_max = listenfd; struct client_info clients[MAX_CLIENTS]; memset(clients, 0, MAX_CLIENTS * sizeof(struct client_info)); int newsockfd; struct sockaddr_in client_addr; fd_set tmp_fds; FD_ZERO(&tmp_fds); int rv; while (1) { tmp_fds = read_fds; if (select(fd_max + 1, &tmp_fds, NULL, NULL, NULL) < 0) { perror("Error in select"); close(listenfd); exit(EXIT_FAILURE); } /* If an event happened on the listenfd, then a new TWAMP-Control * connection is received */ if (FD_ISSET(listenfd, &tmp_fds)) { uint32_t client_len = sizeof(client_addr); if ((newsockfd = accept(listenfd, (struct sockaddr *)&client_addr, &client_len)) < 0) { perror("Error in accept"); } else { /* Add a new client if there are any slots available */ int pos = find_empty_client(clients, MAX_CLIENTS); uint8_t mode_mask = 0; if (pos != -1) { clients[pos].status = kConnected; clients[pos].socket = newsockfd; clients[pos].addr = client_addr; clients[pos].sess_no = 0; used_sockets++; FD_SET(newsockfd, &read_fds); if (newsockfd > fd_max) fd_max = newsockfd; mode_mask = 0xFF; } rv = send_greeting(mode_mask, &clients[pos]); } } /* Receives other packets from the established TWAMP-Control sessions */ uint8_t buffer[4096]; int i, j; for (i = 0; i < MAX_CLIENTS; i++) /* It can only receive TWAMP-Control messages from Online clients */ if (clients[i].status != kOffline) if (FD_ISSET(clients[i].socket, &tmp_fds)) { switch (clients[i].status) { case kConnected: /* If a TCP session has been established and a * ServerGreeting has been sent, wait for the * SetUpResponse and finish the TWAMP-Control setup */ rv = receive_greet_response(&clients[i]); if (rv > 0) { rv = send_start_serv(&clients[i], StartTime); } break; case kConfigured: /* Reset the buffer to receive a new message */ memset(buffer, 0, 4096); rv = recv(clients[i].socket, buffer, 4096, 0); if (rv <= 0) { cleanup_client(&clients[i]); break; } /* Check the message received: It can only be * StartSessions or RequestTWSession */ switch (buffer[0]) { case kStartSessions: rv = receive_start_sessions(&clients[i], (StartSessions *)buffer); break; case kRequestTWSession: rv = receive_request_session(&clients[i], (RequestSession *)buffer); break; default: break; } if (rv <= 0) cleanup_client(&clients[i]); break; case kTesting: /* In this state can only receive a StopSessions msg */ memset(buffer, 0, 4096); rv = recv(clients[i].socket, buffer, 4096, 0); if (rv <= 0) { cleanup_client(&clients[i]); break; } if (buffer[0] == kStopSessions) { rv = receive_stop_sessions(&clients[i], (StopSessions *) buffer); } break; default: break; } } /* Check for TWAMP-Test packets */ for (i = 0; i < MAX_CLIENTS; i++) { struct timeval current; gettimeofday(¤t, NULL); if (clients[i].status == kTesting) { uint8_t has_active_test_sessions = 0; for (j = 0; j < clients[i].sess_no; j++) { rv = get_actual_shutdown(¤t, &clients[i].shutdown_time, &clients[i].sessions[j].req.Timeout); if (rv > 0) { has_active_test_sessions = 1; if (FD_ISSET(clients[i].sessions[j].socket, &tmp_fds)) { rv = receive_test_message(&clients[i], j); } } else { FD_CLR(clients[i].sessions[j].socket, &read_fds); close(clients[i].sessions[j].socket); used_sockets--; clients[i].sessions[j].socket = -1; } } if (!has_active_test_sessions) { memset(&clients[i].shutdown_time, 0, sizeof(clients[i].shutdown_time)); clients[i].sess_no = 0; clients[i].status = kConfigured; } } } } return 0; }