📄 dialback_in.c
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL"). You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/. * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights * * Portions created by or assigned to Jabber.com, Inc. are * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above. If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL. If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL. * * * --------------------------------------------------------------------------*//** * @file dialback_in.c * @brief handle incoming server to server connections * * In this file there are the functions used to handle the incoming connections * on the server connection manager. * * After an other server has connected to us, we have to check its identity using * dialback. If the check succeeds, we trust the peer, that it is allowed to send * messages originating at the checked domain. * * How dialback works is documented in XMPP core (RFC 3920) */#include "dialback.h"/* On incoming connections, it's our job to validate any packets we receive on this serverWe'll get: <db:result to=B from=A>...</db:result>We verify w/ the dialback process, then we'll send back: <db:result type="valid" to=A from=B/>*//** * incoming dialback streams */typedef struct dbic_struct { mio m; /**< the connection of the incoming stream */ char *id; /**< random id we assigned to this stream */ xmlnode results; /**< db:result elements that we received and that are not yet fully processed (just doing dialback on them). We add an additional attribute "key" to the element: "streamid@ourdomain/peersdomain" */ db d; /**< the dialback instance */ char *we_domain; /**< who the other end expects us to be (to attribute of stream head) for selecting a certificate at STARTTLS */} *dbic, _dbic;/** * remove a incoming connection from the hashtable of all incoming connections * waiting to be checked * * @param arg the connection that should be removed from the hash-table (type is dbic) */void dialback_in_dbic_cleanup(void *arg) { dbic c = (dbic)arg; if(xhash_get(c->d->in_id,c->id) == c) xhash_zap(c->d->in_id,c->id);}/** * create a new instance of dbic, holding information about an incoming s2s stream * * @param d the dialback instance * @param m the connection of this stream * @param we_domain what the other end expects to be our main domain (for STARTTLS) * @return the new instance of dbic */dbic dialback_in_dbic_new(db d, mio m, const char *we_domain) { dbic c; c = pmalloco(m->p, sizeof(_dbic)); c->m = m; c->id = pstrdup(m->p,dialback_randstr()); /* generate a random id for this incoming stream */ c->results = xmlnode_new_tag_pool(m->p,"r"); /* wrapper element, we add the db:result elements inside this one */ c->d = d; c->we_domain = pstrdup(m->p, we_domain); pool_cleanup(m->p,dialback_in_dbic_cleanup, (void *)c); /* remove us automatically if our memory pool is freed */ xhash_put(d->in_id, c->id, (void *)c); /* insert ourself in the hash of not yet verified connections */ log_debug2(ZONE, LOGT_IO, "created incoming connection %s from %s",c->id,m->ip); return c;}/** * callback for mio for accepted sockets that are dialback * * - We check if the other host wants to switch to using TLS. * - We check if the other host wants to verify a dialback connection we made to them * - We accept db:result element, where the peer wants to authenticate to use a domain * - We accept stanzas send from a sender the peer has been authorized to use * - Else we generate a stream:error * * @param m the connection on which the stanza has been read * @param flags the mio action, should always be MIO_XML_NODE, other actions are ignored * @param arg the dbic instance of the stream on which the stanza has been read * @param x the stanza that has been read */void dialback_in_read_db(mio m, int flags, void *arg, xmlnode x){ dbic c = (dbic)arg; miod md; jid key, from; xmlnode x2; if(flags != MIO_XML_NODE) return; log_debug2(ZONE, LOGT_IO, "dbin read dialback: fd %d packet %s",m->fd, xmlnode2str(x)); /* incoming stream error? */ if (j_strcmp(xmlnode_get_name(x), "stream:error") == 0) { spool s = spool_new(x->p); streamerr errstruct = pmalloco(x->p, sizeof(_streamerr)); char *errmsg = NULL; xstream_parse_error(x->p, x, errstruct); xstream_format_error(s, errstruct); errmsg = spool_print(s); switch (errstruct->severity) { case normal: log_debug2(ZONE, LOGT_IO, "stream error on incoming db conn from %s: %s", mio_ip(m), errmsg); break; case configuration: case feature_lack: case unknown: log_warn(c->d->i->id, "received stream error on incoming db conn from %s: %s", mio_ip(m), errmsg); break; case error: default: log_error(c->d->i->id, "received stream error on incoming db conn from %s: %s", mio_ip(m), errmsg); } mio_close(m); return; } /* incoming starttls */ if (j_strcmp(xmlnode_get_name(x), "starttls") == 0 && j_strcmp(xmlnode_get_attrib(x, "xmlns"), NS_XMPP_TLS) == 0) { /* starting TLS possible? */#ifdef HAVE_SSL if (mio_ssl_starttls_possible(m, c->we_domain)) { /* ACK the start */ xmlnode proceed = xmlnode_new_tag("proceed"); xmlnode_put_attrib(proceed, "xmlns", NS_XMPP_TLS); mio_write(m, proceed, NULL, 0); /* start TLS on this connection */ if (mio_xml_starttls(m, 0, c->we_domain) != 0) { /* STARTTLS failed */ mio_close(m); return; } /* we get a stream header again */ mio_reset(m, dialback_in_read, (void *)c->d); return; } else {#endif /* NACK */ mio_write(m, NULL, "<failure xmlns='" NS_XMPP_TLS "'/></stream:stream>", -1); mio_close(m); xmlnode_free(x); return;#ifdef HAVE_SSL }#endif } /* incoming verification request, check and respond */ if(j_strcmp(xmlnode_get_name(x),"db:verify") == 0) { char *is = xmlnode_get_data(x); /* what the peer tries to verify */ char *should = dialback_merlin(xmlnode_pool(x), c->d->secret, xmlnode_get_attrib(x,"from"), xmlnode_get_attrib(x,"id")); if(j_strcmp(is, should) == 0) { xmlnode_put_attrib(x,"type","valid"); } else { xmlnode_put_attrib(x,"type","invalid"); log_notice(c->d->i->id, "Is somebody faking us? %s tried to verify the invalid dialback key %s (should be %s)", xmlnode_get_attrib(x, "from"), is, should); } /* reformat the packet reply */ jutil_tofrom(x); while((x2 = xmlnode_get_firstchild(x)) != NULL) xmlnode_hide(x2); /* hide the contents */ mio_write(m, x, NULL, 0); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -