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

📄 proxy_ftp.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
        case 550:            ap_proxyerror(r, HTTP_BAD_GATEWAY,                             "Failed to read PWD on ftp server");            break;        case 257: {            const char *dirp = ftpmessage;            cwd = ap_getword_conf(r->pool, &dirp);        }    }    return cwd;}/* Common routine for failed authorization (i.e., missing or wrong password) * to an ftp service. This causes most browsers to retry the request * with username and password (which was presumably queried from the user) * supplied in the Authorization: header. * Note that we "invent" a realm name which consists of the * ftp://user@host part of the reqest (sans password -if supplied but invalid-) */static int ftp_unauthorized(request_rec *r, int log_it){    r->proxyreq = PROXYREQ_NONE;    /*     * Log failed requests if they supplied a password (log username/password     * guessing attempts)     */    if (log_it)        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,                      "proxy: missing or failed auth to %s",                      apr_uri_unparse(r->pool,                                 &r->parsed_uri, APR_URI_UNP_OMITPATHINFO));    apr_table_setn(r->err_headers_out, "WWW-Authenticate",                   apr_pstrcat(r->pool, "Basic realm=\"",                               apr_uri_unparse(r->pool, &r->parsed_uri,                       APR_URI_UNP_OMITPASSWORD | APR_URI_UNP_OMITPATHINFO),                               "\"", NULL));    return HTTP_UNAUTHORIZED;}/* * Handles direct access of ftp:// URLs * Original (Non-PASV) version from * Troy Morrison <spiffnet@zoom.com> * PASV added by Chuck * Filters by [Graham Leggett <minfrin@sharp.fm>] */int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,                             char *url, const char *proxyhost,                             apr_port_t proxyport){    apr_pool_t *p = r->pool;    conn_rec *c = r->connection;    proxy_conn_rec *backend;    apr_socket_t *sock, *local_sock, *data_sock = NULL;    apr_sockaddr_t *connect_addr;    apr_status_t rv;    conn_rec *origin, *data = NULL;    int err;    apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);    char *buf, *connectname;    apr_port_t connectport;    char buffer[MAX_STRING_LEN];    char *ftpmessage = NULL;    char *path, *strp, *type_suffix, *cwd = NULL;    apr_uri_t uri;     char *user = NULL;/*    char *account = NULL; how to supply an account in a URL? */    const char *password = NULL;    int len, rc;    int one = 1;    char *size = NULL;    apr_socket_t *origin_sock = NULL;    char xfer_type = 'A'; /* after ftp login, the default is ASCII */    int  dirlisting = 0;#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))    apr_time_t mtime = 0L;#endif    /* stuff for PASV mode */    int connect = 0, use_port = 0;    char dates[APR_RFC822_DATE_LEN];    /* is this for us? */    if (proxyhost) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: FTP: declining URL %s - proxyhost %s specified:", url, proxyhost);        return DECLINED;        /* proxy connections are via HTTP */    }    if (strncasecmp(url, "ftp:", 4)) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: FTP: declining URL %s - not ftp:", url);        return DECLINED;        /* only interested in FTP */    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: FTP: serving URL %s", url);    /* create space for state information */    backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_ftp_module);    if (!backend) {        backend = apr_pcalloc(c->pool, sizeof(proxy_conn_rec));        backend->connection = NULL;        backend->hostname = NULL;        backend->port = 0;        ap_set_module_config(c->conn_config, &proxy_ftp_module, backend);    }    if (backend->connection)        origin_sock = ap_get_module_config(backend->connection->conn_config, &core_module);    /*     * I: Who Do I Connect To? -----------------------     *     * Break up the URL to determine the host to connect to     */    /* we only support GET and HEAD */    if (r->method_number != M_GET)        return HTTP_NOT_IMPLEMENTED;    /* We break the URL into host, port, path-search */    if (r->parsed_uri.hostname == NULL) {        if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {            return ap_proxyerror(r, HTTP_BAD_REQUEST,                apr_psprintf(p, "URI cannot be parsed: %s", url));        }        connectname = uri.hostname;        connectport = uri.port;        path = apr_pstrdup(p, uri.path);    }    else {        connectname = r->parsed_uri.hostname;        connectport = r->parsed_uri.port;        path = apr_pstrdup(p, r->parsed_uri.path);    }    if (connectport == 0) {        connectport = apr_uri_port_of_scheme("ftp");    }    path = (path != NULL && path[0] != '\0') ? &path[1] : "";    type_suffix = strchr(path, ';');    if (type_suffix != NULL)        *(type_suffix++) = '\0';    if (type_suffix != NULL && strncmp(type_suffix, "type=", 5) == 0        && apr_isalpha(type_suffix[5])) {        /* "type=d" forces a dir listing.         * The other types (i|a|e) are directly used for the ftp TYPE command         */        if ( ! (dirlisting = (apr_tolower(type_suffix[5]) == 'd')))            xfer_type = apr_toupper(type_suffix[5]);        /* Check valid types, rather than ignoring invalid types silently: */        if (strchr("AEI", xfer_type) == NULL)            return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(r->pool,                                    "ftp proxy supports only types 'a', 'i', or 'e': \"",                                    type_suffix, "\" is invalid.", NULL));    }    else {        /* make binary transfers the default */        xfer_type = 'I';    }    /*     * The "Authorization:" header must be checked first. We allow the user     * to "override" the URL-coded user [ & password ] in the Browsers'     * User&Password Dialog. NOTE that this is only marginally more secure     * than having the password travel in plain as part of the URL, because     * Basic Auth simply uuencodes the plain text password. But chances are     * still smaller that the URL is logged regularly.     */    if ((password = apr_table_get(r->headers_in, "Authorization")) != NULL        && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0        && (password = ap_pbase64decode(r->pool, password))[0] != ':') {        /*         * Note that this allocation has to be made from r->connection->pool         * because it has the lifetime of the connection.  The other         * allocations are temporary and can be tossed away any time.         */        user = ap_getword_nulls(r->connection->pool, &password, ':');        r->ap_auth_type = "Basic";        r->user = r->parsed_uri.user = user;    }    else if ((user = r->parsed_uri.user) != NULL) {        user = apr_pstrdup(p, user);        decodeenc(user);        if ((password = r->parsed_uri.password) != NULL) {            char *tmp = apr_pstrdup(p, password);            decodeenc(tmp);            password = tmp;        }    }    else {        user = "anonymous";        password = "apache-proxy@";    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,       "proxy: FTP: connecting %s to %s:%d", url, connectname, connectport);    /* do a DNS lookup for the destination host */    err = apr_sockaddr_info_get(&connect_addr, connectname, APR_UNSPEC, connectport, 0, p);    /* check if ProxyBlock directive on this host */    if (OK != ap_proxy_checkproxyblock(r, conf, connect_addr)) {        return ap_proxyerror(r, HTTP_FORBIDDEN,                             "Connect to remote machine blocked");    }    /*     * II: Make the Connection -----------------------     *     * We have determined who to connect to. Now make the connection.     */    /*     * get all the possible IP addresses for the destname and loop through     * them until we get a successful connection     */    if (APR_SUCCESS != err) {        return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,                                                 "DNS lookup failure for: ",                                                        connectname, NULL));    }    /*     * At this point we have a list of one or more IP addresses of the     * machine to connect to. If configured, reorder this list so that the     * "best candidate" is first try. "best candidate" could mean the least     * loaded server, the fastest responding server, whatever.     *     * For now we do nothing, ie we get DNS round robin. XXX FIXME     */    /* try each IP address until we connect successfully */    {        int failed = 1;        while (connect_addr) {	    if ((rv = apr_socket_create(&sock, connect_addr->family, SOCK_STREAM, r->pool)) != APR_SUCCESS) {		ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,			      "proxy: FTP: error creating socket");                connect_addr = connect_addr->next;		continue;	    }#if !defined(TPF) && !defined(BEOS)	    if (conf->recv_buffer_size > 0		&& (rv = apr_socket_opt_set(sock, APR_SO_RCVBUF,                                            conf->recv_buffer_size))) {		ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,			      "apr_socket_opt_set(APR_SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");	    }#endif	    if (APR_SUCCESS != (rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, one))) {		apr_socket_close(sock);#ifndef _OSD_POSIX              /* BS2000 has this option "always on" */		ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,			      "proxy: FTP: error setting reuseaddr option: apr_socket_opt_set(APR_SO_REUSEADDR)");                connect_addr = connect_addr->next;		continue;#endif                          /* _OSD_POSIX */	    }	    /* Set a timeout on the socket */	    if (conf->timeout_set == 1) {		apr_socket_timeout_set(sock, conf->timeout);	    }	    else {		apr_socket_timeout_set(sock, r->server->timeout);	    }            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: FTP: fam %d socket created, trying to connect to %pI (%s)...",                          connect_addr->family, connect_addr, connectname);            /* make the connection out of the socket */            rv = apr_connect(sock, connect_addr);            /* if an error occurred, loop round and try again */            if (rv != APR_SUCCESS) {		apr_socket_close(sock);                ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,                             "proxy: FTP: attempt to connect to %pI (%s) failed", connect_addr, connectname);                connect_addr = connect_addr->next;                continue;            }            /* if we get here, all is well */            failed = 0;            break;        }        /* handle a permanent error from the above loop */        if (failed) {            return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,                          "Could not connect to remote machine: %s port %d",                                                 connectname, connectport));        }    }    /* the socket is now open, create a new connection */    origin = ap_run_create_connection(p, r->server, sock, r->connection->id,                                      r->connection->sbh, c->bucket_alloc);    if (!origin) {        /*         * the peer reset the connection already; ap_run_create_connection() closed         * the socket         */        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: FTP: an error occurred creating a new connection to %pI (%s)", connect_addr, connectname);        return HTTP_INTERNAL_SERVER_ERROR;    }    /* if a keepalive connection is floating around, close it first! */    /* we might support ftp keepalives later, but not now... */    if (backend->connection) {        apr_socket_close(origin_sock);        backend->connection = NULL;        origin_sock = NULL;    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: FTP: control connection complete");    /*     * III: Send Control Request -------------------------     *     * Log into the ftp server, send the username & password, change to the     * correct directory...     */    /* set up the connection filters */    rc = ap_run_pre_connection(origin, sock);    if (rc != OK && rc != DONE) {

⌨️ 快捷键说明

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