Esempio n. 1
0
/* Run command, check authentication first */
static void ftpsrv_process_cmd(FTPSRV_SESSION_STRUCT* session)
{
    const FTPSRV_COMMAND_STRUCT* row = ftpsrv_commands;
    int result = 1;
    char* cp = session->command;
    uint32_t auth_valid;

    /* Convert command to upper case */
    while (*cp)
    {
        *cp = toupper(*cp);
        cp++;
    }

    /* Find function corresponding to command */
    while ((row->command != NULL) && strncmp(session->command, row->command, strlen(row->command)))
    {
        row++;
    }
    
    /* Process authentication sequence if required */
    auth_valid = ftpsrv_process_auth(session, row->auth_req);
    
    /* Run command if authentication is valid */
    if (auth_valid)
    {
        if (row->function != NULL)
        {
            row->function(session);
        }
        else
        {
            session->message = (char*) ftpsrvmsg_unimp;
        }
    }
    else
    {
        if (session->message == NULL)
        {
            session->message = (char*) ftpsrvmsg_not_logged;
        }
        if (session->auth_input.uid != NULL)
        {
            _mem_free(session->auth_input.uid);
            session->auth_input.uid = NULL;
        }
    }

    ftpsrv_send_msg(session, session->message);
    session->message = NULL;
    _mem_zero(session->buffer, FTPSRV_BUF_SIZE);
}
Esempio n. 2
0
int32_t ftpsrv_help(FTPSRV_SESSION_STRUCT* session)
{
    const FTPSRV_COMMAND_STRUCT* cmd_ptr = ftpsrv_commands;
    uint32_t                     length = 0;
    uint32_t                     n = 1;
    uint32_t                     space = FTPSRV_BUF_SIZE;
    uint32_t                     max_cmd_length = ftpsrv_max_cmd_length();
    char*                        separator;
    char*                        buffer = session->buffer;

    ftpsrv_send_msg(session, ftpsrvmsg_help_start);

    while(cmd_ptr->command != NULL)
    {
        /* After every fifth command print a new line. Commands are separated by spaces */
        separator = (n % 4) ? " " : "\r\n";
        n++;
        length += snprintf(buffer+length, space, "%s%s", cmd_ptr->command, separator);
        space = FTPSRV_BUF_SIZE-length;
        
        /* If there is not enough space in the buffer flush it to client and repeat printing */
        if (space < (max_cmd_length + sizeof("\r\n")))
        {
            send(session->control_sock, buffer, FTPSRV_BUF_SIZE-space, 0);
            _mem_zero(buffer, length);
            space = FTPSRV_BUF_SIZE;
            length = 0;
        }

        cmd_ptr++;
    }

    if (n)
    {
        space -= snprintf(buffer+length, space, "\r\n");
    }
    
    /* Send command list from the buffer and set message to HELP end text */
    send(session->control_sock, buffer, FTPSRV_BUF_SIZE-space, 0);

    session->message = (char*) ftpsrvmsg_help_end;
    return(FTPSRV_OK);
}
Esempio n. 3
0
/* Task for reading/writing file */
void ftpsrv_transfer_task(void* init_ptr, void* creator)
{
    FTPSRV_TRANSFER_PARAM* param = (FTPSRV_TRANSFER_PARAM*) init_ptr;
    MQX_FILE_PTR           file = param->file;
    uint32_t               mode = param->mode;
    uint32_t               sock = param->sock;
    FTPSRV_SESSION_STRUCT* session = param->session;
    void*                  data_buffer;
    char*                  msg_str;

    if (session->state == FTPSRV_STATE_TRANSFER)
    {
        RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR);
        return;
    }

    data_buffer = RTCS_mem_alloc(FTPSRVCFG_DATA_BUFFER_SIZE);
    if (data_buffer == NULL)
    {
        RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR);
        return;
    }

    session->transfer_tid = _task_get_id();
    session->state = FTPSRV_STATE_TRANSFER;

    RTCS_task_resume_creator(creator, (uint32_t) RTCS_OK);
    
    while (1)
    {
        FTPSRV_TRANSFER_MSG message;
        _mqx_uint           retval;

        /* Reading from file */
        if (mode == FTPSRV_MODE_READ)
        {
            uint32_t length;
            int32_t  error;

            length = fread((void*) data_buffer, 1, FTPSRVCFG_DATA_BUFFER_SIZE, file);
            if ((length != FTPSRVCFG_DATA_BUFFER_SIZE) && ferror(file) && !feof(file))
            {
                msg_str = (char*) ftpsrvmsg_locerr;
                break;
            }
            error = send(sock, data_buffer, length, 0);
            if (error == RTCS_ERROR)
            {
                msg_str = (char*) ftpsrvmsg_locerr;
                break;
            }

            if (feof(file))
            {
                msg_str = (char*) ftpsrvmsg_trans_complete;
                break;
            }
        }
        /* Writing to file */
        else if ((mode == FTPSRV_MODE_WRITE) || (mode == FTPSRV_MODE_APPEND))
        {
            uint32_t length;
            int32_t  received;

            received = recv(sock, data_buffer, FTPSRVCFG_DATA_BUFFER_SIZE, 0);
            if (received == RTCS_ERROR)
            {
                msg_str = (char*) ftpsrvmsg_trans_complete;
                break;
            }
            
            length = fwrite((void*) data_buffer, 1, received, file);
            if (length != received)
            {
                if (length == IO_ERROR)
                {
                    msg_str = (char*) ftpsrvmsg_no_space;
                }
                else
                {
                    msg_str = (char*) ftpsrvmsg_writefail;
                }
                break;
            }
        }
        retval = _lwmsgq_receive((void*) session->msg_queue, (uint32_t *)&message, LWMSGQ_TIMEOUT_FOR, 1, NULL);
        if (retval != MQX_OK)
        {
            continue;
        }
        if (message.command == FTPSRV_CMD_ABORT)
        {
            msg_str = (char*) ftpsrvmsg_trans_abort;
            break;
        }
        else if (message.command == FTPSRV_CMD_STAT)
        {
            /* TODO: Add code to print out transfer statistics */
        }
    }
    _mem_free(data_buffer);
    fclose(file);
    ftpsrv_send_msg(session, msg_str);
    shutdown(sock, FLAG_CLOSE_TX);
    session->state = FTPSRV_STATE_IDLE;
}
Esempio n. 4
0
static void ftpsrv_session_task(void* init_ptr, void* creator)
{
    FTPSRV_SESSION_STRUCT* session;
    FTPSRV_STRUCT*         server = ((FTPSRV_SESSION_PARAM*) init_ptr)->server;
    uint32_t               sock = ((FTPSRV_SESSION_PARAM*) init_ptr)->sock;
    uint32_t               i;
    _task_id               tid =  _task_get_id();
    _mqx_uint              retval = 0;

    /* Find empty session */
    _lwsem_wait(&server->tid_sem);

    for (i = 0; i < server->params.max_ses; i++)
    {
        if (server->session[i] == NULL)
        {
            break;
        }
    }
     
    if (i == server->params.max_ses)
    {
        RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR);
        _lwsem_post(&server->tid_sem);
        _lwsem_post(&server->ses_cnt);
        return;
    }
    
    /* Save task ID - used for indication of running task */
    server->ses_tid[i] = tid;
    /* Access to array done. Unblock other tasks. */
    _lwsem_post(&server->tid_sem);
    
    /* Allocate session */
    session = ftpsrv_ses_alloc(server);

    if (session) 
    {
        server->session[i] = session;

        RTCS_task_resume_creator(creator, RTCS_OK);       
        ftpsrv_ses_init(server, session, sock);
        ftpsrv_send_msg(session, ftpsrvmsg_banner);
        
        /* Read and process commands */
        while (session->connected)
        {
            if (ftpsrv_read_cmd(session) != FTPSRV_OK)
            {
                _mem_zero(session->buffer, FTPSRV_BUF_SIZE);
                continue;
            }
            ftpsrv_process_cmd(session);
            _sched_yield();
        }
        /* cleanup session */
        ftpsrv_ses_close(session);
        ftpsrv_ses_free(session);
        server->session[i] = NULL;
    }
    else 
    {
        RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR);
    }

    /* Cleanup and end task */
    _lwsem_post(&server->ses_cnt);
    /* Null tid => task is no longer running */
    _lwsem_wait(&server->tid_sem);
    server->ses_tid[i] = 0;
    _lwsem_post(&server->tid_sem);
}
Esempio n. 5
0
int32_t ftpsrv_list(FTPSRV_SESSION_STRUCT* session)
{
    int32_t  length;
    char*    path;
    void*    dir_ptr;
    uint32_t sock;
    char*    dir_param;
    char*    full_path;
    char*    temp;
    uint32_t path_length;
    uint32_t wrong_path;

    if (session->cmd_arg == NULL)
    {
        path = "";
    }
    else
    {
        rtcs_url_decode(session->cmd_arg);
        path = rtcs_path_strip_delimiters(session->cmd_arg);
    }

    /* Translate relative path to absolute. */
    full_path = ftpsrv_get_full_path(session, path, &wrong_path);
    if (full_path == NULL)
    {
        if (wrong_path)
        {
            session->message = (char*) ftpsrvmsg_no_file;
        }
        else
        {
            session->message = (char*) ftpsrvmsg_no_memory;
        }
        return(FTPSRV_ERROR);
    }
    path_length = strlen(full_path);

    /* Allocate space for path + appendix, copy full path and add appendix to it. */
    /* This is required because MFS cannot list directories, only files. */
    temp = RTCS_mem_alloc_zero(path_length+sizeof(FTPSRV_PATH_APPENDIX)); 
    _mem_copy(full_path, temp, path_length);
    _mem_copy(FTPSRV_PATH_APPENDIX, temp+path_length, sizeof(FTPSRV_PATH_APPENDIX)-1);
    _mem_free(full_path);
    full_path = temp;

    /* Open directory. Unix format for LIST command, simple file list for NLIST. */
    if (!strcmp(session->command, "LIST"))
    {
        /* Unix */
        dir_param = "u*";
    }
    else
    {
        /* File list */
        dir_param = "f*";
    }

    /* Open directory, get list, cleanup and return. */
    dir_ptr = _io_mfs_dir_open(session->fs_ptr, full_path, dir_param);
    if (dir_ptr == NULL)
    {
        session->message = (char*) ftpsrvmsg_no_file;
        return(FTPSRV_ERROR);
    } 

    /* Send initialization message */
    ftpsrv_send_msg(session, ftpsrvmsg_opening_datacon);
    
    /* Open data connection */
    sock = ftpsrv_open_data_connection(session);
    if (sock == RTCS_SOCKET_ERROR)
    {
        session->message = (char*) ftpsrvmsg_locerr;
        _mem_free(full_path);
        _io_mfs_dir_close(dir_ptr);
        return(FTPSRV_ERROR);
    }

    /* Send data (directory listing). */
    while ((length = _io_mfs_dir_read(dir_ptr, session->buffer, FTPSRV_BUF_SIZE)) > 0)
    {
        /* If we are in root do not list "one level up" nor "current dir" link */
        if ((strstr(session->buffer, " .. ") || strstr(session->buffer, " . ")) && !strcmp(session->cur_dir, "\\"))
        {
            _mem_zero(session->buffer, length);
        }
        else
        {
            if (send(sock, session->buffer, length, 0) != length)
            { 
                ftpsrv_send_msg(session, ftpsrvmsg_writefail);
                break;
            }
        }
    }
    /* Cleanup */
    closesocket(sock);
    _io_mfs_dir_close(dir_ptr);
    _mem_free(full_path);

    session->message = (char*) ftpsrvmsg_trans_complete;
    return FTPSRV_OK;
}