⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxy_ftp.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 4 页
字号:
                                                   strerror(errno), NULL)));    }    /* record request_time for HTTP/1.1 age calculation */    c->req_time = time(NULL);    ctrl = ap_bcreate(p, B_RDWR | B_SOCKET);    ap_bpushfd(ctrl, sock, sock);/* shouldn't we implement telnet control options here? */#ifdef CHARSET_EBCDIC    ap_bsetflag(ctrl, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 1);#endif                          /* CHARSET_EBCDIC */    /* possible results: */    /* 120 Service ready in nnn minutes. */    /* 220 Service ready for new user. */    /* 421 Service not available, closing control connection. */    ap_hard_timeout("proxy ftp", r);    i = ftp_getrc_msg(ctrl, resp, sizeof resp);    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);    if (i == -1 || i == 421) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                      ap_proxyerror(r, HTTP_BAD_GATEWAY,                                       "Error reading from remote server"));    }#if 0    if (i == 120) {        /*         * RFC2068 states: 14.38 Retry-After         *          * The Retry-After response-header field can be used with a 503 (Service         * Unavailable) response to indicate how long the service is expected         * to be unavailable to the requesting client. The value of this         * field can be either an HTTP-date or an integer number of seconds         * (in decimal) after the time of the response. Retry-After  =         * "Retry-After" ":" ( HTTP-date | delta-seconds )         *//**INDENT** Error@756: Unbalanced parens */        ap_set_header("Retry-After", ap_psprintf(p, "%u", 60 * wait_mins);        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                          ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp));    }#endif    if (i != 220) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                  ap_proxyerror(r, HTTP_BAD_GATEWAY, resp));    }    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: connected.");    ap_bvputs(ctrl, "USER ", user, CRLF, NULL);    ap_bflush(ctrl);            /* capture any errors */    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: USER %s", user);    /* possible results; 230, 331, 332, 421, 500, 501, 530 */    /* states: 1 - error, 2 - success; 3 - send password, 4,5 fail */    /* 230 User logged in, proceed. */    /* 331 User name okay, need password. */    /* 332 Need account for login. */    /* 421 Service not available, closing control connection. */    /* 500 Syntax error, command unrecognized. */    /* (This may include errors such as command line too long.) */    /* 501 Syntax error in parameters or arguments. */    /* 530 Not logged in. */    i = ftp_getrc(ctrl);    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);    if (i == -1 || i == 421) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                      ap_proxyerror(r, HTTP_BAD_GATEWAY,                                       "Error reading from remote server"));    }    if (i == 530) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                      ftp_unauthorized(r, 1));    }    if (i != 230 && i != 331) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                      HTTP_BAD_GATEWAY);    }    if (i == 331) {             /* send password */        if (password == NULL) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ftp_unauthorized(r, 0));        }        ap_bvputs(ctrl, "PASS ", password, CRLF, NULL);        ap_bflush(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASS %s", password);        /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */        /* 230 User logged in, proceed. */        /* 332 Need account for login. */        /* 421 Service not available, closing control connection. */        /* 500 Syntax error, command unrecognized. */        /* 501 Syntax error in parameters or arguments. */        /* 503 Bad sequence of commands. */        /* 530 Not logged in. */        i = ftp_getrc(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);        if (i == -1 || i == 421) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_GATEWAY,                                       "Error reading from remote server"));        }        if (i == 332) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_UNAUTHORIZED,                                                 "Need account for login"));        }        /* @@@ questionable -- we might as well return a 403 Forbidden here */        if (i == 530)           /* log it: passwd guessing attempt? */            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ftp_unauthorized(r, 1));        if (i != 230 && i != 202)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          HTTP_BAD_GATEWAY);    }    /*     * Special handling for leading "%2f": this enforces a "cwd /" out of the     * $HOME directory which was the starting point after login     */    if (strncasecmp(path, "%2f", 3) == 0) {        path += 3;        while (*path == '/')    /* skip leading '/' (after root %2f) */            ++path;        ap_bputs("CWD /" CRLF, ctrl);        ap_bflush(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD /");        /* possible results: 250, 421, 500, 501, 502, 530, 550 */        /* 250 Requested file action okay, completed. */        /* 421 Service not available, closing control connection. */        /* 500 Syntax error, command unrecognized. */        /* 501 Syntax error in parameters or arguments. */        /* 502 Command not implemented. */        /* 530 Not logged in. */        /* 550 Requested action not taken. */        i = ftp_getrc(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);        if (i == -1 || i == 421)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_GATEWAY,                                       "Error reading from remote server"));        else if (i == 550)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          HTTP_NOT_FOUND);        else if (i != 250)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          HTTP_BAD_GATEWAY);    }/* set the directory (walk directory component by component): * this is what we must do if we don't know the OS type of the remote * machine */    for (; (strp = strchr(path, '/')) != NULL; path = strp + 1) {        char *slash = strp;        *slash = '\0';        /* Skip multiple '/' (or trailing '/') to avoid 500 errors */        while (strp[1] == '/')            ++strp;        if (strp[1] == '\0')            break;        len = decodeenc(path);  /* Note! This decodes a %2f -> "/" */        if (strchr(path, '/'))  /* were there any '/' characters? */            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_REQUEST,                       "Use of %2F is only allowed at the base directory"));        ap_bvputs(ctrl, "CWD ", path, CRLF, NULL);        ap_bflush(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: CWD %s", path);        *slash = '/';/* responses: 250, 421, 500, 501, 502, 530, 550 */        /* 250 Requested file action okay, completed. */        /* 421 Service not available, closing control connection. */        /* 500 Syntax error, command unrecognized. */        /* 501 Syntax error in parameters or arguments. */        /* 502 Command not implemented. */        /* 530 Not logged in. */        /* 550 Requested action not taken. */        i = ftp_getrc(ctrl);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", i);        if (i == -1 || i == 421)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_GATEWAY,                                       "Error reading from remote server"));        if (i == 550)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          HTTP_NOT_FOUND);        if (i == 500 || i == 501)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_REQUEST,                      "Syntax error in filename (reported by ftp server)"));        if (i != 250)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          HTTP_BAD_GATEWAY);    }    if (parms != NULL && strncmp(parms, "type=", 5) == 0        && ap_isalpha(parms[5])) {        /*         * "type=d" forces a dir listing. The other types (i|a|e) are         * directly used for the ftp TYPE command         */        if (!(get_dirlisting = (parms[5] == 'd')))            xfer_type = ap_toupper(parms[5]);        /* Check valid types, rather than ignoring invalid types silently: */        if (strchr("AEI", xfer_type) == NULL)            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                      ap_proxyerror(r, HTTP_BAD_REQUEST, ap_pstrcat(r->pool,                       "ftp proxy supports only types 'a', 'i', or 'e': \"",                                           parms, "\" is invalid.", NULL)));    }    else {        /* make binary transfers the default */        xfer_type = 'I';    }/* try to set up PASV data connection first */    dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);    if (dsock == -1) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,                                      "proxy: error creating PASV socket"));    }#if !defined (TPF) && !defined(BEOS)    if (conf->recv_buffer_size) {        if (setsockopt(dsock, SOL_SOCKET, SO_RCVBUF,                (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, r,                          "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");        }    }#endif    ap_bputs("PASV" CRLF, ctrl);    ap_bflush(ctrl);    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASV command issued");/* possible results: 227, 421, 500, 501, 502, 530 */    /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */    /* 421 Service not available, closing control connection. */    /* 500 Syntax error, command unrecognized. */    /* 501 Syntax error in parameters or arguments. */    /* 502 Command not implemented. */    /* 530 Not logged in. */    i = ap_bgets(pasv, sizeof(pasv), ctrl);    if (i == -1 || i == 421) {        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,                               "proxy: PASV: control connection is toast"));    }    else {        pasv[i - 1] = '\0';        pstr = strtok(pasv, " ");       /* separate result code */        if (pstr != NULL) {            presult = atoi(pstr);            if (*(pstr + strlen(pstr) + 1) == '=')                pstr += strlen(pstr) + 2;            else {                pstr = strtok(NULL, "(");       /* separate address & port                                                 * params */                if (pstr != NULL)                    pstr = strtok(NULL, ")");            }        }        else            presult = atoi(pasv);        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: returned status %d", presult);        if (presult == 227 && pstr != NULL && (sscanf(pstr,                 "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {            /* pardon the parens, but it makes gcc happy */            paddr = (((((h3 << 8) + h2) << 8) + h1) << 8) + h0;            pport = (p1 << 8) + p0;            ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d",                         h3, h2, h1, h0, pport);            data_addr.sin_family = AF_INET;            data_addr.sin_addr.s_addr = htonl(paddr);            data_addr.sin_port = htons(pport);            i = ap_proxy_doconnect(dsock, &data_addr, r);            if (i == -1) {                return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                          ap_proxyerror(r, HTTP_BAD_GATEWAY,                                                        ap_pstrcat(r->pool,                                    "Could not connect to remote machine: ",                                                   strerror(errno), NULL)));            }            pasvmode = 1;        }        else {            ap_pclosesocket(p, dsock);  /* and try the regular way */            dsock = -1;        }    }    if (!pasvmode) {            /* set up data connection */        clen = sizeof(struct sockaddr_in);        if (getsockname(sock, (struct sockaddr *)&server, &clen) < 0) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,                                    "proxy: error getting socket address"));        }        dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);        if (dsock == -1) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,                                           "proxy: error creating socket"));        }        if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one,                       sizeof(one)) == -1) {#ifndef _OSD_POSIX              /* BS2000 has this option "always on" */            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,                                  "proxy: error setting reuseaddr option"));#endif                          /* _OSD_POSIX */        }        if (bind(dsock, (struct sockaddr *)&server,                 sizeof(struct sockaddr_in)) == -1) {            return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,             ap_psprintf(p, "proxy: error binding to ftp data socket %s:%d",                         inet_ntoa(server.sin_addr), server.sin_port)));        }        listen(dsock, 2);       /* only need a short queue */    }/* set request; "path" holds last path component */    len = decodeenc(path);    if (strchr(path, '/'))      /* were there any '/' characters? */        return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,                                      ap_proxyerror(r, HTTP_BAD_REQUEST,                       "Use of %2F is only allowed at the base directory"));    /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -