"Fossies" - the Fresh Open Source Software Archive

Member "mod_ftp-0.9.6/modules/ftp/ftp_connection.c" (28 May 2009, 9850 Bytes) of package /linux/www/apache_httpd_modules/old/mod_ftp-0.9.6-beta.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ftp_connection.c" see the Fossies "Dox" file reference documentation.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 /*
   18  * Original Copyright (c) 2005 Covalent Technologies
   19  *
   20  * FTP Protocol module for Apache 2.0
   21  */
   22 
   23 #include "mod_ftp.h"
   24 #include "ftp_internal.h"
   25 
   26 /* Placeholder of "unknown" username (not valid for ftp_cmd_pass)
   27  */
   28 const char ftp_unknown_username[] = "unknown";
   29 
   30 /*
   31  * initialize_ftp_connection: Used to initialize the ftp_connection structure
   32  *                            when accepting an incoming FTP connection.
   33  *
   34  * Arguments: c - The connection associated with the session
   35  *            fc - The ftp connection to initialize
   36  *
   37  * Returns: nothing
   38  */
   39 static void initialize_ftp_connection(conn_rec *c, ftp_connection *fc)
   40 {
   41     /*
   42      * The ftp_connection structure is calloc'ed so only initalize the
   43      * members that we need to.
   44      */
   45     fc->connection = c;
   46     fc->user = ftp_unknown_username;
   47     fc->auth = FTP_AUTH_NONE;
   48     fc->prot = FTP_PROT_CLEAR;
   49     fc->type = TYPE_A;
   50     fc->passive_created = -1;
   51     fc->orig_server = c->base_server;
   52 
   53     fc->cwd = apr_palloc(c->pool, APR_PATH_MAX + 1);
   54     fc->cwd[0] = '/';
   55     fc->cwd[1] = '\0';
   56 
   57     fc->rename_from = apr_palloc(c->pool, APR_PATH_MAX + 1);
   58     fc->rename_from[0] = '\0';
   59 
   60     apr_pool_create(&fc->login_pool, c->pool);
   61     apr_pool_tag(fc->login_pool, "login");
   62     apr_pool_create(&fc->data_pool, c->pool);
   63     apr_pool_tag(fc->data_pool, "data");
   64 
   65     fc->cntlsock = ap_get_module_config(c->conn_config, &core_module);
   66 
   67     ftp_set_module_config(c->conn_config, fc);
   68 }
   69 
   70 /* ftp_ssl_init: Fakes a read on the SSL filters to force initialization.
   71  *
   72  * Arguments: cdata - The data connection
   73  *
   74  * Return: apr_status_t
   75  */
   76 apr_status_t ftp_ssl_init(conn_rec *cdata)
   77 {
   78     ftp_connection *fc = ftp_get_module_config(cdata->conn_config);
   79     apr_bucket_brigade *bb;
   80     apr_status_t rv;
   81     apr_socket_t *client_socket;
   82 
   83     /*
   84      * This is handled in the NET_TIME filter, which unfortunately ignores
   85      * the timeout for the purpose of AP_MODE_INIT. Fix a timeout so the core
   86      * read filter will behave.
   87      */
   88     client_socket = ap_get_module_config(cdata->conn_config, &core_module);
   89     rv = apr_socket_timeout_set(client_socket, fc->orig_server->timeout);
   90 
   91     if (rv != APR_SUCCESS) {
   92         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, fc->orig_server,
   93                      "Failed to set socket timeout");
   94     }
   95 
   96     bb = apr_brigade_create(cdata->pool, cdata->bucket_alloc);
   97     rv = ap_get_brigade(cdata->input_filters, bb, AP_MODE_INIT,
   98                         APR_BLOCK_READ, 0);
   99     apr_brigade_destroy(bb);
  100 
  101     if (rv != APR_SUCCESS) {
  102         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, fc->orig_server,
  103                      "Failed to initialize the ftp ssl data stream");
  104     }
  105 
  106     return rv;
  107 }
  108 
  109 /*
  110  * ftp_send_welcome: Send the server welcome string to the client
  111  *
  112  * Arguments: fc - The ftp connection to send the welcome message to
  113  *
  114  * Returns: apr_status_t
  115  */
  116 static apr_status_t ftp_send_welcome(ftp_connection *fc)
  117 {
  118     conn_rec *c = fc->connection;
  119     ftp_server_config *fsc;
  120     apr_status_t rv;
  121 
  122     fsc = ftp_get_module_config(fc->orig_server->module_config);
  123 
  124     /* Check if a login message has been configured */
  125     if (fsc->banner_message) {
  126         if (fsc->banner_message_isfile) {
  127             rv = ftp_show_file(c->output_filters, fc->data_pool,
  128                                FTP_REPLY_SERVICE_READY, fc,
  129                                fsc->banner_message);
  130             if (rv != APR_SUCCESS) {
  131                 return rv;
  132             }
  133         }
  134         else {
  135             char outbuf[BUFSIZ];
  136 
  137             ftp_message_generate(fc, fsc->banner_message,
  138                                  outbuf, sizeof(outbuf));
  139 
  140             rv = ftp_reply(fc, c->output_filters, fc->data_pool,
  141                            FTP_REPLY_SERVICE_READY, 1, outbuf);
  142 
  143             if (rv != APR_SUCCESS) {
  144                 return rv;
  145             }
  146         }
  147     }
  148 
  149     rv = ftp_reply(fc, c->output_filters, fc->data_pool,
  150                    FTP_REPLY_SERVICE_READY, 0,
  151                    "%s FTP Server (%s) ready.",
  152                    fc->orig_server->server_hostname,
  153 #if AP_MODULE_MAGIC_AT_LEAST(20060905,0)
  154                    ap_get_server_banner());
  155 #else
  156                    ap_get_server_version());
  157 #endif
  158     return rv;
  159 }
  160 
  161 /*
  162  * ftp_process_connection: Connection handler for the FTP module.
  163  *
  164  * Arguments: c - The incoming connection
  165  *
  166  * Returns: Returns OK when the connection is to be closed.
  167  */
  168 int ftp_process_connection(conn_rec *c)
  169 {
  170     ap_filter_t *f;
  171     request_rec *r;
  172     ftp_connection *fc;
  173     apr_status_t rv;
  174     int idle_timeout_set = 0;
  175     extern ap_filter_rec_t *ftp_ssl_input_filter_handle;
  176     extern ap_filter_rec_t *ftp_ssl_output_filter_handle;
  177     ftp_server_config *fsc;
  178 
  179     fsc = ftp_get_module_config(c->base_server->module_config);
  180 
  181     if (!fsc->enabled) {
  182         return DECLINED;
  183     }
  184 
  185     /*
  186      * Allocate for FTP connection structure, and initialize
  187      */
  188     fc = apr_pcalloc(c->pool, sizeof(*fc));
  189     initialize_ftp_connection(c, fc);
  190 
  191     /* Check for implicit security on the control connection */
  192     if (!fsc->implicit_ssl) {
  193         for (f = c->output_filters; f; f = f->next) {
  194             if (strcasecmp(f->frec->name, FTP_SSL_FILTER) == 0) {
  195                 fc->ssl_output_ctx = f->ctx;
  196                 ap_remove_output_filter(f);
  197             }
  198         }
  199         for (f = c->input_filters; f; f = f->next) {
  200             if (strcasecmp(f->frec->name, FTP_SSL_FILTER) == 0) {
  201                 fc->ssl_input_ctx = f->ctx;
  202                 ap_remove_input_filter(f);
  203             }
  204         }
  205     }
  206     else {
  207         /* Initialize control connection */
  208         if ((rv = ftp_ssl_init(c)) != APR_SUCCESS) {
  209             /*
  210              * Error initializing the connection, most likely from a client
  211              * attempting to connect w/o SSL.  Just drop the connection
  212              */
  213             ap_log_error(APLOG_MARK, APLOG_INFO, rv, fc->orig_server,
  214                          "Error initializing SSL connection.  Client "
  215                          "connecting without SSL?");
  216             return OK;
  217         }
  218 
  219         /*
  220          * From draft-murray-auth-ftp-ssl-06.txt: For implicit SSL the data
  221          * connection should be implicitly protected (i.e. the PBSZ 0, PROT P
  222          * command sequence is not required but the client and server will
  223          * protect the data channel as if it had).
  224          * 
  225          * Support for Implicit SSL was declared deprecated as of
  226          * draft-murray-auth-ftp-ssl-07.txt, and is not documented whatsoever
  227          * within RFC4217.
  228          */
  229         fc->auth = FTP_AUTH_SSL;
  230         fc->prot = FTP_PROT_PRIVATE;
  231         fc->is_secure = 1;
  232     }
  233 
  234     rv = ftp_send_welcome(fc);
  235     if (rv != APR_SUCCESS) {
  236         ap_log_error(APLOG_MARK, APLOG_INFO, rv, fc->orig_server,
  237                      "Error sending server welcome string");
  238         return OK;
  239     }
  240 
  241     /*
  242      * Begin processing requests
  243      */
  244 
  245     /* Set initial login timeout value */
  246     rv = apr_socket_timeout_set(fc->cntlsock,
  247                                 fsc->timeout_login * APR_USEC_PER_SEC);
  248     if (rv != APR_SUCCESS) {
  249         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, fc->orig_server,
  250                      "Couldn't set SO_TIMEOUT socket option");
  251     }
  252 
  253     ap_update_child_status(c->sbh,
  254                            SERVER_BUSY_READ, NULL);
  255 
  256     while ((r = ftp_read_request(fc)) != NULL) {
  257 
  258         /*
  259          * Set socket timeout values.  A user can use the SITE command to
  260          * change the idle timeout during an FTP session, but since we do not
  261          * support the SITE command, it doesn't make sense to be setting the
  262          * socket timeout on every single request.
  263          */
  264         if (!idle_timeout_set) {
  265             rv = apr_socket_timeout_set(fc->cntlsock,
  266                                         fsc->timeout_idle * APR_USEC_PER_SEC);
  267             if (rv != APR_SUCCESS) {
  268                 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
  269                              "Couldn't set socket timeout");
  270             }
  271             idle_timeout_set = 1;
  272         }
  273 
  274         ap_update_child_status(c->sbh,
  275                                SERVER_BUSY_WRITE, NULL);
  276 
  277         ftp_process_request(r);
  278 
  279         if (ap_extended_status) {
  280             ap_increment_counts(c->sbh, r);
  281         }
  282 
  283         apr_pool_destroy(r->pool);
  284 
  285         /* Check if the connection should be closed  */
  286         if (fc->close_connection) {
  287             break;
  288         }
  289 
  290         /* Check if the client has requested a secure connection */
  291         if ((fc->auth == FTP_AUTH_TLS || fc->auth == FTP_AUTH_SSL) &&
  292             fc->is_secure == 0) {
  293             ap_add_output_filter_handle(ftp_ssl_output_filter_handle,
  294                                         fc->ssl_output_ctx, NULL, c);
  295             ap_add_input_filter_handle(ftp_ssl_input_filter_handle,
  296                                        fc->ssl_input_ctx, NULL, c);
  297             fc->is_secure = 1;
  298         }
  299     }
  300     if (fc->logged_in) {
  301         ftp_limitlogin_loggedout(c);
  302     }
  303     return OK;
  304 }