示例#1
0
文件: main.c 项目: 6wei/jabberd2
static void _sm_hosts_expand(sm_t sm)
{
    config_elem_t elem;
    char id[1024];
    int i;

    elem = config_get(sm->config, "local.id");
    if(!elem) {
        /* use SM id */
        xhash_put(sm->hosts, pstrdup(xhash_pool(sm->hosts), sm->id), sm);
        log_write(sm->log, LOG_NOTICE, "id: %s", sm->id);
        return;
    }

    for(i = 0; i < elem->nvalues; i++) {
        /* stringprep ids (domain names) so that they are in canonical form */
        strncpy(id, elem->values[i], 1024);
        id[1023] = '\0';
        if (stringprep_nameprep(id, 1024) != 0) {
            log_write(sm->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
            exit(1);
        }

        /* insert into vHosts xhash */
        xhash_put(sm->hosts, pstrdup(xhash_pool(sm->hosts), id), sm);

        log_write(sm->log, LOG_NOTICE, "[%s] configured", id);
    }
}
示例#2
0
/** register a new global ns */
int sm_register_ns(sm_t sm, const char *uri) {
    int ns_idx;

    ns_idx = (int) (long) xhash_get(sm->xmlns, uri);
    if (ns_idx == 0) {
        ns_idx = xhash_count(sm->xmlns) + 2;
        xhash_put(sm->xmlns, pstrdup(xhash_pool(sm->xmlns), uri), (void *) (long) ns_idx);
    }
    xhash_put(sm->xmlns_refcount, uri, (void *) ((long) xhash_get(sm->xmlns_refcount, uri) + 1));

    return ns_idx;
}
示例#3
0
文件: router.c 项目: 6wei/jabberd2
static int _router_accept_check(router_t r, mio_fd_t fd, const char *ip) {
    rate_t rt;

    if(access_check(r->access, ip) == 0) {
        log_write(r->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd->fd, ip);
        return 1;
    }

    if(r->conn_rate_total != 0) {
        rt = (rate_t) xhash_get(r->conn_rates, ip);
        if(rt == NULL) {
            rt = rate_new(r->conn_rate_total, r->conn_rate_seconds, r->conn_rate_wait);
            xhash_put(r->conn_rates, pstrdup(xhash_pool(r->conn_rates), ip), (void *) rt);
        }

        if(rate_check(rt) == 0) {
            log_write(r->log, LOG_NOTICE, "[%d] [%s] is being rate limited", fd->fd, ip);
            return 1;
        }

        rate_add(rt, 1);
    }

    return 0;
}
示例#4
0
文件: aci.c 项目: zipo/zipo
xht aci_load(router_t r) {
    xht aci;
    int aelem, uelem, attr;
    char type[33];
    aci_user_t list_head, list_tail, user;

    log_debug(ZONE, "loading aci");

    aci = xhash_new(51);

    if((aelem = nad_find_elem(r->config->nad, 0, -1, "aci", 1)) < 0)
        return aci;

    aelem = nad_find_elem(r->config->nad, aelem, -1, "acl", 1);
    while(aelem >= 0) {
        if((attr = nad_find_attr(r->config->nad, aelem, -1, "type", NULL)) < 0) {
            aelem = nad_find_elem(r->config->nad, aelem, -1, "acl", 0);
            continue;
        }

        list_head = NULL;
        list_tail = NULL;

        snprintf(type, 33, "%.*s", NAD_AVAL_L(r->config->nad, attr), NAD_AVAL(r->config->nad, attr));

        log_debug(ZONE, "building list for '%s'", type);

        uelem = nad_find_elem(r->config->nad, aelem, -1, "user", 1);
        while(uelem >= 0) {
            if(NAD_CDATA_L(r->config->nad, uelem) > 0) {
                user = (aci_user_t) calloc(1, sizeof(struct aci_user_st));

                user->name = (char *) malloc(sizeof(char) * (NAD_CDATA_L(r->config->nad, uelem) + 1));
                sprintf(user->name, "%.*s", NAD_CDATA_L(r->config->nad, uelem), NAD_CDATA(r->config->nad, uelem));

                if(list_tail != NULL) {
                   list_tail->next = user;
                   list_tail = user;
                }

                /* record the head of the list */
                if(list_head == NULL) {
                   list_head = user;
                   list_tail = user;
                }
                
                log_debug(ZONE, "added '%s'", user->name);
            }

            uelem = nad_find_elem(r->config->nad, uelem, -1, "user", 0);
        }

        if(list_head != NULL)
            xhash_put(aci, pstrdup(xhash_pool(aci), type), (void *) list_head);

        aelem = nad_find_elem(r->config->nad, aelem, -1, "acl", 0);
    }

    return aci;
}
示例#5
0
文件: user.c 项目: 6wei/jabberd2
/** fetch user data */
user_t user_load(sm_t sm, jid_t jid) {
    user_t user;

    /* already loaded */
    user = xhash_get(sm->users, jid_user(jid));
    if(user != NULL) {
        log_debug(ZONE, "returning previously-created user data for %s", jid_user(jid));
        return user;
    }

    /* make a new one */
    user = _user_alloc(sm, jid);

    /* get modules to setup */
    if(mm_user_load(sm->mm, user) != 0) {
        log_debug(ZONE, "modules failed user load for %s", jid_user(jid));
        pool_free(user->p);
        return NULL;
    }

    /* save them for later */
    xhash_put(sm->users, jid_user(user->jid), (void *) user);

    log_debug(ZONE, "loaded user data for %s", jid_user(jid));

    return user;
}
示例#6
0
/*
 * get group's descriptive name by it's text id
 * returned value needs to be freed by caller
 */
static const char *_roster_publish_get_group_name(sm_t sm, roster_publish_t rp, const char *groupid)
{
    os_t os;
    os_object_t o;
    char *str;
    char *group;

#ifndef NO_SM_CACHE
    _roster_publish_group_cache_t group_cached;
#endif

    if(!groupid) return groupid;

#ifndef NO_SM_CACHE
    /* check for remembered group value in cache */
    if( rp->group_cache_ttl ) {
        if( rp->group_cache ) {
            group_cached = xhash_get(rp->group_cache, groupid);
            if( group_cached != NULL ) {
                if( (time(NULL) - group_cached->time) >= rp->group_cache_ttl ) {
                    log_debug(ZONE,"group cache: expiring cached value for %s",groupid);
                    xhash_zap(rp->group_cache, groupid);
                    free(group_cached);
                } else {
                    log_debug(ZONE,"group cache: returning cached value for %s",groupid);
                    return strdup(group_cached->groupname);
                }
            }
        } else {
            log_debug(ZONE,"group cache: creating cache");
            rp->group_cache = xhash_new(401);
        }
    }
#endif

    if(storage_get(sm->st, "published-roster-groups", groupid, NULL, &os) == st_SUCCESS && os_iter_first(os)) {
        o = os_iter_object(os);
        if( os_object_get_str(os, o, "groupname", &str) && str ) {
            group=strdup(str);
        } else {
            group=NULL;
        }
        os_free(os);
#ifndef NO_SM_CACHE
        if( rp->group_cache_ttl && group ) {
            log_debug(ZONE,"group cache: updating cache value for %s",groupid);
            group_cached = calloc(1, sizeof(struct _roster_publish_group_cache_st));
            group_cached->time = time(NULL);
            group_cached->groupid = strdup(groupid);
            group_cached->groupname = strdup(group);
            xhash_put(rp->group_cache, group_cached->groupid, group_cached);
        }
#endif
        return group;
    } else {
        return NULL;
    }
}
示例#7
0
/** unregister a global ns */
void sm_unregister_ns(sm_t sm, const char *uri) {
    int refcount = (int) (long) xhash_get(sm->xmlns_refcount, uri);
    if (refcount == 1) {
        xhash_zap(sm->xmlns, uri);
        xhash_zap(sm->xmlns_refcount, uri);
    } else if (refcount > 1) {
        xhash_put(sm->xmlns_refcount, uri, (void *) ((long) xhash_get(sm->xmlns_refcount, uri) - 1));
    }
}
示例#8
0
文件: main.c 项目: hannson/jabberd2
static void _s2s_hosts_expand(s2s_t s2s)
{
    char *realm;
    config_elem_t elem;
    char id[1024];
    int i;

    elem = config_get(s2s->config, "local.id");

    if (elem) for(i = 0; i < elem->nvalues; i++) {
        host_t host = (host_t) pmalloco(xhash_pool(s2s->hosts), sizeof(struct host_st));
        if(!host) {
            log_write(s2s->log, LOG_ERR, "cannot allocate memory for new host, aborting");
            exit(1);
        }

        realm = j_attr((const char **) elem->attrs[i], "realm");

        /* stringprep ids (domain names) so that they are in canonical form */
        strncpy(id, elem->values[i], 1024);
        id[1023] = '\0';
        if (stringprep_nameprep(id, 1024) != 0) {
            log_write(s2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
            exit(1);
        }

        host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(s2s->hosts), id);

        host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile");

        host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain");

        host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0);

#ifdef HAVE_SSL
        if(host->host_pemfile != NULL) {
            if(s2s->sx_ssl == NULL) {
                s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode);
                if(s2s->sx_ssl == NULL) {
                    log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
                    host->host_pemfile = NULL;
                }
            } else {
                if(sx_ssl_server_addcert(s2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode) != 0) {
                    log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
                    host->host_pemfile = NULL;
                }
            }
        }
#endif

        /* insert into vHosts xhash */
        xhash_put(s2s->hosts, pstrdup(xhash_pool(s2s->hosts), id), host);

        log_write(s2s->log, LOG_NOTICE, "[%s] configured; realm=%s", id, host->realm);
    }
}
示例#9
0
/* Hostname lookup requested */
void dnsrv_lookup(dns_io d, dpacket p)
{
    dns_packet_list l, lnew;
    xmlnode req;
    char *reqs;

    /* make sure we have a child! */
    if(d->out <= 0)
    {
        deliver_fail(p, "DNS Resolver Error");
        return;
    }

    /* Attempt to lookup this hostname in the packet table */
    l = (dns_packet_list)xhash_get(d->packet_table, p->host);

    /* IF: hashtable has the hostname, a lookup is already pending,
       so push the packet on the top of the list (most recent at the top) */
    if (l != NULL)
    {
         log_debug(ZONE, "dnsrv: Adding lookup request for %s to pending queue.", p->host);
         lnew = pmalloco(p->p, sizeof(_dns_packet_list));
         lnew->packet = p;
         lnew->stamp = time(NULL);
         lnew->next = l;
         xhash_put(d->packet_table, p->host, lnew);
         return;
    }

    /* insert the packet into the packet_table using the hostname
       as the key and send a request to the coprocess */
    log_debug(ZONE, "dnsrv: Creating lookup request queue for %s", p->host);
    l = pmalloco(p->p, sizeof(_dns_packet_list));
    l->packet = p;
    l->stamp  = time(NULL);
    xhash_put(d->packet_table, p->host, l);
    req = xmlnode_new_tag_pool(p->p,"host");
    xmlnode_insert_cdata(req,p->host,-1);

    reqs = xmlnode2str(req);
    log_debug(ZONE, "dnsrv: Transmitting lookup request: %s", reqs);
    pth_write(d->out, reqs, strlen(reqs));
}
示例#10
0
xht aci_load(sm_t sm)
{
    xht acls;
    int aelem, jelem, attr;
    char type[33];
    jid_t list, jid;

    log_debug(ZONE, "loading aci");

    acls = xhash_new(51);

    if((aelem = nad_find_elem(sm->config->nad, 0, -1, "aci", 1)) < 0)
        return acls;

    aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 1);
    while(aelem >= 0)
    {
        list = NULL;

        if((attr = nad_find_attr(sm->config->nad, aelem, -1, "type", NULL)) < 0)
        {
            aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 0);
            continue;
        }

        snprintf(type, 33, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));

        log_debug(ZONE, "building list for '%s'", type);

        jelem = nad_find_elem(sm->config->nad, aelem, -1, "jid", 1);
        while(jelem >= 0)
        {
            if(NAD_CDATA_L(sm->config->nad, jelem) > 0)
            {
                jid = jid_new(NAD_CDATA(sm->config->nad, jelem), NAD_CDATA_L(sm->config->nad, jelem));
                list = jid_append(list, jid);
                
                log_debug(ZONE, "added '%s'", jid_user(jid));

                jid_free(jid);
            }

            jelem = nad_find_elem(sm->config->nad, jelem, -1, "jid", 0);
        }

        if(list != NULL) {
            xhash_put(acls, pstrdup(xhash_pool(acls), type), (void *) list);
        }

        aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 0);
    }

    return acls;
}
示例#11
0
文件: feature.c 项目: 6wei/jabberd2
/** unregister feature */
void feature_unregister(sm_t sm, const char *feature)
{
    int refcount = (int) (long) xhash_get(sm->features, feature);

    log_debug(ZONE, "unregistering feature %s", feature);

    if (refcount == 1) {
        xhash_zap(sm->features, feature);
    } else if (refcount > 1) {
        xhash_put(sm->features, feature, (void *) ((long) refcount - 1));
    }
}
示例#12
0
文件: iq.c 项目: Doap/transports
int at_register_iqns(ati ti, const char *ns, iqcb cb)
{
    iqcb cur;

    log_debug(ZONE, "Registering callback for %s", ns);
    cur = xhash_get(ti->iq__callbacks, ns);
    if(cur)
    {
        xhash_zap(ti->iq__callbacks, ns);
    }
    xhash_put(ti->iq__callbacks, ns, cb);

    return;
}
示例#13
0
void dnsrv_process_xstream_io(int type, xmlnode x, void* arg)
{
     dns_io di            = (dns_io)arg;
     char* hostname       = NULL;
     char* ipaddr         = NULL;
     char* resendhost     = NULL;
     dns_packet_list head = NULL;
     dns_packet_list heado = NULL;

     /* Node Format: <host ip="201.83.28.2">foo.org</host> */
     if (type == XSTREAM_NODE)
     {    
          log_debug(ZONE,"incoming resolution: %s",xmlnode2str(x));
          hostname = xmlnode_get_data(x);

          /* whatever the response was, let's cache it */
          xmlnode_free((xmlnode)xhash_get(di->cache_table,hostname)); /* free any old cache, shouldn't ever be any */
          xmlnode_put_vattrib(x,"t",(void*)time(NULL));
          xhash_put(di->cache_table,hostname,(void*)x);

          /* Get the hostname and look it up in the hashtable */
          head = xhash_get(di->packet_table, hostname);
          /* Process the packet list */
          if (head != NULL)
          {
               ipaddr = xmlnode_get_attrib(x, "ip");
               resendhost = xmlnode_get_attrib(x, "to");

               /* Remove the list from the hashtable */
               xhash_zap(di->packet_table, hostname);
               
               /* Walk the list and insert IPs */
               while(head != NULL)
               {
                    heado = head;
                    /* Move to next.. */
                    head = head->next;
                    /* Deliver the packet */
                    dnsrv_resend(heado->packet->x, ipaddr, resendhost);
               }
          }
          /* Host name was not found, something is _TERRIBLY_ wrong! */
          else
               log_debug(ZONE, "Resolved unknown host/ip request: %s\n", xmlnode2str(x));

          return; /* we cached x above, so we don't free it below :) */
     }
     xmlnode_free(x);
} 
示例#14
0
nad_t nad_new(void)
{
    nad_t nad;

    nad = calloc(1, sizeof(struct nad_st));

    nad->scope = -1;

#ifdef NAD_DEBUG
    {
    char loc[24];
    snprintf(loc, sizeof(loc), "%x", (int) nad);
    xhash_put(_nad_alloc_tracked, pstrdup(xhash_pool(_nad_alloc_tracked), loc), (void *) 1);
    }
    _nad_ptr_check(__func__, nad);
#endif

    return nad;
}
示例#15
0
文件: router.c 项目: 6wei/jabberd2
static int _route_add(xht hroutes, const char *name, component_t comp, route_type_t rtype) {
    routes_t routes;

    routes = xhash_get(hroutes, name);
    if(routes == NULL) {
        routes = (routes_t) calloc(1, sizeof(struct routes_st));
        routes->name = strdup(name);
        routes->rtype = rtype;
    }
    routes->comp = (component_t *) realloc(routes->comp, sizeof(component_t *) * (routes->ncomp + 1));
    routes->comp[routes->ncomp] = comp;
    routes->ncomp++;
    xhash_put(hroutes, routes->name, (void *) routes);

    if(routes->rtype != rtype)
        log_write(comp->r->log, LOG_ERR, "Mixed route types for '%s' bind request", name);

    return routes->ncomp;
}
示例#16
0
// Rate limit check:  Prevent denial-of-service due to excessive database queries
// Make sure owner is responsible for the query!
int sm_storage_rate_limit(sm_t sm, const char *owner) {
    rate_t rt;
    user_t user;
    sess_t sess;
    item_t item;

    if (sm->query_rate_total == 0 || owner == NULL)
    return FALSE;

    user = xhash_get(sm->users, owner);
    if (user != NULL) {
        rt = (rate_t) xhash_get(sm->query_rates, owner);
        if (rt == NULL) {
            rt = rate_new(sm->query_rate_total, sm->query_rate_seconds, sm->query_rate_wait);
            xhash_put(sm->query_rates, pstrdup(xhash_pool(sm->query_rates), owner), (void *) rt);
            pool_cleanup(xhash_pool(sm->query_rates), (void (*)(void *)) rate_free, rt);
        }

        if(rate_check(rt) == 0) {
            log_write(sm->log, LOG_WARNING, "[%s] is being disconnected, too many database queries within %d seconds", owner, sm->query_rate_seconds);
            user = xhash_get(sm->users, owner);
            for (sess = user->sessions; sess != NULL; sess = sess->next) {
                sm_c2s_action(sess, "ended", NULL);
            }
            if(xhash_iter_first(user->roster))
                do {
                    xhash_iter_get(user->roster, NULL, NULL, (void *) &item);
                    if(item->to) {
                        pkt_router(pkt_create(user->sm, "presence", "unavailable", jid_full(item->jid), jid_full(user->jid)));
                    }
                } while(xhash_iter_next(user->roster));
            return TRUE;
            } else {
                rate_add(rt, 1);
            }
        } else {
            log_debug(ZONE, "Error: could not get user data for %s", owner);
    }
    return FALSE;
}
示例#17
0
文件: object.c 项目: 6wei/jabberd2
void os_object_put(os_object_t o, const char *key, const void *val, os_type_t type) {
    os_field_t osf;
    nad_t nad;

    log_debug(ZONE, "adding field %s (val %x type %d) to object", key, val, type);

    osf = pmalloco(o->os->p, sizeof(struct os_field_st));
    osf->key = pstrdup(o->os->p, key);

    switch(type) {
        case os_type_BOOLEAN:
        case os_type_INTEGER:
            osf->val = (void *) (intptr_t) (* (int *) val);
            break;

        case os_type_STRING:
            osf->val = (void *) pstrdup(o->os->p, (char *) val);
            break;

        case os_type_NAD:
            nad = nad_copy((nad_t) val);

            /* make sure that the nad gets freed when the os pool gets freed */
            pool_cleanup(o->os->p, (pool_cleanup_t) nad_free, (void *) nad);

            osf->val = (void *) nad;
            break;

        case os_type_UNKNOWN:
            break;
    }

    osf->type = type;

    xhash_put(o->hash, osf->key, (void *) osf);
}
示例#18
0
void nad_free(nad_t nad)
{
    if(nad == NULL) return;

#ifdef NAD_DEBUG
    _nad_ptr_check(__func__, nad);
    {
    char loc[24];
    snprintf(loc, sizeof(loc), "%x", (int) nad);
    xhash_zap(_nad_alloc_tracked, loc);
    xhash_put(_nad_free_tracked, pstrdup(xhash_pool(_nad_free_tracked), loc), (void *) nad);
    }
#endif

    /* Free nad */
    free(nad->elems);
    free(nad->attrs);
    free(nad->cdata);
    free(nad->nss);
    free(nad->depths);
#ifndef NAD_DEBUG
    free(nad);
#endif
}
示例#19
0
文件: router.c 项目: 6wei/jabberd2
static int _router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
    component_t comp = (component_t) arg;
    sx_buf_t buf = (sx_buf_t) data;
    int rlen, len, attr, ns, sns, n;
    sx_error_t *sxe;
    nad_t nad;
    struct jid_st sto, sfrom;
    jid_static_buf sto_buf, sfrom_buf;
    jid_t to, from;
    alias_t alias;

    /* init static jid */
    jid_static(&sto,&sto_buf);
    jid_static(&sfrom,&sfrom_buf);

    switch(e) {
        case event_WANT_READ:
            log_debug(ZONE, "want read");
            mio_read(comp->r->mio, comp->fd);
            break;

        case event_WANT_WRITE:
            log_debug(ZONE, "want write");
            mio_write(comp->r->mio, comp->fd);
            break;

        case event_READ:
            log_debug(ZONE, "reading from %d", comp->fd->fd);

            /* check rate limits */
            if(comp->rate != NULL) {
                if(rate_check(comp->rate) == 0) {

                    /* inform the app if we haven't already */
                    if(!comp->rate_log) {
                        log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] is being byte rate limited", comp->ip, comp->port);

                        comp->rate_log = 1;
                    }

                    log_debug(ZONE, "%d is throttled, delaying read", comp->fd->fd);

                    buf->len = 0;
                    return 0;
                }

                /* find out how much we can have */
                rlen = rate_left(comp->rate);
                if(rlen > buf->len)
                    rlen = buf->len;
            }

            /* no limit, just read as much as we can */
            else
                rlen = buf->len;
            
            /* do the read */
            len = recv(comp->fd->fd, buf->data, rlen, 0);

            /* update rate limits */
            if(comp->rate != NULL && len > 0) {
                comp->rate_log = 0;
                rate_add(comp->rate, len);
            }

            if(len < 0) {
                if(MIO_WOULDBLOCK) {
                    buf->len = 0;
                    return 0;
                }

                log_debug(ZONE, "read failed: %s", strerror(errno));

                sx_kill(comp->s);
                
                return -1;
            }

            else if(len == 0) {
                /* they went away */
                sx_kill(comp->s);

                return -1;
            }

            log_debug(ZONE, "read %d bytes", len);

            buf->len = len;

            return len;

        case event_WRITE:
            log_debug(ZONE, "writing to %d", comp->fd->fd);

            len = send(comp->fd->fd, buf->data, buf->len, 0);
            if(len >= 0) {
                log_debug(ZONE, "%d bytes written", len);
                return len;
            }

            if(MIO_WOULDBLOCK)
                return 0;

            log_debug(ZONE, "write failed: %s", strerror(errno));
        
            sx_kill(comp->s);
        
            return -1;

        case event_ERROR:
            sxe = (sx_error_t *) data;
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] error: %s (%s)", comp->ip, comp->port, sxe->generic, sxe->specific);

            break;

        case event_STREAM:
            
            /* legacy check */
            if(s->ns == NULL || strcmp("jabber:component:accept", s->ns) != 0)
                return 0;

            /* component, old skool */
            comp->legacy = 1;

            /* enabled? */
            if(comp->r->local_secret == NULL) {
                sx_error(s, stream_err_INVALID_NAMESPACE, "support for legacy components not available");      /* !!! correct error? */
                sx_close(s);
                return 0;
            }
            
            /* sanity */
            if(s->req_to == NULL) {
                sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header");
                sx_close(s);
                return 0;
            }

            break;

        case event_OPEN:
            
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] authenticated as %s", comp->ip, comp->port, comp->s->auth_id);

            /* make a route for legacy components */
            if(comp->legacy) {
                for(alias = comp->r->aliases; alias != NULL; alias = alias->next)
                    if(strcmp(alias->name, s->req_to) == 0) {
                        sx_error(s, stream_err_HOST_UNKNOWN, "requested name is aliased");   /* !!! correct error? */
                        sx_close(s);
                        return 0;
                    }


                n = _route_add(comp->r->routes, s->req_to, comp, route_MULTI_FROM);
                xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), s->req_to), (void *) comp);

                if(n>1)
                    log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", s->req_to, n, comp->ip, comp->port);
                else
                    log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", s->req_to, comp->ip, comp->port);

                /* advertise the name */
                _router_advertise(comp->r, s->req_to, comp, 0);

                /* this is a legacy component, so we don't tell it about other routes */

                /* bind aliases */
                for(alias = comp->r->aliases; alias != NULL; alias = alias->next) {
                    if(strcmp(alias->target, s->req_to) == 0) {
                        _route_add(comp->r->routes, alias->name, comp, route_MULTI_FROM);
                        xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp);
            
                        log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, s->req_to, comp->ip, comp->port);

                        /* advertise name */
                        _router_advertise(comp->r, alias->name, comp, 0);
                    }
                }
            }

            break;

        case event_PACKET:
            nad = (nad_t) data;

            /* preauth */
            if(comp->s->state == state_STREAM) {
                /* non-legacy components can't do anything before auth */
                if(!comp->legacy) {
                    log_debug(ZONE, "stream is preauth, dropping packet");
                    nad_free(nad);
                    return 0;
                }

                /* watch for handshake requests */
                if(NAD_ENAME_L(nad, 0) != 9 || strncmp("handshake", NAD_ENAME(nad, 0), NAD_ENAME_L(nad, 0)) != 0) { 
                    log_debug(ZONE, "unknown preauth packet %.*s, dropping", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));

                    nad_free(nad);
                    return 0;
                }

                /* process incoming handshakes */
                _router_process_handshake(comp, nad);

                return 0;
            }

            /* legacy processing */
            if(comp->legacy) {
                log_debug(ZONE, "packet from legacy component, munging it");

                attr = nad_find_attr(nad, 0, -1, "to", NULL);
                if(attr < 0 || (to = jid_reset(&sto, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
                    log_debug(ZONE, "invalid or missing 'to' address on legacy packet, dropping it");
                    nad_free(nad);
                    return 0;
                }

                attr = nad_find_attr(nad, 0, -1, "from", NULL);
                if(attr < 0 || (from = jid_reset(&sfrom, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
                    log_debug(ZONE, "invalid or missing 'from' address on legacy packet, dropping it");
                    nad_free(nad);
                    return 0;
                }

                /* rewrite component packets into client packets */
                ns = nad_find_namespace(nad, 0, "jabber:component:accept", NULL);
                if(ns >= 0) {
                    if(nad->elems[0].ns == ns)
                        nad->elems[0].ns = nad->nss[nad->elems[0].ns].next;
                    else {
                        for(sns = nad->elems[0].ns; sns >= 0 && nad->nss[sns].next != ns; sns = nad->nss[sns].next);
                        nad->nss[sns].next = nad->nss[nad->nss[sns].next].next;
                    }
                }

                ns = nad_find_namespace(nad, 0, uri_CLIENT, NULL);
                if(ns < 0) {
                    ns = nad_add_namespace(nad, uri_CLIENT, NULL);
                    nad->scope = -1;
                    nad->nss[ns].next = nad->elems[0].ns;
                    nad->elems[0].ns = ns;
                }
                nad->elems[0].my_ns = ns;

                /* wrap up the packet */
                ns = nad_add_namespace(nad, uri_COMPONENT, NULL);

                nad_wrap_elem(nad, 0, ns, "route");

                nad_set_attr(nad, 0, -1, "to", to->domain, 0);
                nad_set_attr(nad, 0, -1, "from", from->domain, 0);
            }

            /* top element must be router scoped */
            if(NAD_ENS(nad, 0) < 0 || NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0) {
                log_debug(ZONE, "invalid packet namespace, dropping");
                nad_free(nad);
                return 0;
            }

            /* bind a name to this component */
            if(NAD_ENAME_L(nad, 0) == 4 && strncmp("bind", NAD_ENAME(nad, 0), 4) == 0) {
                _router_process_bind(comp, nad);
                return 0;
            }

            /* unbind a name from this component */
            if(NAD_ENAME_L(nad, 0) == 6 && strncmp("unbind", NAD_ENAME(nad, 0), 6) == 0) {
                _router_process_unbind(comp, nad);
                return 0;
            }

            /* route packets */
            if(NAD_ENAME_L(nad, 0) == 5 && strncmp("route", NAD_ENAME(nad, 0), 5) == 0) {
                _router_process_route(comp, nad);
                return 0;
            }

            /* throttle packets */
            if(NAD_ENAME_L(nad, 0) == 8 && strncmp("throttle", NAD_ENAME(nad, 0), 8) == 0) {
                _router_process_throttle(comp, nad);
                return 0;
            }

            log_debug(ZONE, "unknown packet, dropping");

            nad_free(nad);
            return 0;

        case event_CLOSED:
        {
            /* close comp->fd by putting it in closefd ... unless it is already there */
            _jqueue_node_t n;
            for (n = comp->r->closefd->front; n != NULL; n = n->prev)
                if (n->data == comp->fd) break;
            if (!n) jqueue_push(comp->r->closefd, (void *) comp->fd, 0 /*priority*/);
            return 0;
        }
    }

    return 0;
}
示例#20
0
文件: main.c 项目: 6wei/jabberd2
/** pull values out of the config file */
static void _c2s_config_expand(c2s_t c2s)
{
    const char *str, *ip, *mask;
    char *req_domain, *to_address, *to_port;
    config_elem_t elem;
    int i;
    stream_redirect_t sr;

    set_debug_log_from_config(c2s->config);

    c2s->id = config_get_one(c2s->config, "id", 0);
    if(c2s->id == NULL)
        c2s->id = "c2s";

    c2s->router_ip = config_get_one(c2s->config, "router.ip", 0);
    if(c2s->router_ip == NULL)
        c2s->router_ip = "127.0.0.1";

    c2s->router_port = j_atoi(config_get_one(c2s->config, "router.port", 0), 5347);

    c2s->router_user = config_get_one(c2s->config, "router.user", 0);
    if(c2s->router_user == NULL)
        c2s->router_user = "******";
    c2s->router_pass = config_get_one(c2s->config, "router.pass", 0);
    if(c2s->router_pass == NULL)
        c2s->router_pass = "******";

    c2s->router_pemfile = config_get_one(c2s->config, "router.pemfile", 0);

    c2s->router_cachain = config_get_one(c2s->config, "router.cachain", 0);

    c2s->router_private_key_password = config_get_one(c2s->config, "router.private_key_password", 0);

    c2s->retry_init = j_atoi(config_get_one(c2s->config, "router.retry.init", 0), 3);
    c2s->retry_lost = j_atoi(config_get_one(c2s->config, "router.retry.lost", 0), 3);
    if((c2s->retry_sleep = j_atoi(config_get_one(c2s->config, "router.retry.sleep", 0), 2)) < 1)
        c2s->retry_sleep = 1;

    c2s->log_type = log_STDOUT;
    if(config_get(c2s->config, "log") != NULL) {
        if((str = config_get_attr(c2s->config, "log", 0, "type")) != NULL) {
            if(strcmp(str, "file") == 0)
                c2s->log_type = log_FILE;
            else if(strcmp(str, "syslog") == 0)
                c2s->log_type = log_SYSLOG;
        }
    }

    if(c2s->log_type == log_SYSLOG) {
        c2s->log_facility = config_get_one(c2s->config, "log.facility", 0);
        c2s->log_ident = config_get_one(c2s->config, "log.ident", 0);
        if(c2s->log_ident == NULL)
            c2s->log_ident = "jabberd/c2s";
    } else if(c2s->log_type == log_FILE)
        c2s->log_ident = config_get_one(c2s->config, "log.file", 0);

    c2s->packet_stats = config_get_one(c2s->config, "stats.packet", 0);

    c2s->local_ip = config_get_one(c2s->config, "local.ip", 0);
    if(c2s->local_ip == NULL)
        c2s->local_ip = "0.0.0.0";

    c2s->local_port = j_atoi(config_get_one(c2s->config, "local.port", 0), 0);

    c2s->local_pemfile = config_get_one(c2s->config, "local.pemfile", 0);

    c2s->local_cachain = config_get_one(c2s->config, "local.cachain", 0);

    c2s->local_private_key_password = config_get_one(c2s->config, "local.private_key_password", 0);

    c2s->local_verify_mode = j_atoi(config_get_one(c2s->config, "local.verify-mode", 0), 0);

    c2s->local_ssl_port = j_atoi(config_get_one(c2s->config, "local.ssl-port", 0), 0);

    c2s->http_forward = config_get_one(c2s->config, "local.httpforward", 0);

    c2s->io_max_fds = j_atoi(config_get_one(c2s->config, "io.max_fds", 0), 1024);

    c2s->compression = (config_get(c2s->config, "io.compression") != NULL);

    c2s->io_check_interval = j_atoi(config_get_one(c2s->config, "io.check.interval", 0), 0);
    c2s->io_check_idle = j_atoi(config_get_one(c2s->config, "io.check.idle", 0), 0);
    c2s->io_check_keepalive = j_atoi(config_get_one(c2s->config, "io.check.keepalive", 0), 0);

    c2s->pbx_pipe = config_get_one(c2s->config, "pbx.pipe", 0);

    elem = config_get(c2s->config, "stream_redirect.redirect");
    if(elem != NULL)
    {
        for(i = 0; i < elem->nvalues; i++)
        {
            sr = (stream_redirect_t) pmalloco(xhash_pool(c2s->stream_redirects), sizeof(struct stream_redirect_st));
            if(!sr) {
                log_write(c2s->log, LOG_ERR, "cannot allocate memory for new stream redirection record, aborting");
                exit(1);
            }
            req_domain = j_attr((const char **) elem->attrs[i], "requested_domain");
            to_address = j_attr((const char **) elem->attrs[i], "to_address");
            to_port = j_attr((const char **) elem->attrs[i], "to_port");

            if(req_domain == NULL || to_address == NULL || to_port == NULL) {
                log_write(c2s->log, LOG_ERR, "Error reading a stream_redirect.redirect element from file, skipping");
                continue;
            }

            // Note that to_address should be RFC 3986 compliant
            sr->to_address = to_address;
            sr->to_port = to_port;
            
            xhash_put(c2s->stream_redirects, pstrdup(xhash_pool(c2s->stream_redirects), req_domain), sr);
        }
    }

    c2s->ar_module_name = config_get_one(c2s->config, "authreg.module", 0);

    if(config_get(c2s->config, "authreg.mechanisms.traditional.plain") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_PLAIN;
    if(config_get(c2s->config, "authreg.mechanisms.traditional.digest") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_DIGEST;
    if(config_get(c2s->config, "authreg.mechanisms.traditional.cram-md5") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_CRAMMD5;

    if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.plain") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_PLAIN;
    if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.digest") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_DIGEST;
    if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.cram-md5") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_CRAMMD5;

    elem = config_get(c2s->config, "io.limits.bytes");
    if(elem != NULL)
    {
        c2s->byte_rate_total = j_atoi(elem->values[0], 0);
        if(c2s->byte_rate_total != 0)
        {
            c2s->byte_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 1);
            c2s->byte_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
        }
    }

    elem = config_get(c2s->config, "io.limits.stanzas");
    if(elem != NULL)
    {
        c2s->stanza_rate_total = j_atoi(elem->values[0], 0);
        if(c2s->stanza_rate_total != 0)
        {
            c2s->stanza_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 1);
            c2s->stanza_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
        }
    }

    elem = config_get(c2s->config, "io.limits.connects");
    if(elem != NULL)
    {
        c2s->conn_rate_total = j_atoi(elem->values[0], 0);
        if(c2s->conn_rate_total != 0)
        {
            c2s->conn_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 5);
            c2s->conn_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
        }
    }

    c2s->stanza_size_limit = j_atoi(config_get_one(c2s->config, "io.limits.stanzasize", 0), 0);

    /* tweak timed checks with rate times */
    if(c2s->io_check_interval == 0) {
        if(c2s->byte_rate_total != 0)
            c2s->io_check_interval = c2s->byte_rate_wait;

        if(c2s->stanza_rate_total != 0 && c2s->io_check_interval > c2s->stanza_rate_wait)
            c2s->io_check_interval = c2s->stanza_rate_wait;
    }

    str = config_get_one(c2s->config, "io.access.order", 0);
    if(str == NULL || strcmp(str, "deny,allow") != 0)
        c2s->access = access_new(0);
    else
        c2s->access = access_new(1);

    elem = config_get(c2s->config, "io.access.allow");
    if(elem != NULL)
    {
        for(i = 0; i < elem->nvalues; i++)
        {
            ip = j_attr((const char **) elem->attrs[i], "ip");
            mask = j_attr((const char **) elem->attrs[i], "mask");

            if(ip == NULL)
                continue;

            if(mask == NULL)
                mask = "255.255.255.255";

            access_allow(c2s->access, ip, mask);
        }
    }

    elem = config_get(c2s->config, "io.access.deny");
    if(elem != NULL)
    {
        for(i = 0; i < elem->nvalues; i++)
        {
            ip = j_attr((const char **) elem->attrs[i], "ip");
            mask = j_attr((const char **) elem->attrs[i], "mask");

            if(ip == NULL)
                continue;

            if(mask == NULL)
                mask = "255.255.255.255";

            access_deny(c2s->access, ip, mask);
        }
    }
}
示例#21
0
文件: router.c 项目: 6wei/jabberd2
static void _router_process_bind(component_t comp, nad_t nad) {
    int attr, multi, n;
    jid_t name;
    alias_t alias;
    char *user, *c;

    attr = nad_find_attr(nad, 0, -1, "name", NULL);
    if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "no or invalid 'name' on bind packet, bouncing");
        nad_set_attr(nad, 0, -1, "error", "400", 3);
        sx_nad_write(comp->s, nad);
        return;
    }

    user = strdup(comp->s->auth_id);
    c = strchr(user, '@');
    if(c != NULL) *c = '\0';

    if(strcmp(user, name->domain) != 0 && !aci_check(comp->r->aci, "bind", user)) {
        log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but their username (%s) is not permitted to bind other names", comp->ip, comp->port, name->domain, user);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "403", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        free(user);
        return;
    }

    multi = nad_find_attr(nad, 0, -1, "multi", NULL);
    if(xhash_get(comp->r->routes, name->domain) != NULL && multi < 0) {
        log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but it's already bound", comp->ip, comp->port, name->domain);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "409", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        free(user);
        return;
    }

    for(alias = comp->r->aliases; alias != NULL; alias = alias->next)
        if(strcmp(alias->name, name->domain) == 0) {
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but that name is aliased", comp->ip, comp->port);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "409", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

    /* default route */
    if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "default", 1) >= 0) {
        if(!aci_check(comp->r->aci, "default-route", user)) {
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but their username (%s) is not permitted to set a default route", comp->ip, comp->port, name->domain, user);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "403", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

        if(comp->r->default_route != NULL) {
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but one already exists", comp->ip, comp->port, name->domain);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "409", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            return;
        }

        log_write(comp->r->log, LOG_NOTICE, "[%s] set as default route", name->domain);

        comp->r->default_route = strdup(name->domain);
    }

    /* log sinks */
    if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "log", 1) >= 0) {
        if(!aci_check(comp->r->aci, "log", user)) {
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as a log sink, but their username (%s) is not permitted to do this", comp->ip, comp->port, name->domain, user);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "403", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

        log_write(comp->r->log, LOG_NOTICE, "[%s] set as log sink", name->domain);

        xhash_put(comp->r->log_sinks, pstrdup(xhash_pool(comp->r->log_sinks), name->domain), (void *) comp);
    }

    free(user);

    n = _route_add(comp->r->routes, name->domain, comp, multi<0?route_SINGLE:route_MULTI_TO);
    xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), name->domain), (void *) comp);

    if(n>1)
        log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", name->domain, n, comp->ip, comp->port);
    else
        log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", name->domain, comp->ip, comp->port);

    nad_set_attr(nad, 0, -1, "name", NULL, 0);
    sx_nad_write(comp->s, nad);

    /* advertise name */
    _router_advertise(comp->r, name->domain, comp, 0);

    /* tell the new component about everyone else */
    xhash_walk(comp->r->routes, _router_advertise_reverse, (void *) comp);

    /* bind aliases */
    for(alias = comp->r->aliases; alias != NULL; alias = alias->next) {
        if(strcmp(alias->target, name->domain) == 0) {
            _route_add(comp->r->routes, name->domain, comp, route_MULTI_TO);
            xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp);
            
            log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, name->domain, comp->ip, comp->port);

            /* advertise name */
            _router_advertise(comp->r, alias->name, comp, 0);
        }
    }

    /* done with this */
    jid_free(name);
}
示例#22
0
文件: router.c 项目: 6wei/jabberd2
int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
    component_t comp = (component_t) arg;
    router_t r = (router_t) arg;
    struct sockaddr_storage sa;
    socklen_t namelen = sizeof(sa);
    int port, nbytes;

    switch(a) {
        case action_READ:
            log_debug(ZONE, "read action on fd %d", fd->fd);

            /* they did something */
            comp->last_activity = time(NULL);

            ioctl(fd->fd, FIONREAD, &nbytes);
            if(nbytes == 0) {
                sx_kill(comp->s);
                return 0;
            }

            return sx_can_read(comp->s);

        case action_WRITE:
            log_debug(ZONE, "write action on fd %d", fd->fd);

           /* update activity timestamp */
            comp->last_activity = time(NULL);

            return sx_can_write(comp->s);

        case action_CLOSE:
            log_debug(ZONE, "close action on fd %d", fd->fd);

            r = comp->r;

            log_write(r->log, LOG_NOTICE, "[%s, port=%d] disconnect", comp->ip, comp->port);

            /* unbind names */
            xhash_walk(comp->routes, _router_route_unbind_walker, (void *) comp);

            /* deregister component */
            xhash_zap(r->components, comp->ipport);

            xhash_free(comp->routes);

            if(comp->tq != NULL)
                /* !!! bounce packets */
                jqueue_free(comp->tq);

            rate_free(comp->rate);

            jqueue_push(comp->r->dead, (void *) comp->s, 0);

            free(comp);

            break;

        case action_ACCEPT:
            log_debug(ZONE, "accept action on fd %d", fd->fd);

            getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
            port = j_inet_getport(&sa);

            log_write(r->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port);

            if(_router_accept_check(r, fd, (char *) data) != 0)
                return 1;

            comp = (component_t) calloc(1, sizeof(struct component_st));

            comp->r = r;

            comp->fd = fd;

            snprintf(comp->ip, INET6_ADDRSTRLEN, "%s", (char *) data);
            comp->port = port;

            snprintf(comp->ipport, INET6_ADDRSTRLEN + 6, "%s:%d", comp->ip, comp->port);

            comp->s = sx_new(r->sx_env, fd->fd, _router_sx_callback, (void *) comp);
            mio_app(m, fd, router_mio_callback, (void *) comp);

            if(r->byte_rate_total != 0)
                comp->rate = rate_new(r->byte_rate_total, r->byte_rate_seconds, r->byte_rate_wait);

            comp->routes = xhash_new(51);

            /* register component */
            log_debug(ZONE, "new component (%p) \"%s\"", comp, comp->ipport);
            xhash_put(r->components, comp->ipport, (void *) comp);

#ifdef HAVE_SSL
            sx_server_init(comp->s, SX_SSL_STARTTLS_OFFER | SX_SASL_OFFER);
#else
            sx_server_init(comp->s, SX_SASL_OFFER);
#endif

            break;
    }

    return 0;
}
示例#23
0
st_ret_t storage_add_type(storage_t st, const char *driver, const char *type) {
    st_driver_t drv;
    st_driver_init_fn init_fn = NULL;
    char mod_fullpath[PATH_MAX];
    const char *modules_path;
    st_ret_t ret;
    void *handle;

    /* startup, see if we've already registered this type */
    if(type == NULL) {
        log_debug(ZONE, "adding arbitrary types to driver '%s'", driver);

        /* see if we already have one */
        if(st->default_drv != NULL) {
            log_debug(ZONE, "we already have a default handler, ignoring this one");
            return st_FAILED;
        }
    } else {
        log_debug(ZONE, "adding type '%s' to driver '%s'", type, driver);

        /* see if we already have one */
        if(xhash_get(st->types, type) != NULL) {
            log_debug(ZONE, "we already have a handler for type '%s', ignoring this one", type);
            return st_FAILED;
        }
    }

    /* set modules path */
    modules_path = config_get_one(st->config, "storage.path", 0);

    /* get the driver */
    drv = xhash_get(st->drivers, driver);
    if(drv == NULL) {
        log_debug(ZONE, "driver not loaded, trying to init");

        log_write(st->log, LOG_INFO, "loading '%s' storage module", driver);
#ifndef _WIN32
        if (modules_path != NULL)
            snprintf(mod_fullpath, PATH_MAX, "%s/storage_%s.so", modules_path, driver);
        else
            snprintf(mod_fullpath, PATH_MAX, "%s/storage_%s.so", LIBRARY_DIR, driver);
        handle = dlopen(mod_fullpath, RTLD_LAZY);
        if (handle != NULL)
            init_fn = dlsym(handle, "st_init");
#else
        if (modules_path != NULL)
            snprintf(mod_fullpath, PATH_MAX, "%s\\storage_%s.dll", modules_path, driver);
        else
            snprintf(mod_fullpath, PATH_MAX, "storage_%s.dll", driver);
        handle = (void*) LoadLibrary(mod_fullpath);
        if (handle != NULL)
            init_fn = (st_driver_init_fn)GetProcAddress((HMODULE) handle, "st_init");
#endif
    
        if (handle != NULL && init_fn != NULL) {
            log_debug(ZONE, "preloaded module '%s' (not initialized yet)", driver);
        } else {
#ifndef _WIN32
            log_write(st->log, LOG_ERR, "failed loading storage module '%s' (%s)", driver, dlerror());
            if (handle != NULL)
                dlclose(handle);
#else
            log_write(st->log, LOG_ERR, "failed loading storage module '%s' (errcode: %x)", driver, GetLastError());
            if (handle != NULL)
                FreeLibrary((HMODULE) handle);
#endif
            return st_FAILED;
        }

        /* make a new driver structure */
        drv = (st_driver_t) calloc(1, sizeof(struct st_driver_st));

        drv->handle = handle;
        drv->st = st;

        log_debug(ZONE, "calling driver initializer");

        /* init */
        if((init_fn)(drv) == st_FAILED) {
            log_write(st->log, LOG_NOTICE, "initialisation of storage driver '%s' failed", driver);
            free(drv);
            return st_FAILED;
        }

        /* add it to the drivers hash so we can find it later */
        drv->name = pstrdup(xhash_pool(st->drivers), driver);
        xhash_put(st->drivers, drv->name, (void *) drv);

        log_write(st->log, LOG_NOTICE, "initialised storage driver '%s'", driver);
    }

    /* if its a default, set it up as such */
    if(type == NULL) {
        st->default_drv = drv;
        return st_SUCCESS;
    }

    /* its a real type, so let the driver know */
    if(type != NULL && (ret = (drv->add_type)(drv, type)) != st_SUCCESS) {
        log_debug(ZONE, "driver '%s' can't handle '%s' data", driver, type);
        return ret;
    }

    /* register the type */
    xhash_put(st->types, pstrdup(xhash_pool(st->types), type), (void *) drv);

    return st_SUCCESS;
}
示例#24
0
文件: in.c 项目: zipo/zipo
int in_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
    conn_t in = (conn_t) arg;
    s2s_t s2s = (s2s_t) arg;
    struct sockaddr_storage sa;
    int namelen = sizeof(sa), port, nbytes;
    char ipport[INET6_ADDRSTRLEN + 17];

    switch(a) {
        case action_READ:
            log_debug(ZONE, "read action on fd %d", fd->fd);

            ioctl(fd->fd, FIONREAD, &nbytes);
            if(nbytes == 0) {
                sx_kill(in->s);
                return 0;
            }

            return sx_can_read(in->s);

        case action_WRITE:
            log_debug(ZONE, "write action on fd %d", fd->fd);
            return sx_can_write(in->s);

        case action_CLOSE:
            log_debug(ZONE, "close action on fd %d", fd->fd);

            /* !!! logging */
            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect, packets: %i", fd->fd, in->ip, in->port, in->packet_count);

            jqueue_push(in->s2s->dead, (void *) in->s, 0);

            /* remove from open streams hash if online, or open connections if not */
            if (in->online)
                xhash_zap(in->s2s->in, in->key);
            else {
                snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
                xhash_zap(in->s2s->in_accept, ipport);
            }

            jqueue_push(in->s2s->dead_conn, (void *) in, 0);

            break;

        case action_ACCEPT:
            s2s = (s2s_t) arg;

            log_debug(ZONE, "accept action on fd %d", fd->fd);
            
            getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
            port = j_inet_getport(&sa);

            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd->fd, (char *) data, port);

            /* new conn */
            in = (conn_t) calloc(1, sizeof(struct conn_st));

            in->s2s = s2s;

            strncpy(in->ip, (char *) data, INET6_ADDRSTRLEN);
            in->port = port;

            in->states = xhash_new(101);
            in->states_time = xhash_new(101);

            in->fd = fd;

            in->init_time = time(NULL);

            in->s = sx_new(s2s->sx_env, in->fd->fd, _in_sx_callback, (void *) in);
            mio_app(m, in->fd, in_mio_callback, (void *) in);

            if(s2s->stanza_size_limit != 0)
                in->s->rbytesmax = s2s->stanza_size_limit;

            /* add to incoming connections hash */
            snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
            xhash_put(s2s->in_accept, pstrdup(xhash_pool(s2s->in_accept),ipport), (void *) in);

#ifdef HAVE_SSL
            sx_server_init(in->s, S2S_DB_HEADER | ((s2s->sx_ssl != NULL) ? SX_SSL_STARTTLS_OFFER : 0) );
#else
            sx_server_init(in->s, S2S_DB_HEADER);
#endif
            break;
    }

    return 0;
}
示例#25
0
文件: main.c 项目: 6wei/jabberd2
static void _c2s_hosts_expand(c2s_t c2s)
{
    char *realm;
    config_elem_t elem;
    char id[1024];
    int i;

    elem = config_get(c2s->config, "local.id");
    if(!elem) {
        log_write(c2s->log, LOG_NOTICE, "no local.id configured - skipping local domains configuration");
        return;
    }
    for(i = 0; i < elem->nvalues; i++) {
        host_t host = (host_t) pmalloco(xhash_pool(c2s->hosts), sizeof(struct host_st));
        if(!host) {
            log_write(c2s->log, LOG_ERR, "cannot allocate memory for new host, aborting");
            exit(1);
        }

        realm = j_attr((const char **) elem->attrs[i], "realm");

        /* stringprep ids (domain names) so that they are in canonical form */
        strncpy(id, elem->values[i], 1024);
        id[1023] = '\0';
        if (stringprep_nameprep(id, 1024) != 0) {
            log_write(c2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
            exit(1);
        }

        host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(c2s->hosts), id);

        host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile");

        host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain");

        host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0);

        host->host_private_key_password = j_attr((const char **) elem->attrs[i], "private-key-password");

#ifdef HAVE_SSL
        if(host->host_pemfile != NULL) {
            if(c2s->sx_ssl == NULL) {
                c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode, host->host_private_key_password);
                if(c2s->sx_ssl == NULL) {
                    log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
                    host->host_pemfile = NULL;
                }
            } else {
                if(sx_ssl_server_addcert(c2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode, host->host_private_key_password) != 0) {
                    log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
                    host->host_pemfile = NULL;
                }
            }
        }
#endif

        host->host_require_starttls = (j_attr((const char **) elem->attrs[i], "require-starttls") != NULL);

        host->ar_register_enable = (j_attr((const char **) elem->attrs[i], "register-enable") != NULL);
        host->ar_register_oob = j_attr((const char **) elem->attrs[i], "register-oob");
        if(host->ar_register_enable || host->ar_register_oob) {
            host->ar_register_instructions = j_attr((const char **) elem->attrs[i], "instructions");
            if(host->ar_register_instructions == NULL) {
                if(host->ar_register_oob)
                    host->ar_register_instructions = "Only web based registration is possible with this server.";
                else
                    host->ar_register_instructions = "Enter a username and password to register with this server.";
            }
        } else
            host->ar_register_password = (j_attr((const char **) elem->attrs[i], "password-change") != NULL);

        /* check for empty <id/> CDATA - XXX this "1" is VERY config.c dependant !!! */
        if(! strcmp(id, "1")) {
            /* remove the realm even if set */
            host->realm = NULL;

            /* skip if vHost already configured */
            if(! c2s->vhost)
                c2s->vhost = host;

            /* add meaningful log "id" */
            strcpy(id, "default vHost");
        } else {
            /* insert into vHosts xhash */
            xhash_put(c2s->hosts, pstrdup(xhash_pool(c2s->hosts), id), host);
        }

        log_write(c2s->log, LOG_NOTICE, "[%s] configured; realm=%s, registration %s, using PEM:%s",
                  id, (host->realm != NULL ? host->realm : "no realm set"), (host->ar_register_enable ? "enabled" : "disabled"),
                  (host->host_pemfile ? host->host_pemfile : "Default"));
    }
}
示例#26
0
文件: main.c 项目: hannson/jabberd2
static void _s2s_time_checks(s2s_t s2s) {
    conn_t conn;
    time_t now;
    char *rkey, *key;
    int keylen;
    jqueue_t q;
    dnscache_t dns;
    char *c;
    int c_len;
    union xhashv xhv;

    now = time(NULL);

    /* queue expiry */
    if(s2s->check_queue > 0) {
        if(xhash_iter_first(s2s->outq))
            do {
                xhv.jq_val = &q;
                xhash_iter_get(s2s->outq, (const char **) &rkey, &keylen, xhv.val);

                log_debug(ZONE, "running time checks for %.*s", keylen, rkey);
                c = memchr(rkey, '/', keylen);
                c++;
                c_len = keylen - (c - rkey);

                /* dns lookup timeout check first */
                dns = xhash_getx(s2s->dnscache, c, c_len);
                if(dns != NULL && dns->pending) {
                    log_debug(ZONE, "dns lookup pending for %.*s", c_len, c);
                    if(now > dns->init_time + s2s->check_queue) {
                        log_write(s2s->log, LOG_NOTICE, "dns lookup for %.*s timed out", c_len, c);

                        /* bounce queue */
                        out_bounce_route_queue(s2s, rkey, keylen, stanza_err_REMOTE_SERVER_NOT_FOUND);

                        /* expire pending dns entry */
                        xhash_zap(s2s->dnscache, dns->name);
                        xhash_free(dns->results);
                        if (dns->query != NULL) {
                            if (dns->query->query != NULL)
                                dns_cancel(NULL, dns->query->query);
                            xhash_free(dns->query->hosts);
                            xhash_free(dns->query->results);
                            free(dns->query->name);
                            free(dns->query);
                        }
                        free(dns);
                    }

                    continue;
                }

                /* get the conn */
                conn = xhash_getx(s2s->out_dest, c, c_len);
                if(conn == NULL) {
                    if(jqueue_size(q) > 0) {
                       /* no pending conn? perhaps it failed? */
                       log_debug(ZONE, "no pending connection for %.*s, bouncing %i packets in queue", c_len, c, jqueue_size(q));

                       /* bounce queue */
                       out_bounce_route_queue(s2s, rkey, keylen, stanza_err_REMOTE_SERVER_TIMEOUT);
                    }

                    continue;
                }

                /* connect timeout check */
                if(!conn->online && now > conn->init_time + s2s->check_queue) {
                    dnsres_t bad;
                    char *ipport;

                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connection to %s timed out", conn->fd->fd, conn->ip, conn->port, c);

                    if (s2s->dns_bad_timeout > 0) {
                        /* mark this host as bad */
                        ipport = dns_make_ipport(conn->ip, conn->port);
                        bad = xhash_get(s2s->dns_bad, ipport);
                        if (bad == NULL) {
                            bad = (dnsres_t) calloc(1, sizeof(struct dnsres_st));
                            bad->key = ipport;
                            xhash_put(s2s->dns_bad, ipport, bad);
                        } else {
                            free(ipport);
                        }
                        bad->expiry = time(NULL) + s2s->dns_bad_timeout;
                    }

                    /* close connection as per XMPP/RFC3920 */
                    /* the close function will retry or bounce the queue */
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->outq));
    }

    /* expiry of connected routes in conn_INPROGRESS state */
    if(s2s->check_queue > 0) {

        /* outgoing connections */
        if(s2s->out_reuse) {
            if(xhash_iter_first(s2s->out_host))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking dialback state for outgoing conn %.*s", keylen, key);
                    if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
                        log_debug(ZONE, "checking pending verify requests for outgoing conn %.*s", keylen, key);
                        if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
                            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
                            sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
                            sx_close(conn->s);
                        }
                    }
                } while(xhash_iter_next(s2s->out_host));
        } else {
            if(xhash_iter_first(s2s->out_dest))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking dialback state for outgoing conn %s (%s)", conn->dkey, conn->key);
                    if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
                        log_debug(ZONE, "checking pending verify requests for outgoing conn %s (%s)", conn->dkey, conn->key);
                        if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
                            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
                            sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
                            sx_close(conn->s);
                        }
                    }
                } while(xhash_iter_next(s2s->out_dest));
        }

        /* incoming open streams */
        if(xhash_iter_first(s2s->in))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);

                log_debug(ZONE, "checking dialback state for incoming conn %.*s", keylen, key);
                if (_s2s_check_conn_routes(s2s, conn, "incoming"))
                    /* if the connection is still valid, check that dialbacks have been initiated */
                    if(!xhash_count(conn->states) && now > conn->init_time + s2s->check_queue) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback started", conn->fd->fd, conn->ip, conn->port);
                        sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "no dialback initiated");
                        sx_close(conn->s);
                    }
            } while(xhash_iter_next(s2s->in));

        /* incoming open connections (not yet streams) */
        if(xhash_iter_first(s2s->in_accept))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in_accept, (const char **) &key, &keylen, xhv.val);

                log_debug(ZONE, "checking stream connection state for incoming conn %i", conn->fd->fd);
                if(!conn->online && now > conn->init_time + s2s->check_queue) {
                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] stream initiation timed out", conn->fd->fd, conn->ip, conn->port);
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->in_accept));

    }

    /* keepalives */
    if(s2s->out_reuse) {
        if(xhash_iter_first(s2s->out_host))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);

                if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
                    log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);

                    sx_raw_write(conn->s, " ", 1);
                }
            } while(xhash_iter_next(s2s->out_host));
    } else {
        if(xhash_iter_first(s2s->out_dest))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);

                if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
                    log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);

                    sx_raw_write(conn->s, " ", 1);
                }
            } while(xhash_iter_next(s2s->out_dest));
    }

    /* idle timeouts - disconnect connections through which no packets have been sent for <idle> seconds */
    if(s2s->check_idle > 0) {

        /* outgoing connections */
        if(s2s->out_reuse) {
            if(xhash_iter_first(s2s->out_host))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking idle state for %.*s", keylen, key);
                    if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                        sx_close(conn->s);
                    }
                } while(xhash_iter_next(s2s->out_host));
        } else {
            if(xhash_iter_first(s2s->out_dest))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking idle state for %s (%s)", conn->dkey, conn->key);
                    if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                        sx_close(conn->s);
                    }
                } while(xhash_iter_next(s2s->out_dest));
        }

        /* incoming connections */
        if(xhash_iter_first(s2s->in))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
                log_debug(ZONE, "checking idle state for %.*s", keylen, key);
                if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->in));

    }

    return;
}
示例#27
0
/**
 * process commandline
 * @return: 0 to indicate that output needs to be written
 */
int _pbx_process_command(c2s_t c2s, char *cmd)
{
	jid_t jid;
	int action = 0, len;
	sess_t sess;
	unsigned char hashbuf[44] = "PBX";
	unsigned char *sesshash;

	sesshash = hashbuf+3;

	/* get command */
	if(!strncasecmp("START ", cmd, 6)) {
		cmd += 6;
		action = 1;
	}
	if(!strncasecmp("STOP ", cmd, 5)) {
		cmd += 5;
		action = 2;
	}
	if(action != 0) {
		len = _pbx_command_part_len(cmd);
		if(len > 0) {
			jid = jid_new(cmd, len);
			if(jid) {
				cmd += len;
				if(*cmd != '\0') cmd++;

				shahash_r(jid_full(jid), sesshash);
				sess = xhash_get(c2s->sessions, hashbuf);

				switch(action) {
					case 1:
						log_debug(ZONE, "STARTing session for %s/%s (%s) with commandline: %s", jid_user(jid), jid->resource, hashbuf, cmd);

						if(sess == NULL) {
						/* create new session */
							sess = (sess_t) calloc(1, sizeof(struct sess_st));
							sess->c2s = c2s;
							sess->last_activity = time(NULL);
							/* put into sessions hash */
							snprintf(sess->skey, sizeof(sess->skey), "%s", hashbuf);
							xhash_put(c2s->sessions, sess->skey, (void *) sess);
							/* generate bound resource */
							sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
							snprintf(sess->resources->c2s_id, sizeof(sess->resources->c2s_id), "%s", hashbuf);
							sess->resources->jid = jid;
							/* open SM session */
							log_write(sess->c2s->log, LOG_NOTICE, "[PBX] requesting session: jid=%s", jid_full(jid));
							sm_start(sess, sess->resources);

							/* generate presence packet to get session online */
							/* a bit hacky, but we need to emulate _some_ of the client behavior */
							sess->result = _pbx_presence_nad(1, cmd);
						}
						else {
							/* just send the presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(1, cmd));
						}

						break;

					case 2:
						log_debug(ZONE, "STOPping session for %s/%s with commandline: %s", jid_user(jid), jid->resource, cmd);

						if(sess != NULL) {
							/* send unavailable presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(0, cmd));
							/* end the session */
							sm_end(sess, sess->resources);
							xhash_zap(c2s->sessions, sess->skey);
							jqueue_push(c2s->dead_sess, (void *) sess, 0);
						}

						break;
				}

				/* TODO: respond with "OK", return 0 */
				return -1;
			}
		}
		/* TODO: generate "ERR" response, return 0 */
		return -1;
	}
	if(!strncasecmp("STATUS", cmd, 6)) {
		log_write(c2s->log, LOG_INFO, "STATUS PBX command not implemented yet");
		return -1;
	}
    return -1;
}
示例#28
0
文件: in.c 项目: zipo/zipo
static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
    conn_t in = (conn_t) arg;
    sx_buf_t buf = (sx_buf_t) data;
    int len;
    sx_error_t *sxe;
    nad_t nad;
    char ipport[INET6_ADDRSTRLEN + 17];

    switch(e) {
        case event_WANT_READ:
            log_debug(ZONE, "want read");
            mio_read(in->s2s->mio, in->fd);
            break;

        case event_WANT_WRITE:
            log_debug(ZONE, "want write");
            mio_write(in->s2s->mio, in->fd);
            break;

        case event_READ:
            log_debug(ZONE, "reading from %d", in->fd->fd);

            /* do the read */
            len = recv(in->fd->fd, buf->data, buf->len, 0);

            if(len < 0) {
                if(MIO_WOULDBLOCK) {
                    buf->len = 0;
                    return 0;
                }

                log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);

                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", in->fd->fd);

            len = send(in->fd->fd, buf->data, buf->len, 0);
            if(len >= 0) {
                log_debug(ZONE, "%d bytes written", len);
                return len;
            }

            if(MIO_WOULDBLOCK)
                return 0;

            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] write error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);

            sx_kill(s);

            return -1;

        case event_ERROR:
            sxe = (sx_error_t *) data;
            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", in->fd->fd, in->ip, in->port, sxe->generic, sxe->specific);

            break;

        case event_STREAM:
        case event_OPEN:

            log_debug(ZONE, "STREAM or OPEN event from %s port %d (id %s)", in->ip, in->port, s->id);

            /* first time, bring them online */
            if ((!in->online)||(strcmp(in->key,s->id)!=0)) { 
                log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming stream online (id %s)", in->fd->fd, in->ip, in->port, s->id);

                in->online = 1;

                /* record the id */
                if (in->key != NULL) {
                   log_debug(ZONE,"adding new SSL stream id %s for stream id %s", s->id, in->key);

                   /* remove the initial (non-SSL) stream id from the in connections hash */
                   xhash_zap(in->s2s->in, in->key);
                   free(in->key);
                }

                in->key = strdup(s->id);

                /* track it - add to open streams hash and remove from new connections hash */
                xhash_put(in->s2s->in, in->key, (void *) in);

                snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
                xhash_zap(in->s2s->in_accept, ipport);
            }  

            break;

        case event_PACKET:
            /* we're counting packets */
            in->packet_count++;
            in->s2s->packet_count++;

            nad = (nad_t) data;

            /* update last packet timestamp */
            in->last_packet = time(NULL);

            /* dialback packets */
            if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_DIALBACK) && strncmp(uri_DIALBACK, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_DIALBACK)) == 0) {
                /* only result and verify mean anything */
                if(NAD_ENAME_L(nad, 0) == 6) {
                    if(strncmp("result", NAD_ENAME(nad, 0), 6) == 0) {
                        _in_result(in, nad);
                        return 0;
                    }

                    if(strncmp("verify", NAD_ENAME(nad, 0), 6) == 0) {
                        _in_verify(in, nad);
                        return 0;
                    }
                }
                
                log_debug(ZONE, "unknown dialback packet, dropping it");

                nad_free(nad);
                return 0;
            }

            /*
             * not dialback, so it has to be a normal-ish jabber packet:
             *  - jabber:client or jabber:server
             *  - message, presence or iq
             *  - has to and from attributes
             */

            if(!(
                 /* must be jabber:client or jabber:server */
                 NAD_ENS(nad, 0) >= 0 &&
                 ((NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_CLIENT) && strncmp(uri_CLIENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_CLIENT)) == 0) ||
                 (NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_SERVER) && strncmp(uri_SERVER, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_SERVER)) == 0)) && (
                    /* can be message */
                    (NAD_ENAME_L(nad, 0) == 7 && strncmp("message", NAD_ENAME(nad, 0), 7) == 0) ||
                    /* or presence */
                    (NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) ||
                    /* or iq */
                    (NAD_ENAME_L(nad, 0) == 2 && strncmp("iq", NAD_ENAME(nad, 0), 2) == 0)
                 ) &&
                 /* to and from required */
                 nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "from", NULL) >= 0
               )) {
                log_debug(ZONE, "they sent us a non-jabber looking packet, dropping it");
                nad_free(nad);
                return 0;
            }

            _in_packet(in, nad);
            return 0;

        case event_CLOSED:
            mio_close(in->s2s->mio, in->fd);
            return -1;
    }

    return 0;
}
示例#29
0
static mod_ret_t _iq_private_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    module_t mod = mi->mod;
    int ns, elem, target, targetns;
    st_ret_t ret;
    char filter[4096];
    os_t os;
    os_object_t o;
    nad_t nad;
    pkt_t result;
    sess_t sscan;

    /* only handle private sets and gets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVATE)
        return mod_PASS;

    /* we're only interested in no to, to our host, or to us */
    if(pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0)
        return mod_PASS;

    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVATE, NULL);
    elem = nad_find_elem(pkt->nad, 1, ns, "query", 1);

    /* find the first child */
    target = elem + 1;
    while(target < pkt->nad->ecur)
    {
        if(pkt->nad->elems[target].depth > pkt->nad->elems[elem].depth)
            break;

        target++;
    }

    /* not found, so we're done */
    if(target == pkt->nad->ecur)
        return -stanza_err_BAD_REQUEST;

    /* find the target namespace */
    targetns = NAD_ENS(pkt->nad, target);

    /* gotta have a namespace */
    if(targetns < 0)
    {
        log_debug(ZONE, "no namespace specified");
        return -stanza_err_BAD_REQUEST;
    }

    log_debug(ZONE, "processing private request for %.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    /* get */
    if(pkt->type == pkt_IQ) {
#ifdef ENABLE_EXPERIMENTAL
        /* remember that this resource requested the namespace */
        if(sess->module_data[mod->index] == NULL) {
            /* create new hash if necesary */
            sess->module_data[mod->index] = xhash_new(101);
            pool_cleanup(sess->p, (void (*))(void *) xhash_free, sess->module_data[mod->index]);
        }
        xhash_put(sess->module_data[mod->index], pstrdupx(sess->p, NAD_NURI(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns)), (void *) 1);
#endif
        snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
        ret = storage_get(sess->user->sm->st, "private", jid_user(sess->jid), filter, &os);
        switch(ret) {
            case st_SUCCESS:
                if(os_iter_first(os)) {
                    o = os_iter_object(os);
                    if(os_object_get_nad(os, o, "xml", &nad)) {
                        result = pkt_new(sess->user->sm, nad_copy(nad));
                        if(result != NULL) {
                            nad_set_attr(result->nad, 1, -1, "type", "result", 6);

                            pkt_id(pkt, result);

                            pkt_sess(result, sess);

                            pkt_free(pkt);

                            os_free(os);
                
                            return mod_HANDLED;
                        }
                    }
                }

                os_free(os);

                /* drop through */
                log_debug(ZONE, "storage_get succeeded, but couldn't make packet, faking st_NOTFOUND");

            case st_NOTFOUND:

                log_debug(ZONE, "namespace not found, returning");

                /*
                 * !!! really, we should just return a 404. 1.4 just slaps a
                 *     result on the packet and sends it back. hurrah for
                 *     legacy namespaces.
                 */
                nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);

                pkt_sess(pkt_tofrom(pkt), sess);
                
                return mod_HANDLED;

            case st_FAILED:
                return -stanza_err_INTERNAL_SERVER_ERROR;

            case st_NOTIMPL:
                return -stanza_err_FEATURE_NOT_IMPLEMENTED;
        }
    }

    os = os_new();
    o = os_object_new(os);

    snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
    os_object_put(o, "ns", filter, os_type_STRING);
    os_object_put(o, "xml", pkt->nad, os_type_NAD);

    snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    ret = storage_replace(sess->user->sm->st, "private", jid_user(sess->jid), filter, os);
    os_free(os);

    switch(ret) {
        case st_FAILED:
            return -stanza_err_INTERNAL_SERVER_ERROR;

        case st_NOTIMPL:
            return -stanza_err_FEATURE_NOT_IMPLEMENTED;

        default:
            /* create result packet */
            result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL);
            pkt_id(pkt, result);
            /* and flush it to the session */
            pkt_sess(result, sess);
