📄 dialback_in.c
字号:
} /* valid sender/recipient jids */ if((from = jid_new(xmlnode_pool(x),xmlnode_get_attrib(x,"from"))) == NULL || (key = jid_new(xmlnode_pool(x),xmlnode_get_attrib(x,"to"))) == NULL) { mio_write(m, NULL, "<stream:error><improper-addressing xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Invalid Packets Recieved!</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } /* make our special key */ jid_set(key,from->server,JID_RESOURCE); jid_set(key,c->id,JID_USER); /* special user of the id attrib makes this key unique */ /* incoming result, track it and forward on */ if(j_strcmp(xmlnode_get_name(x),"db:result") == 0) { /* store the result in the connection, for later validation */ xmlnode_put_attrib(xmlnode_insert_tag_node(c->results, x),"key",jid_full(key)); /* send the verify back to them, on another outgoing trusted socket, via deliver (so it is real and goes through dnsrv and anything else) */ x2 = xmlnode_new_tag_pool(xmlnode_pool(x),"db:verify"); xmlnode_put_attrib(x2,"to",xmlnode_get_attrib(x,"from")); xmlnode_put_attrib(x2,"ofrom",xmlnode_get_attrib(x,"to")); xmlnode_put_attrib(x2,"from",c->d->i->id); /* so bounces come back to us to get tracked */ xmlnode_put_attrib(x2,"dnsqueryby",c->d->i->id); /* so this instance gets the DNS result back */ xmlnode_put_attrib(x2,"id",c->id); xmlnode_insert_node(x2,xmlnode_get_firstchild(x)); /* copy in any children */ deliver(dpacket_new(x2),c->d->i); return; } /* hmm, incoming packet on dialback line, there better be a valid entry for it or else! */ md = xhash_get(c->d->in_ok_db, jid_full(key)); if(md == NULL || md->m != m) { /* dude, what's your problem! *click* */ log_notice(c->d->i->id, "Received unauthorized stanza for/from %s: %s", jid_full(key), xmlnode2str(x)); mio_write(m, NULL, "<stream:error><invalid-from xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Invalid Packets Recieved!</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } dialback_miod_read(md, x);}/** * callback for mio for accepted sockets * * Our task is: * - Verify the stream root element * - Check the type of server-to-server stream (we support: dialback, xmpp+dialback) * - For xmpp+dialback: send stream:features (we support: starttls) * - Reset the mio callback. Stanzas are handled by dialback_in_read_db() * * @param m the connection on which the stream root element has been received * @param the mio action, everything but MIO_XML_ROOT is ignored * @param arg the db instance * @param x the stream root element */void dialback_in_read(mio m, int flags, void *arg, xmlnode x){ db d = (db)arg; xmlnode x2; miod md; jid key; char strid[10]; dbic c; int version = 0; const char *dbns = NULL; log_debug2(ZONE, LOGT_IO, "dbin read: fd %d flag %d",m->fd, flags); if(flags != MIO_XML_ROOT) return; /* validate namespace */ if(j_strcmp(xmlnode_get_attrib(x,"xmlns"),"jabber:server") != 0) { mio_write(m, NULL, "<stream:stream><stream:error><bad-namespace-prefix xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Invalid Stream Header!</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } snprintf(strid, 9, "%X", m); /* for hashes for later */ /* check stream version */ version = j_atoi(xmlnode_get_attrib(x, "version"), 0); dbns = xmlnode_get_attrib(x, "xmlns:db"); /* deprecated non-dialback protocol, reject connection */ if(version < 1 && dbns == NULL) { key = jid_new(xmlnode_pool(x), xmlnode_get_attrib(x, "to")); mio_write(m,NULL, xstream_header_char(xstream_header("jabber:server", NULL, jid_full(key))), -1); 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'>Legacy Access Denied!</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } /* peer is XMPP server but does not support dialback (probably it implements only SASL) */ if (dbns == NULL) { 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. You need to support dialback to communicate with this host.</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } /* check namespaces */ if (j_strcmp(dbns, NS_DIALBACK) != 0) { mio_write(m, NULL, "<stream:error><invalid-namespace xmlns='urn:ietf:params:xml:ns:xmpp-streams'><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>Sorry, but don't you think, that xmlns:db should declare the namespace jabber:server:dialback?</text></stream:error>", -1); mio_close(m); xmlnode_free(x); return; } /* dialback connection */ c = dialback_in_dbic_new(d, m, xmlnode_get_attrib(x, "to")); /* write our header */ x2 = xstream_header(NS_SERVER, NULL, c->we_domain); xmlnode_put_attrib(x2, "xmlns:db", NS_DIALBACK); /* flag ourselves as dialback capable */ if (version >= 1) { xmlnode_put_attrib(x2, "version", "1.0"); /* flag us as XMPP capable */ } xmlnode_put_attrib(x2,"id",c->id); /* send random id as a challenge */ mio_write(m,NULL, xstream_header_char(x2), -1); xmlnode_free(x2); xmlnode_free(x); /* reset to a dialback packet reader */ mio_reset(m, dialback_in_read_db, (void *)c); /* write stream features */ if (version >= 1) { xmlnode features = xmlnode_new_tag("stream:features");#ifdef HAVE_SSL if (mio_ssl_starttls_possible(m, c->we_domain)) { xmlnode starttls = NULL; starttls = xmlnode_insert_tag(features, "starttls"); xmlnode_put_attrib(starttls, "xmlns", NS_XMPP_TLS); }#endif mio_write(m, features, NULL, 0); }}/** * Handle db:verify packets, that we got as a result to our dialback to the authoritive server. * * We expect the to attribute to be our name and the from attribute to be the remote name. * * We have to do: * - Check if there is (still) a connection for this dialback result * - If the we got type='valid' we have to authorize the peer to use the verified sender address * - Inform the peer about the result * * @note dialback_out_connection_cleanup() calls this function as well to trash pending verifies. * In that case we don't get the db:verify result, but the db:verify query (no type attribute set). * * @param d the db instance * @param x the db:verify answer packet */void dialback_in_verify(db d, xmlnode x){ dbic c; xmlnode x2; jid key; const char *type = NULL; log_debug2(ZONE, LOGT_AUTH, "dbin validate: %s",xmlnode2str(x)); /* check for the stored incoming connection first */ if((c = xhash_get(d->in_id, xmlnode_get_attrib(x,"id"))) == NULL) { log_warn(d->i->id, "Dropping a db:verify answer, we don't have a waiting incoming connection (anymore?) for this id: %s", xmlnode2str(x)); xmlnode_free(x); return; } /* make a key of the sender/recipient addresses on the packet */ key = jid_new(xmlnode_pool(x),xmlnode_get_attrib(x,"to")); jid_set(key,xmlnode_get_attrib(x,"from"),JID_RESOURCE); jid_set(key,c->id,JID_USER); /* special user of the id attrib makes this key unique */ if((x2 = xmlnode_get_tag(c->results, spools(xmlnode_pool(x),"?key=",jid_full(key),xmlnode_pool(x)))) == NULL) { log_warn(d->i->id, "Dropping a db:verify answer, we don't have a waiting incoming <db:result/> query (anymore?) for this to/from pair: %s", xmlnode2str(x)); xmlnode_free(x); return; } /* hide the waiting db:result, it has been processed now */ xmlnode_hide(x2); /* get type of db:verify result */ type = xmlnode_get_attrib(x, "type"); /* rewrite the result */ x2 = xmlnode_new_tag_pool(xmlnode_pool(x),"db:result"); xmlnode_put_attrib(x2,"to",xmlnode_get_attrib(x,"from")); xmlnode_put_attrib(x2,"from",xmlnode_get_attrib(x,"to")); xmlnode_put_attrib(x2,"type", type != NULL ? type : "invalid"); /* valid requests get the honour of being miod */ type = xmlnode_get_attrib(x, "type"); if(j_strcmp(type,"valid") == 0) dialback_miod_hash(dialback_miod_new(c->d, c->m), c->d->in_ok_db, key); else log_warn(d->i->id, "Denying peer to use the domain %s. Dialback failed (%s): %s", key->resource, type ? type : "timeout", xmlnode2str(x2)); /* rewrite and send on to the socket */ mio_write(c->m, x2, NULL, -1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -