Beispiel #1
0
int proxy_ftp_sess_get_feat(pool *p, struct proxy_session *proxy_sess) {
    pool *tmp_pool;
    int res, xerrno = 0;
    cmd_rec *cmd;
    pr_response_t *resp;
    unsigned int resp_nlines = 0;
    char *feats, *token;
    size_t token_len = 0;

    tmp_pool = make_sub_pool(p);

    cmd = pr_cmd_alloc(tmp_pool, 1, C_FEAT);
    res = proxy_ftp_ctrl_send_cmd(tmp_pool, proxy_sess->backend_ctrl_conn, cmd);
    if (res < 0) {
        xerrno = errno;

        pr_trace_msg(trace_channel, 4,
                     "error sending %s to backend: %s", (char *) cmd->argv[0],
                     strerror(xerrno));
        destroy_pool(tmp_pool);

        errno = xerrno;
        return -1;
    }

    resp = proxy_ftp_ctrl_recv_resp(tmp_pool, proxy_sess->backend_ctrl_conn,
                                    &resp_nlines);
    if (resp == NULL) {
        xerrno = errno;

        pr_trace_msg(trace_channel, 4,
                     "error receiving %s response from backend: %s", (char *) cmd->argv[0],
                     strerror(xerrno));
        destroy_pool(tmp_pool);

        errno = xerrno;
        return -1;
    }

    if (resp->num[0] != '2') {
        pr_trace_msg(trace_channel, 4,
                     "received unexpected %s response code %s from backend",
                     (char *) cmd->argv[0], resp->num);

        /* Note: If the UseProxyProtocol ProxyOption is enabled, AND if the
         * response message mentions a "PROXY" command, we might read an
         * error response here that is NOT actually for the FEAT command we just
         * sent.
         *
         * A backend FTP server which does not understand the PROXY protocol
         * will treat it as a normal FTP command, and respond.  And that will
         * put us, the client, out of lockstep with the server, for how do we know
         * that we need to read that error response FIRST, then send another
         * command?
         */

        destroy_pool(tmp_pool);
        errno = EPERM;
        return -1;
    }

    proxy_sess->backend_features = pr_table_nalloc(p, 0, 4);

    feats = resp->msg;
    token = pr_str_get_token2(&feats, (char *) feat_crlf, &token_len);
    while (token != NULL) {
        pr_signals_handle();

        if (token_len > 0) {
            /* The FEAT response lines in which we are interested all start with
             * a single space, per RFC spec.  Ignore any other lines.
             */
            if (token[0] == ' ') {
                char *key, *val, *ptr;

                /* Find the next space in the string, to delimit our key/value pairs. */
                ptr = strchr(token + 1, ' ');
                if (ptr != NULL) {
                    key = pstrndup(p, token + 1, ptr - token - 1);
                    val = pstrdup(p, ptr + 1);

                } else {
                    key = pstrdup(p, token + 1);
                    val = pstrdup(p, "");
                }

                pr_table_add(proxy_sess->backend_features, key, val, 0);
            }
        }

        feats = token + token_len + 1;
        token = pr_str_get_token2(&feats, (char *) feat_crlf, &token_len);
    }

    destroy_pool(tmp_pool);
    return 0;
}
Beispiel #2
0
char *pr_str_get_token(char **src, char *sep) {
  return pr_str_get_token2(src, sep, NULL);
}