#ifdef ENABLE_EXPERIMENTAL
            /* push it to all resources that read this xmlns item */
            snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                /* skip our resource and those that didn't read any private-storage */
                if(sscan == sess || sscan->module_data[mod->index] == NULL)
                    continue;

                /* check whether namespace was read */
                if(xhash_get(sscan->module_data[mod->index], filter)) {
                    result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
                    if(result->from != NULL) {
                        jid_free(result->from);
                        nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
                    }
                    pkt_id_new(result);
                    pkt_sess(result, sscan);
                }
            }
#endif
            /* finally free the packet */
            pkt_free(pkt);
            return mod_HANDLED;
    }

    /* we never get here */
    return 0;
}
示例#30
0
文件: in.c 项目: zipo/zipo
/** auth requests */
static void _in_result(conn_t in, nad_t nad) {
    int attr, ns;
    jid_t from, to;
    char *rkey;
    nad_t verify;
    pkt_t pkt;
    time_t now;

    attr = nad_find_attr(nad, 0, -1, "from", NULL);
    if(attr < 0 || (from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "missing or invalid from on db result packet");
        nad_free(nad);
        return;
    }

    attr = nad_find_attr(nad, 0, -1, "to", NULL);
    if(attr < 0 || (to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "missing or invalid to on db result packet");
        jid_free(from);
        nad_free(nad);
        return;
    }

    rkey = s2s_route_key(NULL, to->domain, from->domain);

    log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] received dialback auth request for route '%s'", in->fd->fd, in->ip, in->port, rkey);

    /* get current state */
    if((conn_state_t) xhash_get(in->states, rkey) == conn_VALID) {
        log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] route '%s' is already valid: sending valid", in->fd->fd, in->ip, in->port, rkey);

        /* its already valid, just reply right now */
        stanza_tofrom(nad, 0);
        nad_set_attr(nad, 0, -1, "type", "valid", 5);
        nad->elems[0].icdata = nad->elems[0].itail = -1;
        nad->elems[0].lcdata = nad->elems[0].ltail = 0;

        sx_nad_write(in->s, nad);

        free(rkey);

        jid_free(from);
        jid_free(to);

        return;
    }

    /* not valid, so we need to verify */

    /* need the key */
    if(NAD_CDATA_L(nad, 0) <= 0) {
        log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback key given with db result packet", in->fd->fd, in->ip, in->port, rkey);
        free(rkey);
        nad_free(nad);
        jid_free(from);
        jid_free(to);
        return;
    }

    log_debug(ZONE, "requesting verification for route %s", rkey);

    /* set the route status to INPROGRESS and set timestamp */
    xhash_put(in->states, pstrdup(xhash_pool(in->states), rkey), (void *) conn_INPROGRESS);

    /* record the time that we set conn_INPROGRESS state */
    now = time(NULL);
    xhash_put(in->states_time, pstrdup(xhash_pool(in->states_time), rkey), (void *) now);

    free(rkey);

    /* new packet */
    verify = nad_new();
    ns = nad_add_namespace(verify, uri_DIALBACK, "db");

    nad_append_elem(verify, ns, "verify", 0);
    nad_append_attr(verify, -1, "to", from->domain);
    nad_append_attr(verify, -1, "from", to->domain);
    nad_append_attr(verify, -1, "id", in->s->id);
    nad_append_cdata(verify, NAD_CDATA(nad, 0), NAD_CDATA_L(nad, 0), 1);

    /* new packet */
    pkt = (pkt_t) calloc(1, sizeof(struct pkt_st));

    pkt->nad = verify;

    pkt->to = from;
    pkt->from = to;

    pkt->db = 1;

    /* its away */
    out_packet(in->s2s, pkt);

    nad_free(nad);
}