"Fossies" - the Fresh Open Source Software Archive

Member "mod_ftp-0.9.6/modules/ftp/ftp_limitlogin.c" (25 Aug 2009, 11327 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_limitlogin.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 #include "ap_mpm.h"             /* For MPM query interface */
   27 #include "apr_dbm.h"
   28 #if !(defined(WIN32) || defined(NETWARE))
   29 #include "unixd.h"
   30 #endif
   31 
   32 #define FTP_SERVER_LIMIT_KEY "FireballXL5OnDVD"
   33 #define FTP_DB_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
   34 
   35 /*
   36  * We also use the below as a state variable. Ugly.
   37  */
   38 static apr_global_mutex_t *ftp_lock = NULL;
   39 
   40 static apr_status_t ftp_mutex_init(server_rec *s, apr_pool_t *p)
   41 {
   42     ftp_server_config *fsc = ftp_get_module_config(s->module_config);
   43 
   44     if (fsc->limit_perip || fsc->limit_peruser || fsc->limit_perserver)
   45         return apr_global_mutex_create(&ftp_lock,
   46                             apr_pstrcat(p, fsc->limitdbfile, ".LoCK", NULL),
   47                                        APR_LOCK_DEFAULT, p);
   48     else
   49         return APR_SUCCESS;
   50 }
   51 
   52 static apr_status_t ftp_mutex_on(void)
   53 {
   54     return apr_global_mutex_lock(ftp_lock);
   55 }
   56 
   57 static apr_status_t ftp_mutex_off(void)
   58 {
   59     return apr_global_mutex_unlock(ftp_lock);
   60 }
   61 
   62 static apr_status_t ftp_db_init(server_rec *s, apr_pool_t *p)
   63 {
   64     apr_status_t rv;
   65     apr_dbm_t *dbf;
   66     ftp_server_config *fsc = ftp_get_module_config(s->module_config);
   67 
   68     /*
   69      * Noop in cases where we have not
   70      * setup or enabled the actual mutex. We know
   71      * that this is (still) NULL if ftp_mutex_init() determined
   72      * it didn't need to bother with login limits.
   73      */
   74     if (!ftp_lock)
   75         return APR_SUCCESS;
   76 
   77     ftp_mutex_on();
   78     if ((rv = apr_dbm_open(&dbf, fsc->limitdbfile,
   79                    APR_DBM_RWCREATE, FTP_DB_FILE_MODE, p)) != APR_SUCCESS) {
   80         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
   81                      "Cannot create FTPLimitDBFile file `%s'",
   82                      fsc->limitdbfile);
   83         ftp_mutex_off();
   84         return rv;
   85     }
   86     apr_dbm_close(dbf);
   87 #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
   88     if (geteuid() == 0) {
   89         int ign;
   90 #if MODULE_MAGIC_NUMBER_MAJOR < 20081201
   91 #define ap_unixd_config unixd_config
   92 #endif
   93         ign = chown(fsc->limitdbfile, ap_unixd_config.user_id, -1);
   94         ign = chown(apr_pstrcat(p, fsc->limitdbfile, ".LoCK", NULL),
   95                     ap_unixd_config.user_id, -1);
   96         ign = chown(apr_pstrcat(p, fsc->limitdbfile, ".db", NULL),
   97                     ap_unixd_config.user_id, -1);
   98         ign = chown(apr_pstrcat(p, fsc->limitdbfile, ".dir", NULL),
   99                     ap_unixd_config.user_id, -1);
  100         ign = chown(apr_pstrcat(p, fsc->limitdbfile, ".pag", NULL),
  101                     ap_unixd_config.user_id, -1);
  102     }
  103 #endif
  104     ftp_mutex_off();
  105 
  106     return APR_SUCCESS;
  107 }
  108 
  109 apr_status_t ftp_mutexdb_init(server_rec *s, apr_pool_t *p)
  110 {
  111     apr_status_t rv;
  112     if ((rv = ftp_mutex_init(s, p)) != APR_SUCCESS)
  113         return rv;
  114     return ftp_db_init(s, p);
  115 }
  116 
  117 apr_status_t ftp_mutexdb_child_init(server_rec *s, apr_pool_t *p)
  118 {
  119     ftp_server_config *fsc = ftp_get_module_config(s->module_config);
  120 
  121     if (!ftp_lock)
  122         return APR_SUCCESS;
  123     else
  124         return apr_global_mutex_child_init(&ftp_lock, fsc->limitdbfile, p);
  125 }
  126 
  127 apr_status_t ftp_mutexdb_cleanup(void *data)
  128 {
  129     server_rec *s = data;
  130     ftp_server_config *fsc = ftp_get_module_config(s->module_config);
  131     apr_pool_t *p;
  132 
  133     if (ftp_lock) {
  134         apr_global_mutex_destroy(ftp_lock);
  135         apr_pool_create_ex(&p, s->process->pool, NULL, NULL);
  136         apr_pool_tag(p, "ftp_mutex");
  137         if (p) {
  138             unlink(apr_pstrcat(p, fsc->limitdbfile, ".db", NULL));
  139             unlink(apr_pstrcat(p, fsc->limitdbfile, ".dir", NULL));
  140             unlink(apr_pstrcat(p, fsc->limitdbfile, ".pag", NULL));
  141             unlink(apr_pstrcat(p, fsc->limitdbfile, ".LoCK", NULL));
  142             unlink(fsc->limitdbfile);
  143             apr_pool_destroy(p);
  144         }
  145         ftp_lock = NULL;
  146     }
  147 
  148     return APR_SUCCESS;
  149 }
  150 
  151 #define MYMIN(a,b) ( (a) < (b) ? (a) : (b) )
  152 
  153 ftp_loginlimit_t ftp_limitlogin_check(const char *user, request_rec *r)
  154 {
  155     apr_status_t rv;
  156     conn_rec *c = r->connection;
  157     apr_datum_t ukey;
  158     apr_datum_t ikey;
  159     apr_datum_t skey;
  160     apr_datum_t val;
  161     apr_dbm_t *dbf;
  162     char temp[10];              /* Note: This means only values <=
  163                                  * 999,999,999 */
  164     int uval = 0;
  165     int ival = 0;
  166     int sval = 0;
  167     char *tkey;
  168     char *sname = (r->server->server_hostname
  169                    ? r->server->server_hostname
  170                    : "unknown");
  171     ftp_server_config *fsc =
  172     ftp_get_module_config(r->server->module_config);
  173 
  174     if (!ftp_lock)
  175         return FTP_LIMIT_OK;
  176 
  177     ftp_mutex_on();
  178     if ((rv = apr_dbm_open(&dbf, fsc->limitdbfile,
  179              APR_DBM_RWCREATE, FTP_DB_FILE_MODE, r->pool)) != APR_SUCCESS) {
  180         ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
  181                      "Cannot open FTPLimitDBFile file `%s' for login check",
  182                      fsc->limitdbfile);
  183         ftp_mutex_off();
  184         return FTP_LIMIT_ERROR;
  185     }
  186     /*
  187      * First we check the user settings.
  188      * This is a safe cast, this is a lookup key.
  189      */
  190     tkey = apr_psprintf(r->pool, "%s-%s", sname, user);
  191     ukey.dptr = (char *) tkey;
  192     ukey.dsize = strlen(tkey);
  193     rv = apr_dbm_fetch(dbf, ukey, &val);        /* error for non-existant? */
  194     if (val.dptr != NULL && val.dsize > 0) {
  195         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  196         uval = atoi(temp);
  197     }
  198     if (fsc->limit_peruser && uval >= fsc->limit_peruser) {
  199         ftp_mutex_off();
  200         return FTP_LIMIT_HIT_PERUSER;
  201     }
  202     /*
  203      * Now we check the IP settings.
  204      * This is a safe cast, this is a lookup key.
  205      */
  206     tkey = apr_psprintf(r->pool, "%s-%s", sname, c->remote_ip);
  207     ikey.dptr = (char *) tkey;
  208     ikey.dsize = strlen(tkey);
  209     rv = apr_dbm_fetch(dbf, ikey, &val);        /* error for non-existant? */
  210     if (val.dptr != NULL && val.dsize > 0) {
  211         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  212         ival = atoi(temp);
  213     }
  214     if (fsc->limit_perip && ival >= fsc->limit_perip) {
  215         ftp_mutex_off();
  216         return FTP_LIMIT_HIT_PERIP;
  217     }
  218     /*
  219      * OK, so we're not up against the per user or IP limit,
  220      * we need to check the perserver limit then
  221      */
  222 
  223     tkey = apr_psprintf(r->pool, "%s-%s", sname, FTP_SERVER_LIMIT_KEY);
  224     skey.dptr = (char *) tkey;
  225     skey.dsize = strlen(tkey);
  226     rv = apr_dbm_fetch(dbf, skey, &val);        /* error for non-existant? */
  227     if (val.dptr != NULL && val.dsize > 0) {
  228         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  229         sval = atoi(temp);
  230     }
  231     if (fsc->limit_perserver && sval >= fsc->limit_perserver) {
  232         ftp_mutex_off();
  233         return FTP_LIMIT_HIT_PERSERVER;
  234     }
  235 
  236     /*
  237      * Oh joy. Oh rapture. We have room for this person. We
  238      * now go ahead and update these values in the DB "atomically".
  239      * If not (that is, if we check and then, if OK, we *then*
  240      * update), we hit a race condition.
  241      */
  242     sval++;
  243     uval++;
  244     ival++;
  245     apr_snprintf(temp, sizeof(temp), "%d", uval);
  246     val.dptr = temp;
  247     val.dsize = strlen(temp);
  248     rv = apr_dbm_store(dbf, ukey, val);
  249 
  250     apr_snprintf(temp, sizeof(temp), "%d", ival);
  251     val.dptr = temp;
  252     val.dsize = strlen(temp);
  253     rv = apr_dbm_store(dbf, ikey, val);
  254 
  255     apr_snprintf(temp, sizeof(temp), "%d", sval);
  256     val.dptr = temp;
  257     val.dsize = strlen(temp);
  258     rv = apr_dbm_store(dbf, skey, val);
  259 
  260     apr_dbm_close(dbf);
  261 
  262     ftp_mutex_off();
  263 
  264     return FTP_LIMIT_OK;
  265 }
  266 
  267 int ftp_limitlogin_loggedout(conn_rec *c)
  268 {
  269     ftp_connection *fc = ftp_get_module_config(c->conn_config);
  270     apr_status_t rv;
  271     apr_datum_t ukey;
  272     apr_datum_t ikey;
  273     apr_datum_t skey;
  274     apr_datum_t val;
  275     apr_dbm_t *dbf;
  276     char temp[10];              /* Note: This means only values <=
  277                                  * 999,999,999 */
  278     int uval = 0;
  279     int ival = 0;
  280     int sval = 0;
  281     char *tkey;
  282     char *sname = (fc->orig_server->server_hostname
  283                    ? fc->orig_server->server_hostname
  284                    : "unknown");
  285     ftp_server_config *fsc =
  286     ftp_get_module_config(fc->orig_server->module_config);
  287 
  288     if (!ftp_lock)
  289         return 0;
  290 
  291     ftp_mutex_on();
  292     if ((rv = apr_dbm_open(&dbf, fsc->limitdbfile,
  293                         APR_DBM_RWCREATE, FTP_DB_FILE_MODE, fc->login_pool))
  294         != APR_SUCCESS) {
  295         ap_log_error(APLOG_MARK, APLOG_ERR, rv, fc->orig_server,
  296                "Cannot open FTPLimitDBFile file `%s' for logged out update",
  297                      fsc->limitdbfile);
  298         ftp_mutex_off();
  299         return rv;
  300     }
  301     /*
  302      * This is a safe cast, it's a lookup key
  303      */
  304     tkey = apr_psprintf(c->pool, "%s-%s", sname, fc->user);
  305     ukey.dptr = (char *) tkey;
  306     ukey.dsize = strlen(tkey);
  307     rv = apr_dbm_fetch(dbf, ukey, &val);        /* error for non-existant? */
  308     if (val.dptr != NULL && val.dsize > 0) {
  309         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  310         uval = atoi(temp);
  311     }
  312 
  313     tkey = apr_psprintf(c->pool, "%s-%s", sname, c->remote_ip);
  314     ikey.dptr = (char *) tkey;
  315     ikey.dsize = strlen(tkey);
  316     rv = apr_dbm_fetch(dbf, ikey, &val);        /* error for non-existant? */
  317     if (val.dptr != NULL && val.dsize > 0) {
  318         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  319         ival = atoi(temp);
  320     }
  321 
  322     tkey = apr_psprintf(c->pool, "%s-%s", sname, FTP_SERVER_LIMIT_KEY);
  323     skey.dptr = tkey;
  324     skey.dsize = strlen(tkey);
  325     rv = apr_dbm_fetch(dbf, skey, &val);        /* error for non-existant? */
  326     if (val.dptr != NULL && val.dsize > 0) {
  327         apr_cpystrn(temp, val.dptr, MYMIN(sizeof(temp), val.dsize + 1));
  328         sval = atoi(temp);
  329     }
  330     sval--;
  331     uval--;
  332     ival--;
  333     if (sval < 0)
  334         sval = 0;
  335     if (uval < 0)
  336         uval = 0;
  337     if (ival < 0)
  338         ival = 0;
  339 
  340     apr_snprintf(temp, sizeof(temp), "%d", uval);
  341     val.dptr = temp;
  342     val.dsize = strlen(temp);
  343     rv = apr_dbm_store(dbf, ukey, val);
  344 
  345     apr_snprintf(temp, sizeof(temp), "%d", ival);
  346     val.dptr = temp;
  347     val.dsize = strlen(temp);
  348     rv = apr_dbm_store(dbf, ikey, val);
  349 
  350     apr_snprintf(temp, sizeof(temp), "%d", sval);
  351     val.dptr = temp;
  352     val.dsize = strlen(temp);
  353     rv = apr_dbm_store(dbf, skey, val);
  354 
  355     apr_dbm_close(dbf);
  356 
  357     ftp_mutex_off();
  358 
  359     return 0;
  360 }