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

📄 c2s.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "c2s.h"static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {    sess_t sess = (sess_t) arg;    sx_buf_t buf = (sx_buf_t) data;    int rlen, len, ns, elem, attr, i, r;    sx_error_t *sxe;    nad_t nad;    char root[9];    switch(e) {        case event_WANT_READ:            log_debug(ZONE, "want read");            mio_read(sess->c2s->mio, sess->fd);            break;        case event_WANT_WRITE:            log_debug(ZONE, "want write");            mio_write(sess->c2s->mio, sess->fd);            break;        case event_READ:            log_debug(ZONE, "reading from %d", sess->fd);            /* check rate limits */            if(sess->rate != NULL) {                if(rate_check(sess->rate) == 0) {                    /* inform the app if we haven't already */                    if(!sess->rate_log) {                        if(s->state >= state_STREAM && sess->jid != NULL)                            log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] is being byte rate limited", sess->fd, sess->jid);                        else                            log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] is being byte rate limited", sess->fd, sess->ip, sess->port);                        sess->rate_log = 1;                    }                    log_debug(ZONE, "%d is throttled, delaying read", sess->fd);                    buf->len = 0;                    return 0;                }                /* find out how much we can have */                rlen = rate_left(sess->rate);                if(rlen > buf->len)                    rlen = buf->len;            }            /* do the read */            len = recv(sess->fd, buf->data, buf->len, 0);            if(len < 0) {                if(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN) {                    buf->len = 0;                    return 0;                }                if(s->state >= state_STREAM && sess->jid != NULL)                    log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] read error: %s (%d)", sess->fd, jid_full(sess->jid), strerror(errno), errno);                else                    log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", sess->fd, sess->ip, sess->port, strerror(errno), errno);                sx_kill(s);                                return -1;            }            else if(len == 0) {                /* they went away */                sx_kill(s);                return -1;            }            log_debug(ZONE, "read %d bytes", len);            buf->len = len;            return len;        case event_WRITE:            log_debug(ZONE, "writing to %d", sess->fd);            len = send(sess->fd, buf->data, buf->len, 0);            if(len >= 0) {                log_debug(ZONE, "%d bytes written", len);                return len;            }            if(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN)                return 0;                        if(s->state >= state_OPEN && sess->jid != NULL)                log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] write error: %s (%d)", sess->fd, jid_full(sess->jid), strerror(errno), errno);            else                log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s. port=%d] write error: %s (%d)", sess->fd, sess->ip, sess->port, strerror(errno), errno);                    sx_kill(s);                    return -1;        case event_ERROR:            sxe = (sx_error_t *) data;            if(sess->jid != NULL)                log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] error: %s (%s)", sess->fd, jid_full(sess->jid), sxe->generic, sxe->specific);            else                log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", sess->fd, sess->ip, sess->port, sxe->generic, sxe->specific);            break;                    case event_STREAM:            if(s->req_to == NULL) {                log_debug(ZONE, "no stream to provided, closing");                sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header");                sx_close(s);                return 0;            }            /* setup the realm */            sess->realm = xhash_get(sess->c2s->realms, s->req_to);            if(sess->realm == NULL) {                log_debug(ZONE, "no service available for requested domain '%s'", s->req_to);                sx_error(s, stream_err_HOST_UNKNOWN, "service requested for unknown domain");                sx_close(s);                                return 0;            }            if(xhash_get(sess->c2s->sm_avail, s->req_to) == NULL) {                log_debug(ZONE, "sm for domain '%s' is not online", s->req_to);                sx_error(s, stream_err_HOST_GONE, "session manager for requested domain is not available");                sx_close(s);                return 0;            }            break;        case event_PACKET:            nad = (nad_t) data;            /* we only want (message|presence|iq) in jabber:client, everything else gets dropped */            snprintf(root, 9, "%.*s", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));            if(NAD_ENS(nad, 0) != nad_find_namespace(nad, 0, uri_CLIENT, NULL) ||               (strcmp(root, "message") != 0 && strcmp(root, "presence") != 0 && strcmp(root, "iq") != 0)) {                nad_free(nad);                return 0;            }            /* pre-session requests */            if(!sess->active && sess->sasl_authd && sess->result == NULL && strcmp(root, "iq") == 0 && nad_find_attr(nad, 0, -1, "type", "set") >= 0) {                /* resource bind */                if(!sess->bound && (ns = nad_find_scoped_namespace(nad, uri_BIND, NULL)) >= 0 && (elem = nad_find_elem(nad, 0, ns, "bind", 1)) >= 0) {                    sess->jid = jid_new(sess->c2s->pc, sess->s->auth_id, 0);                    /* get the resource */                    elem = nad_find_elem(nad, elem, ns, "resource", 1);                    /* user-specified resource */                    if(elem >= 0) {                        if(NAD_CDATA_L(nad, elem) == 0) {                            log_debug(ZONE, "no resource specified on bind");                            sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST));                            return 0;                        }                        snprintf(sess->jid->resource, sizeof(sess->jid->resource), "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));                        /* prep the resource */                        if(jid_prep(sess->jid) != 0) {                            jid_free(sess->jid);                            sess->jid = NULL;                            sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST));                                                        return 0;                        }                        /* !!! xmpp-core-19 requires that the resource be unused, and that an                         *     error be returned if its not. this is hard for us todo, and                         *     might not be the right thing anyway (it basically gets rid                         *     of the session replacement functionality, though that is not                         *     as important now that resources can be generated). clarification                         *     sought from the xmppwg */                    }                    /* generated resource */                    else {                        for(i = 0; i < 256; i++) {                            r = (int) (36.0 * rand() / RAND_MAX);                            sess->jid->resource[i] = (r >= 0 && r <= 0) ? (r + 48) : (r + 87);                        }                        shahash_r(sess->jid->resource, sess->jid->resource);                        jid_prep(sess->jid);                    }                    log_write(sess->c2s->log, LOG_NOTICE, "[%d] bound: jid=%s", sess->s->tag, jid_full(sess->jid));                    sess->bound = 1;                    sess->result = nad_new(sess->s->nad_cache);                    ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);                    nad_append_elem(sess->result, ns, "iq", 0);                    nad_set_attr(sess->result, 0, -1, "type", "result", 6);                    attr = nad_find_attr(nad, 0, -1, "id", NULL);                    if(attr >= 0)                        nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));                    ns = nad_add_namespace(sess->result, uri_BIND, NULL);                    nad_append_elem(sess->result, ns, "bind", 1);                    nad_append_elem(sess->result, ns, "jid", 2);                    nad_append_cdata(sess->result, jid_full(sess->jid), strlen(jid_full(sess->jid)), 3);                    sx_nad_write(sess->s, stanza_tofrom(sess->result, 0));                    sess->result = NULL;                    nad_free(nad);                    return 0;                }                /* new-style session request */                else if(sess->bound && (ns = nad_find_scoped_namespace(nad, uri_XSESSION, NULL)) >= 0 && (elem = nad_find_elem(nad, 0, ns, "session", 1)) >= 0) {                    /* our local id */                    sprintf(sess->c2s_id, "%d", sess->s->tag);                    log_write(sess->c2s->log, LOG_NOTICE, "[%d] requesting session: jid=%s", sess->s->tag, jid_full(sess->jid));                    /* build a result packet, we'll send this back to the client after we have a session for them */                    sess->result = nad_new(sess->s->nad_cache);                    ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);                    nad_append_elem(sess->result, ns, "iq", 0);                    nad_set_attr(sess->result, 0, -1, "type", "result", 6);                    attr = nad_find_attr(nad, 0, -1, "id", NULL);                    if(attr >= 0)                        nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));                    /* start a session with the sm */                    sm_start(sess);                    /* finished with the nad */                    nad_free(nad);                    /* handled */                    return 0;                }                log_debug(ZONE, "unrecognised pre-session packet, bye");                sx_error(s, stream_err_NOT_AUTHORIZED, NULL);                sx_close(s);                nad_free(nad);                return 0;            }#ifdef HAVE_SSL            /* drop packets if they have to starttls and they haven't */            if((sess->s->flags & SX_SSL_STARTTLS_REQUIRE) && sess->s->ssf == 0) {                nad_free(nad);                return 0;            }#endif            /* handle iq:auth packets */            if(authreg_process(sess->c2s, sess, nad) == 0)                return 0;            /* drop it if no session */            if(!sess->active) {                log_debug(ZONE, "pre-session packet, bye");                sx_error(s, stream_err_NOT_AUTHORIZED, NULL);                sx_close(s);                nad_free(nad);                return 0;            }            /* pass it on to the session manager */            sm_packet(sess, nad);            break;                case event_OPEN:            /* only send a result and bring us online if this wasn't a sasl auth */            if(strlen(s->auth_method) < 4 || strncmp("SASL", s->auth_method, 4) != 0) {                /* return the auth result to the client */                sx_nad_write(s, sess->result);                sess->result = NULL;                /* we're good to go */                sess->active = 1;            }            /* they sasl auth'd, so we only want the new-style session start */            else {                log_write(sess->c2s->log, LOG_NOTICE, "[%d] SASL authentication succeeded: mechanism=%s; authzid=%s", sess->s->tag, &sess->s->auth_method[5], sess->s->auth_id);                sess->sasl_authd = 1;            }            break;        case event_CLOSED:            mio_close(sess->c2s->mio, sess->fd);            break;    }    return 0;}static int _c2s_client_accept_check(c2s_t c2s, int fd, char *ip) {    rate_t rt;    if(access_check(c2s->access, ip) == 0) {        log_write(c2s->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd, ip);        return 1;    }    if(c2s->conn_rate_total != 0) {

⌨️ 快捷键说明

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