static void ngx_mail_throttle_user_failure_handler (mc_work_t *w)
{
    throttle_callback_t  *callback = w->ctx;
    ngx_str_t            *user = callback->user;
    ngx_mail_session_t   *s = callback->session;
    ngx_log_t            *log = callback->log;

    if (w->response_code == mcres_failure_normal) {
        //NOT_FOUND
        ngx_log_error(NGX_LOG_INFO, log, 0,
            "user throttle: no alias for user:%V",
            user);
        s->vlogin = 1;  /* avoid duplicate lookups for alias */
        ngx_mail_throttle_quser (callback->user, callback);

    } else if(w->response_code == mcres_failure_again) {
        mc_work_t nw;
        nw.ctx = callback;
        nw.request_code = mcreq_get;
        nw.response_code = mcres_unknown;
        nw.on_success = ngx_mail_throttle_user_success_handler;
        nw.on_failure = ngx_mail_throttle_user_failure_handler;
        ngx_log_error (NGX_LOG_NOTICE, callback->log, 0,
                "retry to lookup alias %V before user throttle", callback->user);
        ngx_memcache_post(&nw, *callback->key, *callback->pdu,
                            /* pool */ NULL, log);

    } else { /* mcres_failure_unavailable */
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "throttle allowing access from user %V because "
                "memcache service is unavailable when try to "
                "perform alias lookup", callback->user);
        callback->on_allow(callback);
    }
}
static void ngx_mail_throttle_ip_failure_handler (mc_work_t *w)
{
    throttle_callback_t  *callback = w->ctx;
    ngx_log_t            *log = callback->log;
    if (w->response_code == mcres_failure_normal) {
        /* increment failed, we must begin to add counter for this ip */
        ngx_log_debug1(NGX_LOG_DEBUG_MAIL, log, 0,
            "ip throttle:%V create counter", callback->ip);
        ngx_mail_throttle_ip_add (callback->ip, callback);

    } else if (w->response_code == mcres_failure_again) {
        mc_work_t nw; /* create a new work entry */
        nw.ctx = callback;
        nw.request_code = mcreq_incr;
        nw.response_code = mcres_unknown;
        nw.on_success = ngx_mail_throttle_ip_success_handler;
        nw.on_failure = ngx_mail_throttle_ip_failure_handler;
        ngx_log_error (NGX_LOG_NOTICE, log, 0,
                "retry to check ip throttle:%V", callback->ip);
        ngx_memcache_post(&nw, *callback->key, *callback->pdu,
                          /* pool */ NULL, log);

    } else { /* mcres_failure_unavailable */
        ngx_log_error (NGX_LOG_ERR, log, 0,
             "throttle allowing access from ip %V because of "
             "memcache service is unavailable when try to "
             "increment ip counter", callback->ip);
        callback->on_allow(callback);
    }
}
Ejemplo n.º 3
0
static void ngx_mail_throttle_quser_failure_handler (mc_work_t *w)
{
    throttle_callback_t *callback = w->ctx;
    ngx_log_t           *log = callback->log;
    ngx_flag_t           check_only = callback->check_only;

    if (w->response_code == mcres_failure_normal) {
        if (check_only) {
           ngx_log_error (NGX_LOG_INFO, log, 0,
                "user throttle:%V not found, allow due to check only",
                callback->user);
           callback->on_allow(callback);
       } else {
           ngx_log_debug1(NGX_LOG_DEBUG_MAIL, log, 0,
                "user throttle:%V add counter", callback->user);
           ngx_mail_throttle_user_add(callback->user, callback);
       }

    } else if (w->response_code == mcres_failure_again) {
        mc_work_t nw;
        nw.ctx = callback;
        if (check_only) {
            nw.request_code = mcreq_get;
        } else {
            nw.request_code = mcreq_incr;
        }
        nw.response_code = mcres_unknown;
        nw.on_success = ngx_mail_throttle_quser_success_handler;
        nw.on_failure = ngx_mail_throttle_quser_failure_handler;
        ngx_log_error (NGX_LOG_NOTICE, log, 0,
                "retry to check user throttle:%V", callback->user);
        ngx_memcache_post(&nw, *callback->key, *callback->value,
                            /* pool */ NULL, log);
        } else if(w->response_code == mcres_failure_input) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                       "throttle deny since the user name %V is invalid",
                       callback->user);
            callback->on_deny(callback);
        } else { /* mcres_failure_unavailable */
            if (check_only) {
                ngx_log_error (NGX_LOG_ERR, log, 0,
                    "throttle allowing access from user %V because "
                    "memcache service is unavailable when try to "
                    "get user counter", callback->user);
            } else {
                ngx_log_error (NGX_LOG_ERR, log, 0,
                    "throttle allowing access from user %V because "
                    "memcache service is unavailable when try to "
                    "increment user counter", callback->user);
            }
        callback->on_allow(callback);
    }
}
/* memcache error handler (connection error or memory allocation error) */
static void ngx_mail_throttle_user_add_failure_handler (mc_work_t *w)
{
    throttle_callback_t  *callback = w->ctx;
    ngx_log_t            *log = callback->log;

    if (w->response_code == mcres_failure_normal) {
        /* Counter creation failed because of getting "NOT_STORED". This could
         * occur when more than one processes try to login and post "incr"
         * and all get "NOT_FOUND", and then try to add new counter. One of
         * them will get "STORED" and others will reach here. In some other
         * extreme cases, such as the ttl is very short, or some mis-handling
         * of memcache, this case may also happen. Considering the little
         * probability and the endurable inaccuracy, just ignore it.
         */
        ngx_log_error (NGX_LOG_NOTICE, log, 0,
            "allowing user %V login because unable to create the "
            "user counter", callback->user);
        callback->on_allow(callback);

    } else if (w->response_code == mcres_failure_again) {
        mc_work_t nw;
        nw.ctx = callback;
        nw.request_code = mcreq_add;
        nw.response_code = mcres_unknown;
        nw.on_success = ngx_mail_throttle_user_add_success_handler;
        nw.on_failure = ngx_mail_throttle_user_add_failure_handler;
        ngx_log_error (NGX_LOG_NOTICE, log, 0,
                "retry to check user throttle:%V", callback->user);
        ngx_memcache_post(&nw, *callback->key, *callback->pdu,
                            /* pool */ NULL, log);
    } else {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "throttle allowing access from ip %V because "
            "memcache service is unavailable when try to "
            "create user counter", callback->user);
        callback->on_allow(callback);
    }
}
/* add a throttle counter for a user, here user might be an alias or a fqn */
static void ngx_mail_throttle_user_add
    (ngx_str_t *user, throttle_callback_t *callback)
{
    ngx_pool_t             *pool    = callback->pool;
    ngx_log_t              *log     = callback->log;
    ngx_mail_session_t     *s       = callback->session;
    ngx_mail_throttle_srv_conf_t *tscf;
    mc_work_t               w;
    size_t                  l;
    ngx_str_t               k;
    ngx_str_t              *pdu, *key;
    u_char                 *p;
    ngx_uint_t              ttl;
    size_t                  ttld;

    ngx_log_error (NGX_LOG_INFO, log, 0, "create a throttle counter for user %V", user);
    w.ctx = callback;
    w.request_code = mcreq_add;
    w.response_code = mcres_unknown;
    w.on_success = ngx_mail_throttle_user_add_success_handler;
    w.on_failure = ngx_mail_throttle_user_add_failure_handler;

    k = ngx_memcache_get_user_throttle_key(pool, log, *user);
    if (k.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (generate key for add)", user);
        callback->on_allow(callback);
        return;
    }

    key = ngx_pstrcpy (pool, &k);
    if (key == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (deep copy key for add)", user);
        callback->on_allow(callback);
        return;
    }

    tscf = ngx_mail_get_module_srv_conf (s, ngx_mail_throttle_module);
    ttl = tscf->mail_login_user_ttl / 1000;              /* msec => sec */
    if(tscf->mail_login_user_ttl % 1000 > 0) { ++ttl; }  /* round upward */
    ttld = serialize_number(NULL, ttl);

    l = sizeof("add ") - 1 +
        k.len +
        sizeof(" ") - 1 +
        sizeof("0 ") - 1 +
        ttld + sizeof(" ") - 1 +
        sizeof("1") - 1 + sizeof(CRLF) - 1 +
        1 + sizeof(CRLF) - 1;

    pdu = ngx_palloc (pool, sizeof(ngx_str_t));
    if (pdu == NULL) {
       ngx_log_error (NGX_LOG_ERR, log, 0,
               "allowing user %V login because of internal error"
               "in user throttle control (alloc mem for add pdu)", user);
       callback->on_allow(callback);
       return;
   }

    pdu->data = ngx_palloc(pool, l);
    if (pdu->data == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (alloc mem for add pdu data)", user);
        callback->on_allow(callback);
        return;
    }

    p = pdu->data;
    p = ngx_cpymem(p, "add ", sizeof("add ") - 1);
    p = ngx_cpymem(p, k.data, k.len);
    *p++ = ' ';
    *p++ = '0';
    *p++ = ' ';
    p+= serialize_number(p, ttl);
    *p++ = ' ';
    *p++ = '1';
    *p++ = CR;
    *p++ = LF;
    *p++ = '1';
    *p++ = CR;
    *p++ = LF;
    pdu->len = p - pdu->data;

    callback->key = key;
    callback->pdu = pdu;
    callback->user = user;

    ngx_memcache_post(&w, *key, *pdu,/* pool */ NULL, log);
    return;
}
/* same as ngx_mail_throttle_user, but works on a fully qualified user name */
static void ngx_mail_throttle_quser (ngx_str_t * quser, throttle_callback_t *callback)
{
    ngx_log_t           *log;
    ngx_pool_t          *pool;
    mc_work_t            w;
    ngx_str_t            k;
    ngx_str_t           *pdu, *key;
    size_t               l;
    u_char              *p;
    ngx_mail_session_t  *s;
    ngx_flag_t           check_only;

    pool = callback->pool;
    log = callback->log;
    s = callback->session;
    check_only = callback->check_only;

    k = ngx_memcache_get_user_throttle_key (pool, log, *quser);
    if (k.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (generate key for get)", quser);
        callback->on_allow(callback);
        return;
    }

    key = ngx_pstrcpy (pool, &k);
    if (key == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (deep copy check user key)", quser);
        callback->on_allow(callback);
    }

    if (check_only == 0)
    {   // try to increment the counter for this user
        ngx_log_error (NGX_LOG_INFO, log, 0, "check user throttle:%V", quser);
        w.ctx = callback;
        w.request_code = mcreq_incr;
        w.response_code = mcres_unknown;
        w.on_success = ngx_mail_throttle_quser_success_handler;
        w.on_failure = ngx_mail_throttle_quser_failure_handler;

        l = sizeof("incr ") - 1 +
            k.len +
            sizeof(" ") - 1 +
            sizeof("1") - 1 +
            sizeof(CRLF) - 1;
        pdu = ngx_palloc (pool, sizeof(ngx_str_t));
        if (pdu == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing user %V login because of internal error"
                    "in ip throttle control (alloc mem for incr pdu)", quser);
            callback->on_allow(callback);
            return;
        }
        pdu->data = ngx_palloc (pool, l);
        if (pdu->data == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing user %V login because of internal error "
                    "in user throttle control (alloc mem for incr pdu data)", quser);
            callback->on_allow(callback);
            return;
        }

        p = pdu->data;
        p = ngx_cpymem(p, "incr ", sizeof("incr ") - 1);
        p = ngx_cpymem(p, k.data, k.len);
        *p++ = ' ';
        *p++ = '1';
        *p++ = CR;
        *p++ = LF;
        pdu->len = p - pdu->data;
    }
    else
    {   // just check the counter
        ngx_log_error (NGX_LOG_INFO, log, 0, "check user throttle:%V, check only", quser);
        w.ctx = callback;
        w.request_code = mcreq_get;
        w.response_code = mcres_unknown;
        w.on_success = ngx_mail_throttle_quser_success_handler;
        w.on_failure = ngx_mail_throttle_quser_failure_handler;

        l = sizeof("get ") - 1 +
            k.len +
            sizeof(CRLF) - 1;

        pdu = ngx_palloc (pool, sizeof(ngx_str_t));
        if (pdu == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing ip %V login because of internal error"
                    "in user throttle control (alloc mem for get pdu)", quser);
            callback->on_allow(callback);
            return;
        }
        pdu->data = ngx_palloc (pool, l);
        if (pdu->data == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing user %V login because of internal error "
                    "in user throttle control (alloc mem for get pdu data)", quser);
            callback->on_allow(callback);
            return;
        }

        p = pdu->data;
        p = ngx_cpymem(p, "get ", sizeof("get ") - 1);
        p = ngx_cpymem(p, k.data, k.len);
        *p++ = CR;
        *p++ = LF;
        pdu->len = p - pdu->data;
    }

    callback->key = key;
    callback->pdu = pdu;
    callback->user = quser;

    ngx_memcache_post(&w, *key, *pdu,/* pool */ NULL, log);
}
/* check whether the client ip should be allowed to proceed, or whether
   the connection should be throttled
 */
void ngx_mail_throttle_user (ngx_str_t user, throttle_callback_t *callback)
{
    ngx_pool_t          *pool;
    ngx_log_t           *log;
    ngx_connection_t    *c;
    ngx_str_t           *cusr, *pdu;
    ngx_mail_session_t  *s;
    mc_work_t            w;
    size_t               l;
    u_char              *p;
    ngx_str_t            proxyip;

    pool = callback->pool;
    log = callback->log;
    c = callback->connection;
    s = callback->session;

    ngx_log_error (NGX_LOG_INFO, log, 0,
        "user throttle: lookup alias, user:%V", &user);

    /* save a copy of the user name */
    cusr = ngx_pstrcpy(pool, &user);
    if (cusr == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (deep copy user for incr)", &user);
        callback->on_allow(callback);
        return;
    }

    if (s->vlogin) {
        /* user alias has already been looked up */
        ngx_log_debug1 (NGX_LOG_DEBUG_MAIL, log, 0,
            "user throttle: skip alias lookup, user:%V", &user);
        ngx_mail_throttle_quser(cusr, callback);
        return;
    }

    w.ctx = callback;
    w.request_code = mcreq_get;
    w.response_code = mcres_unknown;
    w.on_success = ngx_mail_throttle_user_success_handler;
    w.on_failure = ngx_mail_throttle_user_failure_handler;

    /* GSSAPI workaround: don't lookup aliases for GSSAPI */
    if (s->auth_method == NGX_MAIL_AUTH_GSSAPI) {
        ngx_log_error(NGX_LOG_NOTICE, log, 0,
            "not looking up cached aliases for auth=gssapi");
        callback->on_deny(callback);
        return;
    }

    /* first stringify the proxy-ip address */
    proxyip = ngx_mail_get_local_addr4 (pool, c->fd);

    s->key_alias = ngx_memcache_get_alias_key(
            pool,
            log,
            *cusr,
            proxyip
        );

    if (s->key_alias.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (create alias key)", &user);
        callback->on_allow(callback);
        return;
    }

    l = sizeof("get ") - 1 +
        s->key_alias.len +
        sizeof(CRLF) - 1;

    pdu = ngx_palloc(pool, sizeof(ngx_str_t));
    if (pdu == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error"
                "in ip throttle control (alloc mem for get alias pdu)", &user);
        callback->on_allow(callback);
        return;
    }
    pdu->data = ngx_palloc(pool, l);
    if (pdu->data == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (alloc mem for get alias pdu data)", &user);
        callback->on_allow(callback);
        return;
    }

    p = ngx_cpymem(pdu->data, "get ", sizeof("get ") - 1);
    p = ngx_cpymem(p, s->key_alias.data, s->key_alias.len);
    *p++ = CR;
    *p++ = LF;
    pdu->len = p - pdu->data;

    callback->key = &s->key_alias;
    callback->pdu = pdu;
    callback->user = cusr;

    ngx_memcache_post(&w, s->key_alias, *pdu,/* pool */ NULL, log);
}
/* check whether the client ip should be allowed to proceed, or whether
   the connection should be throttled
 */
void ngx_mail_throttle_ip (ngx_str_t ip, throttle_callback_t *callback)
{
    ngx_log_t       *log;
    ngx_pool_t      *pool;
    mc_work_t        w;
    ngx_str_t        k;
    ngx_str_t       *eip, *key, *pdu;
    size_t           l;
    u_char          *p;
    ngx_mail_session_t  *s;

    pool = callback->pool;
    log = callback->log;
    s = callback->session;

    ngx_log_error (NGX_LOG_INFO, log, 0, "check ip throttle:%V", &ip);

    w.ctx = callback;
    w.request_code = mcreq_incr;
    w.response_code = mcres_unknown;
    w.on_success = ngx_mail_throttle_ip_success_handler;
    w.on_failure = ngx_mail_throttle_ip_failure_handler;

    k = ngx_memcache_get_ip_throttle_key(pool, log, ip);

    if (k.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (generate key for incr)", &ip);
        callback->on_allow(callback);
        return;
    }

    key = ngx_pstrcpy (pool, &k);
    if (key == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (deep copy key for incr)", &ip);
        callback->on_allow(callback);
    }

    l = sizeof("incr ") - 1 +
        k.len +
        sizeof(" ") - 1 +
        sizeof("1") - 1 +
        sizeof(CRLF) - 1;

    pdu = ngx_palloc (pool, sizeof(ngx_str_t));
    if (pdu == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (alloc mem for incr pdu)", &ip);
        callback->on_allow(callback);
        return;
    }

    pdu->data = ngx_palloc (pool, l);
    if (pdu->data == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (alloc mem for incr pdu data)", &ip);
        callback->on_allow(callback);
        return;
    }

    /* make a copy of the input IP address for callback reference */
    eip = ngx_pstrcpy (pool, &ip);
    if (eip == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (deep copy ip for incr)", &ip);
        callback->on_allow(callback);
        return;
    }

    p = pdu->data;
    p = ngx_cpymem(p, "incr ", sizeof("incr ") - 1);
    p = ngx_cpymem(p, k.data, k.len);
    *p++ = ' ';
    *p++ = '1';
    *p++ = CR;
    *p++ = LF;
    pdu->len = p - pdu->data;

    callback->ip = eip;
    callback->pdu = pdu;
    callback->key = key;

    ngx_memcache_post(&w, *key, *pdu, /* pool */ NULL, log);
}
Ejemplo n.º 9
0
/* same as ngx_mail_throttle_user, but works on a fully qualified user name */
static void ngx_mail_throttle_quser (ngx_str_t * quser, throttle_callback_t *callback)
{
    ngx_log_t           *log;
    ngx_pool_t          *pool;
    mc_work_t            w;
    ngx_str_t            k;
    ngx_str_t           *value, *key;
    ngx_flag_t           check_only;

    pool = callback->pool;
    log = callback->log;
    check_only = callback->check_only;

    k = ngx_mail_throttle_get_user_throttle_key(pool, log, *quser);
    if (k.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (generate key for get)", quser);
        callback->on_allow(callback);
        return;
    }

    key = ngx_pstrcpy (pool, &k);
    if (key == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
            "allowing user %V login because of internal error "
            "in user throttle control (deep copy check user key)", quser);
        callback->on_allow(callback);
    }

    if (check_only == 0)
    {   // try to increment the counter for this user
        ngx_log_error (NGX_LOG_INFO, log, 0, "check user throttle:%V", quser);
        w.ctx = callback;
        w.request_code = mcreq_incr;
        w.response_code = mcres_unknown;
        w.on_success = ngx_mail_throttle_quser_success_handler;
        w.on_failure = ngx_mail_throttle_quser_failure_handler;

        value = ngx_palloc (pool, sizeof(ngx_str_t));
        if (value == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing user %V login because of internal error"
                    "in ip throttle control (alloc mem for incr value)", quser);
            callback->on_allow(callback);
            return;
        }

        ngx_str_set(value, "1");
    }
    else
    {   // just check the counter
        ngx_log_error (NGX_LOG_INFO, log, 0, "check user throttle:%V, check only", quser);
        w.ctx = callback;
        w.request_code = mcreq_get;
        w.response_code = mcres_unknown;
        w.on_success = ngx_mail_throttle_quser_success_handler;
        w.on_failure = ngx_mail_throttle_quser_failure_handler;

        value = ngx_palloc (pool, sizeof(ngx_str_t));
        if (value == NULL) {
            ngx_log_error (NGX_LOG_ERR, log, 0,
                    "allowing ip %V login because of internal error"
                    "in user throttle control (alloc mem for get value)", quser);
            callback->on_allow(callback);
            return;
        }

        ngx_str_null (value);
    }

    callback->key = key;
    callback->value = value;
    callback->user = quser;

    ngx_memcache_post(&w, *key, *value,/* pool */ NULL, log);
}
Ejemplo n.º 10
0
/* check whether the client user name should be allowed to proceed, or whether
   the connection should be throttled
 */
void ngx_mail_throttle_user (ngx_str_t user, throttle_callback_t *callback)
{
    ngx_pool_t          *pool;
    ngx_log_t           *log;
    ngx_connection_t    *c;
    ngx_str_t           *cusr;
    ngx_mail_session_t  *s;
    mc_work_t            w;
    ngx_str_t            proxyip;
    ngx_str_t           *dummy_value;

    pool = callback->pool;
    log = callback->log;
    c = callback->connection;
    s = callback->session;

    ngx_log_debug1 (NGX_LOG_DEBUG_MAIL, log, 0,
        "user throttle: lookup alias, user:%V", &user);

    /* save a copy of the user name */
    cusr = ngx_pstrcpy(pool, &user);
    if (cusr == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (deep copy user for incr)", &user);
        callback->on_allow(callback);
        return;
    }

    if (s->vlogin) {
        /* user alias has already been looked up */
        ngx_log_debug1 (NGX_LOG_DEBUG_MAIL, log, 0,
            "user throttle: skip alias lookup, user:%V", &user);
        ngx_mail_throttle_quser(cusr, callback);
        return;
    }

    w.ctx = callback;
    w.request_code = mcreq_get;
    w.response_code = mcres_unknown;
    w.on_success = ngx_mail_throttle_user_success_handler;
    w.on_failure = ngx_mail_throttle_user_failure_handler;

    /* GSSAPI workaround: don't lookup aliases for GSSAPI */
    if (s->auth_method == NGX_MAIL_AUTH_GSSAPI) {
        ngx_log_error(NGX_LOG_INFO, log, 0,
            "not looking up cached aliases for auth=gssapi");
        ngx_mail_throttle_quser(cusr, callback);
        return;
    }

    /* first stringify the proxy-ip address */
    proxyip = ngx_mail_get_socket_local_addr_str (pool, c->fd);

    s->key_alias = ngx_zm_lookup_get_mail_alias_key(
            pool,
            log,
            *cusr,
            proxyip
        );

    if (s->key_alias.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing user %V login because of internal error "
                "in user throttle control (create alias key)", &user);
        callback->on_allow(callback);
        return;
    }

    dummy_value = ngx_palloc (pool, sizeof (ngx_str_t));

    ngx_str_null (dummy_value);

    callback->key = &s->key_alias;
    callback->value = dummy_value;
    callback->user = cusr;

    ngx_memcache_post(&w, s->key_alias, *dummy_value,/* pool */ NULL, log);
}
Ejemplo n.º 11
0
/* check whether the client ip should be allowed to proceed, or whether
   the connection should be throttled
 */
void ngx_mail_throttle_ip (ngx_str_t ip, throttle_callback_t *callback)
{
    ngx_log_t       *log;
    ngx_pool_t      *pool;
    mc_work_t        w;
    ngx_str_t        k;
    ngx_str_t       *value, *eip, *key;

    pool = callback->pool;
    log = callback->log;

    ngx_log_error (NGX_LOG_INFO, log, 0, "check ip throttle:[%V]", &ip);

    w.ctx = callback;
    w.request_code = mcreq_incr;
    w.response_code = mcres_unknown;
    w.on_success = ngx_mail_throttle_ip_success_handler;
    w.on_failure = ngx_mail_throttle_ip_failure_handler;

    k = ngx_mail_throttle_get_ip_throttle_key(pool, log, ip);

    if (k.len == 0) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (generate key for incr)", &ip);
        callback->on_allow(callback);
        return;
    }

    key = ngx_pstrcpy (pool, &k);
    if (key == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (deep copy key for incr)", &ip);
        callback->on_allow(callback);
    }

    value = ngx_palloc (pool, sizeof(ngx_str_t));
    if (value == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (alloc mem for incr value)", &ip);
        callback->on_allow(callback);
        return;
    }

    ngx_str_set(value, "1");

    /* make a copy of the input IP address for callback reference */
    eip = ngx_pstrcpy (pool, &ip);
    if (eip == NULL) {
        ngx_log_error (NGX_LOG_ERR, log, 0,
                "allowing ip %V login because of internal error"
                "in ip throttle control (deep copy ip for incr)", &ip);
        callback->on_allow(callback);
        return;
    }

    callback->ip = eip;
    callback->value = value;
    callback->key = key;

    ngx_memcache_post(&w, *key, *value, /* pool */ NULL, log);
}