PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/jserver/osrf_chat.c

https://gitlab.com/evergreen-bjwebb/opensrf-debian
C | 1082 lines | 746 code | 221 blank | 115 comment | 135 complexity | fab4f57932fa76b5ca18a90a9be1cba8 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /*
  2. Copyright (C) 2005 Georgia Public Library Service
  3. Bill Erickson <billserickson@gmail.com>
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. */
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <time.h>
  16. /* opensrf headers */
  17. #include "opensrf/utils.h"
  18. #include "opensrf/osrf_hash.h"
  19. #include "opensrf/osrf_list.h"
  20. #include "opensrf/log.h"
  21. #include "opensrf/xml_utils.h"
  22. #include "opensrf/socket_bundle.h"
  23. #include "opensrf/sha.h"
  24. #include "opensrf/transport_message.h"
  25. /* libxml2 headers */
  26. #include <libxml/parser.h>
  27. #include <libxml/tree.h>
  28. #include <libxml/globals.h>
  29. #include <libxml/xmlerror.h>
  30. #include "osrf_chat.h"
  31. /* client to server XML */
  32. #define OSRF_CHAT_START_STREAM "<?xml version='1.0'?><stream:stream "\
  33. "xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' "\
  34. "from='%s' version='1.0' id='%s'>"
  35. #define OSRF_CHAT_PARSE_ERROR "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
  36. "version='1.0'><stream:error xmlns:stream='http://etherx.jabber.org/streams'>"\
  37. "<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>" \
  38. "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>syntax " \
  39. "error</text></stream:error></stream:stream>"
  40. #define OSRF_CHAT_LOGIN_OK "<iq xmlns='jabber:client' id='0123456789' type='result'/>"
  41. #define OSRF_CHAT_NO_RECIPIENT "<message xmlns='jabber:client' type='error' from='%s' to='%s'>"\
  42. "<error type='cancel' code='404'><item-not-found " \
  43. "xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"\
  44. "</error><body>NOT ADDING BODY</body></message>"
  45. /* ---------------------------------------------------------------------------------- */
  46. /* server to server XML */
  47. // client to server init
  48. #define OSRF_CHAT_S2S_INIT "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
  49. "xmlns='jabber:server' xmlns:db='jabber:server:dialback'>"
  50. // server to client challenge
  51. #define OSRF_CHAT_S2S_CHALLENGE "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
  52. "xmlns='jabber:server' id='%s' xmlns:db='jabber:server:dialback'>"
  53. // client to server challenge response
  54. #define OSRF_CHAT_S2S_RESPONSE "<db:result xmlns:db='jabber:server:dialback' to='%s' from='%s'>%s</db:result>"
  55. // server to client verify
  56. #define OSRF_CHAT_S2S_VERIFY_REQUEST \
  57. "<db:verify xmlns:db='jabber:server:dialback' id='%s' from='%s' to='%s'>%s</db:verify>"
  58. // client to server verify response
  59. #define OSRF_CHAT_S2S_VERIFY_RESPONSE \
  60. "<db:verify xmlns:db='jabber:server:dialback' type='valid' to='%s' from='%s' id='%s'/>"
  61. //server to client final verification
  62. #define OSRF_CHAT_S2S_VERIFY_FINAL \
  63. "<db:result xmlns:db='jabber:server:dialback' type='valid' from='%s' to ='%s'/>"
  64. /* c2s states */
  65. #define OSRF_CHAT_STATE_NONE 0 /* blank node */
  66. #define OSRF_CHAT_STATE_CONNECTING 1 /* we have received the opening stream */
  67. #define OSRF_CHAT_STATE_CONNECTED 2 /* we have sent the OK/result message */
  68. /* s2s states */
  69. #define OSRF_CHAT_STATE_S2S_CHALLENGE 4 /* client : waiting for the challenge */
  70. #define OSRF_CHAT_STATE_S2S_RESPONSE 5 /* server : waiting for the challenge response */
  71. #define OSRF_CHAT_STATE_S2S_VERIFY 6 /* client : waiting for verify message */
  72. #define OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE 7 /* server : waiting for verify response */
  73. #define OSRF_CHAT_STATE_S2S_VERIFY_FINAL 8 /* client : waiting for final verify response */
  74. /* xml parser states */
  75. #define OSRF_CHAT_STATE_INMESSAGE 1
  76. #define OSRF_CHAT_STATE_INIQ 2
  77. #define OSRF_CHAT_STATE_INUSERNAME 4
  78. #define OSRF_CHAT_STATE_INRESOURCE 8
  79. #define OSRF_CHAT_STATE_INS2SRESULT 16
  80. #define OSRF_CHAT_STATE_INS2SVERIFY 32
  81. struct osrfChatNodeStruct {
  82. int sockid; /* our socket id */
  83. int type; /* 0 for client, 1 for server */
  84. /* for clients this is the full JID of the client that connected to this server.
  85. for servers it's the domain (network id) of the server we're connected to */
  86. char* remote;
  87. int state; /* for the various stages of connectivity and parsing */
  88. int xmlstate; /* what part of the message are we currently parsing */
  89. int inparse; /* true if we are currently parsing a chunk of XML. If so, we can't free the node.
  90. we have to cache it and free it later */
  91. char* to; /* The JID where the current message is being routed */
  92. char* domain; /* the domain, resource, and username of our connecting entity. */
  93. char* resource; /* for s2s nodes, resource and username will be empty . */
  94. char* username;
  95. char* authkey; /* when doing any auth negotiation, this is the auth seed hash */
  96. osrfList* msgs; /* if we're a server node we may have a pool of messages
  97. waiting to be delivered */
  98. xmlParserCtxtPtr parserCtx;
  99. xmlDocPtr msgDoc;
  100. osrfChatServer* parent;
  101. };
  102. /*
  103. struct __osrfChatS2SMessageStruct {
  104. char* toAddr;
  105. char* msgXML;
  106. };
  107. typedef struct __osrfChatS2SMessageStruct osrfChatS2SMessage;
  108. */
  109. struct osrfChatServerStruct {
  110. osrfHash* nodeHash; /* sometimes we need hash (remote id) lookup,
  111. sometimes we need socket id lookup */
  112. osrfList* nodeList;
  113. osrfList* deadNodes; /* collection of nodes to free when we get a chance */
  114. socket_manager* mgr;
  115. char* secret; /* shared S2S secret */
  116. char* domain; /* the domain this server hosts */
  117. int s2sport;
  118. int port;
  119. };
  120. //static void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode );
  121. static osrfChatNode* osrfNewChatS2SNode( const char* domain, const char* remote );
  122. static osrfChatNode* osrfNewChatNode( int sockid, const char* domain );
  123. static void osrfChatNodeFree( void* node );
  124. static void osrfChatHandleData( void* cs,
  125. socket_manager* mgr, int sockid, char* data, int parent_id );
  126. /* removes dead nodes that have been cached due to mid-parse removals */
  127. static void osrfChatCleanupClients( osrfChatServer* server );
  128. static osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid );
  129. static void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node );
  130. /** pushes new data into the nodes parser */
  131. static int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data );
  132. static void osrfChatSocketClosed( void* blob, int sockid );
  133. /**
  134. Sends msgXML to the client with remote 'toAddr'. If we have no connection
  135. to 'toAddr' and the domain for 'toAddr' is different from our hosted domain
  136. we attempt to send the message to the domain found in 'toAddr'.
  137. */
  138. static int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, const char* toAddr,
  139. const char* fromAddr, const char* msgXML );
  140. static int osrfChatSendRaw( osrfChatNode* node, const char* xml );
  141. static void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node );
  142. /* initializes the negotiation of a server to server connection */
  143. static int osrfChatInitS2S( osrfChatServer* cs, const char* remote, const char* toAddr,
  144. const char* msgXML );
  145. static int osrfChatHandleNewConnection( osrfChatNode* node, const char* name,
  146. const xmlChar** atts );
  147. static int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts );
  148. static int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts );
  149. static int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name,
  150. const xmlChar** atts );
  151. //static int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name,
  152. // const xmlChar** atts );
  153. static int osrfChatHandleS2SConnected( osrfChatNode* node, const char* nm, const xmlChar**atts );
  154. static void osrfChatS2SMessageFree(void* n);
  155. /* generates a random sha1 hex key */
  156. static char* osrfChatMkAuthKey();
  157. static void osrfChatStartStream( void* blob );
  158. static void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts );
  159. static void osrfChatEndElement( void* blob, const xmlChar* name );
  160. static void osrfChatHandleCharacter(void* blob, const xmlChar *ch, int len);
  161. static void osrfChatParseError( void* blob, const char* msg, ... );
  162. static xmlSAXHandler osrfChatSaxHandlerStruct = {
  163. NULL, /* internalSubset */
  164. NULL, /* isStandalone */
  165. NULL, /* hasInternalSubset */
  166. NULL, /* hasExternalSubset */
  167. NULL, /* resolveEntity */
  168. NULL, /* getEntity */
  169. NULL, /* entityDecl */
  170. NULL, /* notationDecl */
  171. NULL, /* attributeDecl */
  172. NULL, /* elementDecl */
  173. NULL, /* unparsedEntityDecl */
  174. NULL, /* setDocumentLocator */
  175. osrfChatStartStream, /* startDocument */
  176. NULL, /* endDocument */
  177. osrfChatStartElement, /* startElement */
  178. osrfChatEndElement, /* endElement */
  179. NULL, /* reference */
  180. osrfChatHandleCharacter, /* characters */
  181. NULL, /* ignorableWhitespace */
  182. NULL, /* processingInstruction */
  183. NULL, /* comment */
  184. osrfChatParseError, /* xmlParserWarning */
  185. osrfChatParseError, /* xmlParserError */
  186. NULL, /* xmlParserFatalError : unused */
  187. NULL, /* getParameterEntity */
  188. NULL, /* cdataBlock; */
  189. NULL, /* externalSubset; */
  190. 1,
  191. NULL,
  192. NULL, /* startElementNs */
  193. NULL, /* endElementNs */
  194. NULL /* xmlStructuredErrorFunc */
  195. };
  196. static const xmlSAXHandlerPtr osrfChatSaxHandler = &osrfChatSaxHandlerStruct;
  197. #ifndef HOST_NAME_MAX
  198. #define HOST_NAME_MAX 256
  199. #endif
  200. static int osrfChatXMLErrorOcurred = 0;
  201. /* This is used by code in osrfChatPushData, but that code is
  202. currently commented out. Uncomment the next line if needed. */
  203. //static int osrfChatClientSentDisconnect = 0;
  204. /* shorter version of strcmp */
  205. static int eq(const char* a, const char* b) {
  206. return (a && b && !strcmp(a,b));
  207. }
  208. //#define eq(a,b) ((a && b && !strcmp(a,b)) ? 1 : 0)
  209. /* gnarly debug function */
  210. static void chatdbg( osrfChatServer* server ) {
  211. if(!server) return;
  212. return; /* heavy logging, should only be used in heavy debug mode */
  213. growing_buffer* buf = buffer_init(256);
  214. buffer_add(buf, "---------------------------------------------------------------------\n");
  215. buffer_fadd(buf,
  216. "ChopChop Debug:\n"
  217. "Connections: %lu\n"
  218. "Named nodes in hash: %lu\n"
  219. "Domain: %s\n"
  220. "Port: %d\n"
  221. "S2S Port: %d\n"
  222. "-------------------------------------------------------\n",
  223. osrfListGetCount(server->nodeList), osrfHashGetCount(server->nodeHash),
  224. server->domain, server->port, server->s2sport );
  225. osrfListIterator* itr = osrfNewListIterator(server->nodeList);
  226. osrfChatNode* node;
  227. while( (node = osrfListIteratorNext(itr)) ) {
  228. buffer_fadd( buf,
  229. "sockid: %d\n"
  230. "Remote: %s\n"
  231. "State: %d\n"
  232. "XMLState: %d\n"
  233. "In Parse: %d\n"
  234. "to: %s\n"
  235. "Resource: %s\n"
  236. "Username: %s\n"
  237. "Domain: %s\n"
  238. "Authkey: %s\n"
  239. "type: %d\n"
  240. "-------------------------------------------------------\n",
  241. node->sockid, node->remote, node->state, node->xmlstate, node->inparse,
  242. node->to, node->resource, node->username, node->domain, node->authkey, node->type );
  243. }
  244. osrfLogDebug( OSRF_LOG_MARK, "DEBUG:\n%s", buf->buf );
  245. buffer_free(buf);
  246. osrfListIteratorFree(itr);
  247. }
  248. osrfChatServer* osrfNewChatServer( const char* domain, const char* secret, int s2sport ) {
  249. if(!(domain && secret)) return NULL;
  250. osrfChatServer* server = safe_malloc(sizeof(osrfChatServer));
  251. server->nodeHash = osrfNewHash();
  252. server->nodeList = osrfNewList();
  253. server->deadNodes = osrfNewList();
  254. server->nodeList->freeItem = &osrfChatNodeFree;
  255. server->domain = strdup(domain);
  256. server->secret = strdup(secret);
  257. server->s2sport = s2sport;
  258. server->port = 0;
  259. // Build socket manager
  260. server->mgr = safe_malloc(sizeof(socket_manager));
  261. server->mgr->data_received = &osrfChatHandleData;
  262. server->mgr->socket = NULL;
  263. server->mgr->blob = server;
  264. server->mgr->on_socket_closed = &osrfChatSocketClosed;
  265. return server;
  266. }
  267. static void osrfChatCleanupClients( osrfChatServer* server ) {
  268. if(!server) return;
  269. osrfListFree(server->deadNodes);
  270. server->deadNodes = osrfNewList();
  271. }
  272. static osrfChatNode* osrfNewChatNode( int sockid, const char* domain ) {
  273. if(sockid < 1 || !domain) return NULL;
  274. osrfChatNode* node = safe_malloc(sizeof(osrfChatNode));
  275. node->sockid = 0;
  276. node->remote = NULL;
  277. node->state = OSRF_CHAT_STATE_NONE;
  278. node->xmlstate = 0;
  279. node->inparse = 0;
  280. node->msgs = NULL; /* only s2s nodes cache messages */
  281. node->parserCtx = xmlCreatePushParserCtxt(osrfChatSaxHandler, node, "", 0, NULL);
  282. node->msgDoc = xmlNewDoc(BAD_CAST "1.0");
  283. node->domain = strdup(domain);
  284. xmlKeepBlanksDefault(0);
  285. node->authkey = NULL;
  286. node->username = NULL;
  287. node->resource = NULL;
  288. node->to = NULL;
  289. node->type = 0;
  290. node->parent = NULL;
  291. return node;
  292. }
  293. static osrfChatNode* osrfNewChatS2SNode( const char* domain, const char* remote ) {
  294. if(!(domain && remote)) return NULL;
  295. osrfChatNode* n = osrfNewChatNode( 1, domain );
  296. n->state = OSRF_CHAT_STATE_S2S_CHALLENGE;
  297. n->sockid = -1;
  298. n->remote = strdup(remote);
  299. n->msgs = osrfNewList();
  300. n->msgs->freeItem = &osrfChatS2SMessageFree;
  301. n->type = 1;
  302. return n;
  303. }
  304. void osrfChatS2SMessageFree(void* n) {
  305. free(n);
  306. }
  307. static void osrfChatNodeFree( void* node ) {
  308. if(!node) return;
  309. osrfChatNode* n = (osrfChatNode*) node;
  310. /* we can't free messages that are mid-parse because the
  311. we can't free the parser context */
  312. if(n->inparse) {
  313. n->inparse = 0;
  314. osrfListPush(n->parent->deadNodes, n);
  315. return;
  316. }
  317. free(n->remote);
  318. free(n->to);
  319. free(n->username);
  320. free(n->resource);
  321. free(n->domain);
  322. free(n->authkey);
  323. osrfListFree(n->msgs);
  324. if(n->parserCtx) {
  325. xmlFreeDoc(n->parserCtx->myDoc);
  326. xmlFreeParserCtxt(n->parserCtx);
  327. }
  328. xmlFreeDoc(n->msgDoc);
  329. free(n);
  330. }
  331. int osrfChatServerConnect( osrfChatServer* cs, int port, int s2sport, char* listenAddr ) {
  332. if(!(cs && port && listenAddr)) return -1;
  333. cs->port = port;
  334. cs->s2sport = s2sport;
  335. if( socket_open_tcp_server(cs->mgr, port, listenAddr ) < 0 )
  336. return -1;
  337. if( socket_open_tcp_server(cs->mgr, s2sport, listenAddr ) < 0 )
  338. return -1;
  339. return 0;
  340. }
  341. int osrfChatServerWait( osrfChatServer* server ) {
  342. if(!server) return -1;
  343. while(1) {
  344. if(socket_wait_all(server->mgr, -1) < 0)
  345. osrfLogWarning( OSRF_LOG_MARK, "jserver_wait(): socket_wait_all() returned error");
  346. }
  347. return -1;
  348. }
  349. void osrfChatServerFree(osrfChatServer* server ) {
  350. if(!server) return;
  351. osrfHashFree(server->nodeHash);
  352. osrfListFree(server->nodeList);
  353. osrfListFree(server->deadNodes);
  354. socket_manager_free(server->mgr);
  355. free(server->domain);
  356. free(server->secret);
  357. free(server);
  358. }
  359. static void osrfChatHandleData( void* cs,
  360. socket_manager* mgr, int sockid, char* data, int parent_id ) {
  361. if(!(cs && mgr && sockid && data)) return;
  362. osrfChatServer* server = (osrfChatServer*) cs;
  363. osrfChatNode* node = osrfListGetIndex( server->nodeList, sockid );
  364. if(node)
  365. osrfLogDebug( OSRF_LOG_MARK, "Found node for sockid %d with state %d",
  366. sockid, node->state );
  367. if(!node) {
  368. osrfLogDebug( OSRF_LOG_MARK, "Adding new connection for sockid %d", sockid );
  369. node = osrfChatAddNode( server, sockid );
  370. }
  371. if(node) {
  372. if( (osrfChatPushData( server, node, data ) == -1) ) {
  373. osrfLogError( OSRF_LOG_MARK,
  374. "Node at socket %d with remote address %s and destination %s, "
  375. "received bad XML [%s], disconnecting...",
  376. sockid, node->remote, node->to, data );
  377. osrfChatSendRaw( node, OSRF_CHAT_PARSE_ERROR );
  378. osrfChatRemoveNode( server, node );
  379. }
  380. }
  381. osrfChatCleanupClients(server); /* clean up old dead clients */
  382. }
  383. static void osrfChatSocketClosed( void* blob, int sockid ) {
  384. if(!blob) return;
  385. osrfChatServer* server = (osrfChatServer*) blob;
  386. osrfChatNode* node = osrfListGetIndex(server->nodeList, sockid);
  387. osrfChatRemoveNode( server, node );
  388. }
  389. static osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid ) {
  390. if(!(server && sockid)) return NULL;
  391. osrfChatNode* node = osrfNewChatNode(sockid, server->domain);
  392. node->parent = server;
  393. node->sockid = sockid;
  394. osrfListSet( server->nodeList, node, sockid );
  395. return node;
  396. }
  397. void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node ) {
  398. if(!(server && node)) return;
  399. socket_disconnect(server->mgr, node->sockid);
  400. if(node->remote)
  401. osrfHashRemove( server->nodeHash, node->remote );
  402. osrfListRemove( server->nodeList, node->sockid ); /* this will free it */
  403. }
  404. static int osrfChatSendRaw( osrfChatNode* node, const char* msgXML ) {
  405. if(!(node && msgXML)) return -1;
  406. /* wait at most 3 second for this client to take our data */
  407. return socket_send_timeout( node->sockid, msgXML, 3000000 );
  408. }
  409. static void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node ) {
  410. if(!(server && node)) return;
  411. osrfChatSendRaw( node, "</stream:stream>");
  412. osrfChatRemoveNode( server, node );
  413. }
  414. static int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, const char* toAddr,
  415. const char* fromAddr, const char* msgXML ) {
  416. if(!(cs && node && toAddr && msgXML)) return -1;
  417. int l = strlen(toAddr);
  418. char dombuf[l];
  419. memset(dombuf, 0, sizeof(dombuf));
  420. jid_get_domain( toAddr, dombuf, l );
  421. if( eq( dombuf, cs->domain ) ) { /* this is to a user we host */
  422. osrfLogInfo( OSRF_LOG_MARK, "Sending message on local connection\nfrom: %s\nto: %s",
  423. fromAddr, toAddr );
  424. osrfChatNode* tonode = osrfHashGet(cs->nodeHash, toAddr);
  425. if(tonode) {
  426. /* if we can't send to the recipient (recipient is gone or too busy,
  427. * we drop the recipient and inform the sender that the recipient
  428. * is no more */
  429. if( osrfChatSendRaw( tonode, msgXML ) < 0 ) {
  430. osrfChatRemoveNode( cs, tonode );
  431. char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
  432. osrfLogError( OSRF_LOG_MARK, "Node failed to function. "
  433. "Responding to caller with error: %s", toAddr);
  434. if( osrfChatSendRaw( node, xml ) < 0 ) {
  435. osrfLogError(OSRF_LOG_MARK, "Sending node is now gone..removing");
  436. osrfChatRemoveNode( cs, node );
  437. }
  438. free(xml);
  439. }
  440. } else {
  441. /* send an error message saying we don't have this connection */
  442. osrfLogInfo( OSRF_LOG_MARK, "We have no connection for %s", toAddr);
  443. char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
  444. if( osrfChatSendRaw( node, xml ) < 0 )
  445. osrfChatRemoveNode( cs, node );
  446. free(xml);
  447. }
  448. } else {
  449. osrfChatNode* tonode = osrfHashGet(cs->nodeHash, dombuf);
  450. if(tonode) {
  451. if( tonode->state == OSRF_CHAT_STATE_CONNECTED ) {
  452. osrfLogDebug( OSRF_LOG_MARK, "Routing message to server %s", dombuf);
  453. if( osrfChatSendRaw( tonode, msgXML ) < 0 ) {
  454. osrfLogError( OSRF_LOG_MARK, "Node failed to function: %s", toAddr);
  455. char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
  456. if( osrfChatSendRaw( node, xml ) < 0 )
  457. osrfChatRemoveNode( cs, node );
  458. free(xml);
  459. osrfChatRemoveNode( cs, tonode );
  460. }
  461. } else {
  462. osrfLogInfo( OSRF_LOG_MARK,
  463. "Received s2s message and we're still trying to connect...caching");
  464. osrfListPush( tonode->msgs, strdup(msgXML) );
  465. }
  466. } else {
  467. if( osrfChatInitS2S( cs, dombuf, toAddr, msgXML ) != 0 ) {
  468. osrfLogWarning( OSRF_LOG_MARK,
  469. "We are unable to connect to remote server %s for recipient %s",
  470. dombuf, toAddr);
  471. char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
  472. osrfChatSendRaw( node, xml );
  473. free(xml);
  474. }
  475. }
  476. }
  477. return 0;
  478. }
  479. /*
  480. static void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode ) {
  481. if(!(toAddr && msgXML)) return;
  482. osrfChatS2SMessage* msg = safe_malloc(sizeof(osrfChatS2SMessage));
  483. msg->toAddr = strdup(toAddr);
  484. msg->msgXML = strdup(msgXML);
  485. osrfLogInfo( OSRF_LOG_MARK, "Pushing client message onto s2s queue waiting for connect... ");
  486. osrfListPush( snode->msgs, msgXML );
  487. }
  488. */
  489. static int osrfChatInitS2S( osrfChatServer* cs, const char* remote, const char* toAddr,
  490. const char* msgXML ) {
  491. if(!(cs && remote && toAddr && msgXML)) return -1;
  492. osrfLogInfo( OSRF_LOG_MARK, "Initing server2server connection to domain %s", remote );
  493. osrfChatNode* snode = osrfNewChatS2SNode( cs->domain, remote );
  494. snode->parent = cs;
  495. /* try to connect to the remote site */
  496. snode->sockid = socket_open_tcp_client(cs->mgr, cs->s2sport, remote);
  497. if(snode->sockid < 1) {
  498. osrfLogWarning( OSRF_LOG_MARK, "Unable to connect to remote server at %s", remote );
  499. osrfChatNodeFree( snode );
  500. return -1;
  501. }
  502. /* store the message we were supposed to deliver until we're fully connected */
  503. //osrfChatCacheS2SMessage( toAddr, msgXML, snode );
  504. osrfListPush( snode->msgs, strdup(msgXML) );
  505. osrfHashSet(cs->nodeHash, snode, remote );
  506. osrfListSet(cs->nodeList, snode, snode->sockid );
  507. /* send the initial s2s request */
  508. osrfChatSendRaw( snode, OSRF_CHAT_S2S_INIT );
  509. osrfLogDebug( OSRF_LOG_MARK, "Added new s2s node...");
  510. chatdbg(cs);
  511. return 0;
  512. }
  513. /* commence SAX handling code */
  514. static int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data ) {
  515. if(!(node && data)) return -1;
  516. chatdbg(server);
  517. osrfLogDebug( OSRF_LOG_MARK, "pushing data into xml parser for node %d with state %d:\n%s",
  518. node->sockid, node->state, data);
  519. node->inparse = 1;
  520. xmlParseChunk(node->parserCtx, data, strlen(data), 0);
  521. node->inparse = 0;
  522. if(osrfChatXMLErrorOcurred) {
  523. osrfChatXMLErrorOcurred = 0;
  524. return -1;
  525. }
  526. /* we can't do cleanup of the XML handlers while in the middle of a
  527. data push, so set flags in the data push and do the cleanup here */
  528. /*
  529. if(osrfChatClientSentDisconnect) {
  530. osrfChatClientSentDisconnect = 0;
  531. osrfChatNodeFinish( server, node );
  532. }
  533. */
  534. return 0;
  535. }
  536. static void osrfChatStartStream( void* blob ) {
  537. osrfLogDebug( OSRF_LOG_MARK, "Starting new client stream...");
  538. }
  539. static void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts ) {
  540. if(!(blob && name)) return;
  541. osrfChatNode* node = (osrfChatNode*) blob;
  542. int status = -1;
  543. char* nm = (char*) name;
  544. osrfLogDebug( OSRF_LOG_MARK, "Starting element %s with namespace %s and node state %d",
  545. nm, xmlSaxAttr(atts, "xmlns"), node->state );
  546. switch( node->state ) {
  547. case OSRF_CHAT_STATE_NONE:
  548. status = osrfChatHandleNewConnection( node, nm, atts );
  549. osrfLogDebug( OSRF_LOG_MARK, "After NewConnection we have state %d", node->state);
  550. break;
  551. case OSRF_CHAT_STATE_CONNECTING:
  552. status = osrfChatHandleConnecting( node, nm, atts );
  553. break;
  554. case OSRF_CHAT_STATE_CONNECTED:
  555. status = osrfChatHandleConnected( node, nm, atts );
  556. break;
  557. case OSRF_CHAT_STATE_S2S_CHALLENGE:
  558. status = osrfChatHandleS2SChallenge( node, nm, atts );
  559. break;
  560. case OSRF_CHAT_STATE_S2S_RESPONSE: /* server waiting for client response to challenge */
  561. if(eq(nm, "db:result")) {
  562. const char* remote = xmlSaxAttr(atts, "from");
  563. if(remote) {
  564. if( node->remote) free( node->remote );
  565. node->remote = strdup(remote); /* copy off the client's id */
  566. }
  567. status = 0;
  568. node->xmlstate |= OSRF_CHAT_STATE_INS2SRESULT;
  569. } else
  570. status = -1;
  571. break;
  572. case OSRF_CHAT_STATE_S2S_VERIFY: /* client : waiting for server verify message */
  573. if(eq(nm, "db:verify")) {
  574. const char* id = xmlSaxAttr( atts, "id" );
  575. if(id) {
  576. char* xml = va_list_to_string( OSRF_CHAT_S2S_VERIFY_RESPONSE,
  577. node->remote, node->domain, id );
  578. osrfChatSendRaw( node, xml );
  579. free(xml);
  580. node->state = OSRF_CHAT_STATE_S2S_VERIFY_FINAL;
  581. status = 0;
  582. }
  583. }
  584. break;
  585. case OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE: /* server waiting for client verify response */
  586. case OSRF_CHAT_STATE_S2S_VERIFY_FINAL: /* client waitig for final verify */
  587. status = osrfChatHandleS2SConnected( node, nm, atts );
  588. break;
  589. }
  590. if(status != 0)
  591. osrfChatParseError( node, "We don't know how to handle the XML data received" );
  592. }
  593. #define CHAT_CHECK_VARS(x,y,z) if(!(x && y)) return -1; if(z) osrfLogDebug( OSRF_LOG_MARK, z);
  594. int osrfChatHandleS2SConnected( osrfChatNode* node, const char* name, const xmlChar**atts ) {
  595. CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SConnected" );
  596. int status = -1;
  597. if(eq(name,"db:verify")) { /* server receives verify from client */
  598. char* xml = va_list_to_string(OSRF_CHAT_S2S_VERIFY_FINAL, node->domain, node->remote );
  599. osrfChatSendRaw(node, xml );
  600. free(xml);
  601. status = 0;
  602. }
  603. if(eq(name, "db:result")) {
  604. /* send all the messages that we have queued for this server */
  605. node->state = OSRF_CHAT_STATE_CONNECTED;
  606. osrfListIterator* itr = osrfNewListIterator(node->msgs);
  607. const char* xml;
  608. while( (xml = (char*) osrfListIteratorNext(itr)) ) {
  609. xmlDocPtr doc = xmlParseMemory(xml, strlen(xml));
  610. if(doc) {
  611. char* from = (char*) xmlGetProp(xmlDocGetRootElement(doc), BAD_CAST "from");
  612. char* to = (char*) xmlGetProp(xmlDocGetRootElement(doc), BAD_CAST "to");
  613. osrfChatSend( node->parent, node, to, from, xml );
  614. osrfLogDebug( OSRF_LOG_MARK, "Sending cached message from %s to %s", from, to);
  615. xmlFree(to); xmlFree(from);
  616. xmlFreeDoc(doc);
  617. }
  618. }
  619. osrfListIteratorFree(itr);
  620. osrfListFree(node->msgs);
  621. node->msgs = NULL;
  622. status = 0;
  623. }
  624. if(status == 0) {
  625. osrfLogInfo( OSRF_LOG_MARK, "Successfully made S2S connection to %s", node->remote );
  626. node->state = OSRF_CHAT_STATE_CONNECTED;
  627. node->xmlstate = 0;
  628. }
  629. return status;
  630. }
  631. /** check the namespace of the stream message to see if it's a server or client connection */
  632. static int osrfChatHandleNewConnection( osrfChatNode* node, const char* name,
  633. const xmlChar** atts ) {
  634. CHAT_CHECK_VARS(node, name, "osrfChatHandleNewConnection()");
  635. if(!eq(name, "stream:stream"))
  636. return -1;
  637. if( node->authkey ) free( node->authkey );
  638. node->authkey = osrfChatMkAuthKey();
  639. const char* ns = xmlSaxAttr(atts, "xmlns");
  640. if(!ns)
  641. return -1;
  642. if(eq(ns, "jabber:client")) { /* client connection */
  643. const char* domain = xmlSaxAttr( atts, "to" );
  644. if(!domain)
  645. return -1;
  646. if(!eq(domain, node->domain)) {
  647. osrfLogWarning( OSRF_LOG_MARK,
  648. "Client attempting to connect to invalid domain %s. Our domain is %s",
  649. domain, node->domain);
  650. return -1;
  651. }
  652. char* buf = va_list_to_string( OSRF_CHAT_START_STREAM, domain, node->authkey );
  653. node->state = OSRF_CHAT_STATE_CONNECTING;
  654. osrfLogDebug( OSRF_LOG_MARK,
  655. "Server node %d setting state to OSRF_CHAT_STATE_CONNECTING[%d]",
  656. node->sockid, node->state );
  657. osrfLogDebug( OSRF_LOG_MARK, "Server responding to connect message with\n%s\n", buf );
  658. osrfChatSendRaw( node, buf );
  659. free(buf);
  660. return 0;
  661. }
  662. /* server to server init */
  663. if(eq(ns, "jabber:server")) { /* client connection */
  664. osrfLogInfo( OSRF_LOG_MARK,
  665. "We received a new server 2 server connection, generating auth key...");
  666. char* xml = va_list_to_string( OSRF_CHAT_S2S_CHALLENGE, node->authkey );
  667. osrfChatSendRaw( node, xml );
  668. free(xml);
  669. node->state = OSRF_CHAT_STATE_S2S_RESPONSE; /* the next message should be the response */
  670. node->type = 1;
  671. return 0;
  672. }
  673. return -1;
  674. }
  675. char* osrfChatMkAuthKey() {
  676. char hostname[HOST_NAME_MAX + 1] = "";
  677. gethostname(hostname, sizeof(hostname) );
  678. hostname[HOST_NAME_MAX] = '\0';
  679. char keybuf[112];
  680. snprintf(keybuf, sizeof(keybuf), "%d%ld%s", (int) time(NULL), (long) getpid(), hostname);
  681. return strdup(shahash(keybuf));
  682. }
  683. static int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts ) {
  684. CHAT_CHECK_VARS(node, name, "osrfChatHandleConnecting()");
  685. osrfLogDebug( OSRF_LOG_MARK, "Handling connect node %s", name );
  686. if(eq(name, "iq"))
  687. node->xmlstate |= OSRF_CHAT_STATE_INIQ;
  688. else if(eq(name,"username"))
  689. node->xmlstate |= OSRF_CHAT_STATE_INUSERNAME;
  690. else if(eq(name,"resource"))
  691. node->xmlstate |= OSRF_CHAT_STATE_INRESOURCE;
  692. return 0;
  693. }
  694. static int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts ) {
  695. CHAT_CHECK_VARS(node, name, "osrfChatHandleConnected()");
  696. if(eq(name,"message")) {
  697. /* drop the old message and start with a new one */
  698. xmlNodePtr root = xmlNewNode(NULL, BAD_CAST name);
  699. xmlAddAttrs(root, atts);
  700. xmlNodePtr oldRoot = xmlDocSetRootElement(node->msgDoc, root);
  701. free(node->to);
  702. const char* to = xmlSaxAttr(atts, "to");
  703. if(!to)
  704. to = "";
  705. node->to = strdup(to);
  706. if(oldRoot)
  707. xmlFreeNode(oldRoot);
  708. node->xmlstate = OSRF_CHAT_STATE_INMESSAGE;
  709. } else {
  710. /* all non "message" nodes are simply added to the message */
  711. xmlNodePtr nodep = xmlNewNode(NULL, BAD_CAST name);
  712. xmlAddAttrs(nodep, atts);
  713. xmlAddChild(xmlDocGetRootElement(node->msgDoc), nodep);
  714. }
  715. return 0;
  716. }
  717. /* takes s2s secret, hashdomain, and the s2s auth token */
  718. static char* osrfChatGenerateS2SKey(
  719. const char* secret, const char* hashdomain, const char* authtoken ) {
  720. if(!(secret && hashdomain && authtoken)) return NULL;
  721. osrfLogInfo( OSRF_LOG_MARK, "Generating s2s key with auth token: %s", authtoken );
  722. char* a = shahash(secret);
  723. osrfLogDebug( OSRF_LOG_MARK, "S2S secret hash: %s", a);
  724. char* b = va_list_to_string("%s%s", a, hashdomain);
  725. char* c = shahash(b);
  726. osrfLogDebug( OSRF_LOG_MARK, "S2S intermediate hash: %s", c);
  727. char* d = va_list_to_string("%s%s", c, authtoken);
  728. char* e = strdup(shahash(d));
  729. free(b); free(d);
  730. return e;
  731. }
  732. static int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name,
  733. const xmlChar** atts ) {
  734. CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SChallenge()");
  735. /* here we respond to the stream challenge */
  736. if(eq(name, "stream:stream")) {
  737. const char* id = xmlSaxAttr(atts, "id");
  738. if(id) {
  739. /* we use our domain in the s2s challenge hash */
  740. char* d = osrfChatGenerateS2SKey(node->parent->secret, node->domain, id );
  741. char* e = va_list_to_string(OSRF_CHAT_S2S_RESPONSE, node->remote, node->domain, d );
  742. osrfLogInfo( OSRF_LOG_MARK, "Answering s2s challenge with key: %s", e );
  743. osrfChatSendRaw( node, e );
  744. free(d); free(e);
  745. node->state = OSRF_CHAT_STATE_S2S_VERIFY;
  746. return 0;
  747. }
  748. }
  749. return -1;
  750. }
  751. /*
  752. static int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name,
  753. const xmlChar** atts ) {
  754. CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SResponse()");
  755. if(eq(name, "db:result")) {
  756. node->xmlstate |= OSRF_CHAT_STATE_INS2SRESULT;
  757. return 0;
  758. }
  759. return -1;
  760. }
  761. */
  762. static void osrfChatEndElement( void* blob, const xmlChar* name ) {
  763. if(!(blob && name)) return;
  764. osrfChatNode* node = (osrfChatNode*) blob;
  765. char* nm = (char*) name;
  766. if(eq(nm,"stream:stream")) {
  767. osrfChatNodeFinish( node->parent, node );
  768. return;
  769. }
  770. if( node->state == OSRF_CHAT_STATE_CONNECTED ) {
  771. if(eq(nm, "message")) {
  772. xmlNodePtr msg = xmlDocGetRootElement(node->msgDoc);
  773. if(msg && node->type == 0)
  774. xmlSetProp(msg, BAD_CAST "from", BAD_CAST node->remote );
  775. char* string = xmlDocToString(node->msgDoc, 0 );
  776. char* from = (char*) xmlGetProp(msg, BAD_CAST "from");
  777. osrfLogDebug( OSRF_LOG_MARK, "Routing message to %s\n%s\n", node->to, from, string );
  778. osrfChatSend( node->parent, node, node->to, from, string );
  779. xmlFree(from);
  780. free(string);
  781. }
  782. }
  783. if( node->state == OSRF_CHAT_STATE_CONNECTING ) {
  784. if( node->xmlstate & OSRF_CHAT_STATE_INIQ ) {
  785. if(eq(nm, "iq")) {
  786. node->xmlstate &= ~OSRF_CHAT_STATE_INIQ;
  787. if( node->remote )
  788. free( node->remote );
  789. node->remote = va_list_to_string(
  790. "%s@%s/%s", node->username, node->domain, node->resource );
  791. osrfLogInfo( OSRF_LOG_MARK, "%s successfully logged in", node->remote );
  792. osrfLogDebug( OSRF_LOG_MARK, "Setting remote address to %s", node->remote );
  793. osrfChatSendRaw( node, OSRF_CHAT_LOGIN_OK );
  794. if(osrfHashGet( node->parent->nodeHash, node->remote ) ) {
  795. osrfLogWarning( OSRF_LOG_MARK,
  796. "New node replaces existing node for remote id %s", node->remote);
  797. osrfHashRemove(node->parent->nodeHash, node->remote);
  798. }
  799. osrfHashSet( node->parent->nodeHash, node, node->remote );
  800. node->state = OSRF_CHAT_STATE_CONNECTED;
  801. }
  802. }
  803. }
  804. }
  805. static void osrfChatHandleCharacter( void* blob, const xmlChar *ch, int len) {
  806. if(!(blob && ch && len)) return;
  807. osrfChatNode* node = (osrfChatNode*) blob;
  808. /*
  809. osrfLogDebug( OSRF_LOG_MARK, "Char Handler: state %d, xmlstate %d, chardata %s",
  810. node->state, node->xmlstate, (char*) ch );
  811. */
  812. if( node->state == OSRF_CHAT_STATE_CONNECTING ) {
  813. if( node->xmlstate & OSRF_CHAT_STATE_INIQ ) {
  814. if( node->xmlstate & OSRF_CHAT_STATE_INUSERNAME ) {
  815. free(node->username);
  816. node->username = strndup((char*) ch, len);
  817. node->xmlstate &= ~OSRF_CHAT_STATE_INUSERNAME;
  818. }
  819. if( node->xmlstate & OSRF_CHAT_STATE_INRESOURCE ) {
  820. free(node->resource);
  821. node->resource = strndup((char*) ch, len);
  822. node->xmlstate &= ~OSRF_CHAT_STATE_INRESOURCE;
  823. }
  824. }
  825. return;
  826. }
  827. if( node->state == OSRF_CHAT_STATE_CONNECTED ) {
  828. xmlNodePtr last = xmlGetLastChild(xmlDocGetRootElement(node->msgDoc));
  829. xmlNodePtr txt = xmlNewTextLen(ch, len);
  830. xmlAddChild(last, txt);
  831. return;
  832. }
  833. if( node->state == OSRF_CHAT_STATE_S2S_RESPONSE &&
  834. (node->xmlstate & OSRF_CHAT_STATE_INS2SRESULT) ) {
  835. char* key = strndup((char*) ch, len);
  836. osrfLogDebug( OSRF_LOG_MARK, "Got s2s key from %s : %s", node->remote, key );
  837. char* e = osrfChatGenerateS2SKey(node->parent->secret, node->remote, node->authkey );
  838. osrfLogInfo( OSRF_LOG_MARK,
  839. "\nReceived s2s key from server: %s\nKey should be: %s", key, e );
  840. if(eq(key, e)) {
  841. char* msg = va_list_to_string(OSRF_CHAT_S2S_VERIFY_REQUEST,
  842. node->authkey, node->domain, node->remote, e );
  843. osrfChatSendRaw(node, msg );
  844. free(msg);
  845. node->state = OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE;
  846. node->xmlstate = 0;
  847. } else {
  848. osrfLogWarning( OSRF_LOG_MARK, "Server2Server keys do not match!");
  849. }
  850. free( e );
  851. free( key );
  852. /* do the hash dance again */
  853. }
  854. }
  855. static void osrfChatParseError( void* blob, const char* msg, ... ) {
  856. osrfChatXMLErrorOcurred = 1;
  857. }