📄 dialback_out.c
字号:
/* deprecated non-dialback protocol, reject connection */ if (version < 1 && dbns == NULL) { /* Muahahaha! you suck! *click* */ log_notice(c->key->server,"Legacy server access denied"); mio_write(m, NULL, "<stream:error><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Legacy Access Denied!</text></stream:error>", -1); mio_close(m); break; } /* peer is XMPP server, but does not support dialback */ if (dbns == NULL) { log_notice(c->d->i->id, "We cannot send to %s. This XMPP server does not support dialback.", c->key->server); mio_write(m, NULL, "<stream:error><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Sorry, we only support dialback to 'authenticate' our peers. SASL is not supported by us. It seems we cannot communicate to you :-(</text></stream:error>", -1); mio_close(m); break; } /* create and send our result request to initiate dialback for non XMPP-sessions (XMPP has to wait for stream features) */ if (version < 1) { log_debug2(ZONE, LOGT_IO, "pre-XMPP stream could now send <db:result/>"); if (c->db_state == want_request) { cur = xmlnode_new_tag("db:result"); xmlnode_put_attrib(cur, "to", c->key->server); xmlnode_put_attrib(cur, "from", c->key->resource); xmlnode_insert_cdata(cur, dialback_merlin(xmlnode_pool(cur), c->d->secret, c->key->server, c->stream_id), -1); mio_write(m,cur, NULL, 0); c->db_state = sent_request; c->connection_state = sent_db_request; log_debug2(ZONE, LOGT_IO, "... and we wanted ... and we sent <db:result/>"); } else if (c->db_state == not_requested) { c->db_state = could_request; log_debug2(ZONE, LOGT_IO, "... but we didn't want yet"); } } else { c->connection_state = waiting_features; } /* well, we're connected to a dialback server, we can at least send verify requests now */ c->m = m; if (version < 1) { for(cur = xmlnode_get_firstchild(c->verifies); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { mio_write(m, xmlnode_dup(cur), NULL, -1); xmlnode_hide(cur); } } break; case MIO_XML_NODE: /* watch for stream errors */ 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; /* generate error message */ xstream_parse_error(x->p, x, errstruct); xstream_format_error(s, errstruct); errmsg = spool_print(s); /* append error message to connect_results */ if (c->connect_results != NULL && errmsg != NULL) { spool_add(c->connect_results, " ("); spool_add(c->connect_results, pstrdup(c->connect_results->p, errmsg)); spool_add(c->connect_results, ")"); } /* logging */ switch (errstruct->severity) { case normal: log_debug2(ZONE, LOGT_IO, "stream error on outgoing %s conn to %s (%s): %s", c->xmpp_version < 1 ? "preXMPP" : "XMPP1.0", mio_ip(m), jid_full(c->key), errmsg); break; case configuration: case feature_lack: case unknown: log_warn(c->d->i->id, "received stream error on outgoing %s conn to %s (%s): %s", c->xmpp_version < 1 ? "preXMPP" : "XMPP1.0", mio_ip(m), jid_full(c->key), errmsg); break; case error: default: log_error(c->d->i->id, "received stream error on outgoing %s conn to %s (%s): %s", c->xmpp_version < 1 ? "preXMPP" : "XMPP1.0", mio_ip(m), jid_full(c->key), errmsg); } mio_close(m); break; } /* watch for stream:features */ if (j_strcmp(xmlnode_get_name(x), "stream:features") == 0) { c->connection_state = got_features;#ifdef HAVE_SSL /* is starttls supported? */ if (xmlnode_get_tag(x, "starttls?xmlns=" NS_XMPP_TLS) != NULL) { /* don't start if forbidden by caller (configuration) */ if (c->xmpp_no_tls) { log_notice(c->d->i->id, "Server %s advertized starttls, but disabled by our configuration.", c->key->server); } else if (mio_ssl_starttls_possible(m, c->key->resource)) { /* our side is prepared for starttls */ xmlnode starttls = NULL; /* request to start tls on this connection */ log_debug2(ZONE, LOGT_IO, "requesting starttls for an outgoing connection to %s", c->key->server); starttls = xmlnode_new_tag("starttls"); xmlnode_put_attrib(starttls, "xmlns", NS_XMPP_TLS); mio_write(m, starttls, NULL, 0); break; } }#endif /* HAVE_SSL */ /* no stream:feature we'd like to use, we can now send the outstanding db:result - or we could, if we did not want */ log_debug2(ZONE, LOGT_IO, "XMPP-stream: we could now send <db:result/>s"); if (c->db_state == want_request) { cur = xmlnode_new_tag("db:result"); xmlnode_put_attrib(cur, "to", c->key->server); xmlnode_put_attrib(cur, "from", c->key->resource); xmlnode_insert_cdata(cur, dialback_merlin(xmlnode_pool(cur), c->d->secret, c->key->server, c->stream_id), -1); mio_write(m,cur, NULL, 0); c->db_state = sent_request; c->connection_state = sent_db_request; log_debug2(ZONE, LOGT_IO, "... and we wanted ... and we did sent a <db:result/>"); } else if (c->db_state == not_requested) { c->db_state = could_request; log_debug2(ZONE, LOGT_IO, "... but we did not want to"); } /* and we can send the verify requests */ for(cur = xmlnode_get_firstchild(c->verifies); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { mio_write(m, xmlnode_dup(cur), NULL, -1); xmlnode_hide(cur); } /* finished processing stream:features */ break; }#ifdef HAVE_SSL /* watch for positive starttls result */ if (j_strcmp(xmlnode_get_name(x), "proceed") == 0 && j_strcmp(xmlnode_get_attrib(x, "xmlns"), NS_XMPP_TLS) == 0) { /* start tls on our side */ if (mio_xml_starttls(m, 1, c->key->resource)) { /* starting tls failed */ log_warn(c->d->i->id, "Starting TLS on an outgoing s2s to %s failed on our side (%s).", c->key->server, c->key->resource); mio_close(m); break; } /* we forget about the headers we got now again */ c->connection_state = connected; /* send stream header again */ dialback_out_read(m, MIO_NEW, c, NULL); break; } /* watch for negative starttls result */ if (j_strcmp(xmlnode_get_name(x), "failure") == 0 && j_strcmp(xmlnode_get_attrib(x, "xmlns"), NS_XMPP_TLS) == 0) { log_warn(c->d->i->id, "Starting TLS on an outgoing s2s to %s failed on the other side.", c->key->server); mio_close(m); break; }#endif /* HAVE_SSL */ /* watch for a valid result, then we're set to rock! */ if(j_strcmp(xmlnode_get_name(x),"db:result") == 0) { if(j_strcmp(xmlnode_get_attrib(x,"from"),c->key->server) != 0 || j_strcmp(xmlnode_get_attrib(x,"to"),c->key->resource) != 0) { /* naughty... *click* */ log_warn(c->d->i->id,"Received illegal dialback validation remote %s != %s or to %s != %s",c->key->server,xmlnode_get_attrib(x,"from"),c->key->resource,xmlnode_get_attrib(x,"to")); mio_write(m, NULL, "<stream:error><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Invalid Dialback Result</text></stream:error>", -1); mio_close(m); break; } /* process the returned result */ if(j_strcmp(xmlnode_get_attrib(x,"type"),"valid") == 0) { c->connection_state = db_succeeded; mio_reset(m, dialback_out_read_db, (void *)(c->d)); /* different handler now */ md = dialback_miod_new(c->d, m); /* set up the mio wrapper */ dialback_miod_hash(md, c->d->out_ok_db, c->key); /* this registers us to get stuff directly now */ /* flush the queue of packets */ dialback_out_qflush(md, c->q); c->q = NULL; /* we are connected, and can trash this now */ dialback_out_connection_cleanup(c); break; } /* something went wrong, we were invalid? */ c->connection_state = db_failed; if (c->connect_results != NULL) { char *type_attribute = pstrdup(c->connect_results->p, xmlnode_get_attrib(x, "type")); spool_add(c->connect_results, " (dialback result: "); spool_add(c->connect_results, type_attribute ? type_attribute : "no type attribute"); spool_add(c->connect_results, ")"); } log_alert(c->d->i->id,"We were told by %s that our sending name %s is invalid, either something went wrong on their end, we tried using that name improperly, or dns does not resolve to us",c->key->server,c->key->resource); /* close the stream (in former times we sent a stream error, but I think we shouldn't. There is stream fault by the other entity!) */ mio_write(m, NULL, "</stream:stream>", -1); mio_close(m); break; } /* otherwise it's either a verify response, or bust! */ if(j_strcmp(xmlnode_get_name(x),"db:verify") == 0) { dialback_in_verify(c->d, x); return; } log_warn(c->d->i->id,"Dropping connection due to illegal incoming packet on an unverified socket from %s to %s (%s): %s",c->key->resource,c->key->server,m->ip,xmlnode2str(x)); mio_write(m, NULL, "<stream:error><not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Not Allowed to send data on this socket!</text></stream:error>", -1); mio_close(m); break; case MIO_CLOSED: /* add the connect error message to the list of messages for the tried hosts */ if (c->connect_results != NULL) { spool_add(c->connect_results, mio_connect_errmsg(m)); } if(c->ip == NULL) { dialback_out_connection_cleanup(c); /* buh bye! */ } else { if (c->connect_results != NULL) { spool_add(c->connect_results, " / "); } dialback_out_connect(c); /* this one failed, try another */ } return; default: return; } xmlnode_free(x);}/** * callback for walking the connecting hash tree: timing out connections that did not get * authorized in time (default is 30 seconds, can be configured with <queuetimeout/> in * the configuration file) * * @param h the hash containing all pending connections * @param key destination/source address * @param data the dboc * @param arg unused/ignored */void _dialback_out_beat_packets(xht h, const char *key, void *data, void *arg){ dboc c = (dboc)data; dboq cur, next, last; int now = time(NULL); char *bounce_reason = NULL; /* time out individual queue'd packets */ cur = c->q; while(cur != NULL) { if((now - cur->stamp) <= c->d->timeout_packets) { last = cur; cur = cur->next; continue; } /* timed out sukkah! */ next = cur->next; if(c->q == cur) c->q = next; else last->next = next; if (bounce_reason == NULL) { spool errmsg = spool_new(c->p); spool_add(errmsg, "Server connect timeout while "); spool_add(errmsg, dialback_out_connection_state_string(c->connection_state)); if (c->connect_results != NULL) { spool_add(errmsg, ": "); spool_add(errmsg, spool_print(c->connect_results)); } bounce_reason = spool_print(errmsg); } deliver_fail(dpacket_new(cur->x), bounce_reason ? bounce_reason : "Server Connect Timeout"); cur = next; }}/** * start walking the connection hash tree, to see if connections dig not get authorizsed in time * * @param db the dialback instance * @return allways r_DONE */result dialback_out_beat_packets(void *arg){ db d = (db)arg; xhash_walk(d->out_connecting,_dialback_out_beat_packets,NULL); return r_DONE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -