Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
/*
 * 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);
}
Beispiel #6
0
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;
}
Beispiel #7
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(&current, 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(&current, &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;
}