xmlrpc.c 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645
  1. /*
  2. * Copyright (C) 2005 iptelorg GmbH
  3. * Written by Jan Janak <[email protected]>
  4. *
  5. * This file is part of SER, a free SIP server.
  6. *
  7. * SER is free software; you can redistribute it and/or modify it under the
  8. * terms of the GNU General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option) any later
  10. * version
  11. *
  12. * For a license to use the SER software under conditions other than those
  13. * described here, or to purchase support for this software, please contact
  14. * iptel.org by e-mail at the following addresses: [email protected]
  15. *
  16. * SER is distributed in the hope that it will be useful, but WITHOUT ANY
  17. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  18. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  19. * details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc., 59
  23. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. */
  25. /*This define breaks on Solaris OS */
  26. #ifndef __OS_solaris
  27. #define _XOPEN_SOURCE 4 /* strptime */
  28. #endif
  29. #define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
  30. #define _SVID_SOURCE 1 /* timegm */
  31. #include <strings.h>
  32. #include <time.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <stdarg.h>
  38. #include <sys/types.h>
  39. #include <signal.h>
  40. #include <libxml/xmlreader.h>
  41. #include "../../str.h"
  42. #include "../../sr_module.h"
  43. #include "../../error.h"
  44. #include "../../usr_avp.h"
  45. #include "../../mem/mem.h"
  46. #include "../../parser/parse_uri.h"
  47. #include "../../parser/msg_parser.h"
  48. #include "../../ut.h"
  49. #include "../../dset.h"
  50. #include "../../str.h"
  51. #include "../../dprint.h"
  52. #include "../../data_lump.h"
  53. #include "../../data_lump_rpl.h"
  54. #include "../../msg_translator.h"
  55. #include "../../select.h"
  56. #include "../../receive.h" /* needed by process_rpc / receive_msg() */
  57. #include "../../modules/sl/sl.h"
  58. #include "../../nonsip_hooks.h"
  59. #include "../../action.h" /* run_actions */
  60. #include "../../script_cb.h" /* exec_*_script_cb */
  61. #include "../../route.h" /* route_get */
  62. #include "../../sip_msg_clone.h" /* sip_msg_shm_clone */
  63. #include "http.h"
  64. /** @addtogroup xmlrpc
  65. * @ingroup modules
  66. * @{
  67. *
  68. * <h1>Overview of Operation</h1>
  69. * This module provides XML-RPC based interface to management functions in
  70. * SER. You can send XML-RPC requests to SER when the module is loaded and
  71. * configured and it will send XML-RPC replies back. XML-RPC requests are
  72. * encoded as XML documents in the body of HTTP requests. Due to similarity
  73. * between HTTP and SIP SER can easily parse HTTP requests and extract the XML
  74. * document from their body.
  75. *
  76. * When you load this module into SER, it will register a callback function
  77. * that will be called whenever the SER core receives a request with method it
  78. * does not understand. The main callback function is process_xmlrpc(). The
  79. * function first verifies if the protocol identifier inside the request is
  80. * HTTP and whether the request method is either GET or POST. If both
  81. * conditions are met then it will signal to the SER core that it is
  82. * processing the request, otherwise it will reject the request and the SER
  83. * core will pass the requests to other callbacks if they exist.
  84. *
  85. * As the next step the request will be converted from HTTP request to a SIP
  86. * request to ensure that it can be processed by SER and its modules. The
  87. * conversion will modify the URI in the Request-URI of the request, the new
  88. * URI will be a SIP URI. In addition to that it will add a fake Via header
  89. * field and copy all remaining header fields from the original HTTP request.
  90. * The conversion is implemented in http_xmlrpc2sip() function.
  91. *
  92. * After the conversion the module will execute the route statement whose
  93. * number is configured in "route" module parameter. That route stament may
  94. * perform additional security checks and when it ensures that the client is
  95. * authorized to execute management functions then it will call dispatch_rpc()
  96. * module function provided by this module.
  97. *
  98. * dispatch_rpc() function extracts the XML-RPC document from the body of the
  99. * request to determine the name of the method to be called and then it
  100. * searches through the list of all management functions to find a function
  101. * with matching name. If such a function is found then dispatch_rpc() will
  102. * pass control to the function to handle the request. dispatch_rpc() will
  103. * send a reply back to the client when the management function terminates, if
  104. * the function did not do that explicitly.
  105. *
  106. * <h2>Memory Management</h2>
  107. * The module provides implementation for all the functions required by the
  108. * management interface in SER, such as rpc->rpl_printf, rpc->add, rpc->struct_add
  109. * and so on. Whenever the management function calls one of the functions then
  110. * corresponding function in this module will be called to handle the request.
  111. *
  112. * The implementation functions build the reply, that will be sent to the
  113. * client, as they execute and they need to allocate memory to do that. That
  114. * memory must be freed again after the reply has been sent to the client. To
  115. * remember all the memory regions allocated during the execution of the
  116. * management function all functions within this module record all allocated
  117. * memory in the global variable called waste_bin. dispatch_rpc() functions
  118. * executes function collect_garbage() after the reply has been sent to the
  119. * client to free all memory that was allocated from the management function.
  120. * that was executed.
  121. *
  122. * <h2>Request Context</h2>
  123. * Before the module calls a management function it prepares a structure
  124. * called context. The context is defined in structure rpc_ctx and it is
  125. * passed as one of parameter to the management function being called. The
  126. * context contains all the data that is needed during the execution of the
  127. * management function, such as the pointer to the request being processed, a
  128. * pointer to the reply being built, and so on.
  129. *
  130. * Another parameter to the management function being called is a structure
  131. * that contains pointers to all implementation functions. This structure is
  132. * of type rpc_t, this module keeps one global variable of that type called
  133. * func_param and a pointer to that variable is passed to all management
  134. * functions. The global variable is initialized in mod_init().
  135. */
  136. /** @file
  137. *
  138. * This is the main file of XMLRPC SER module which contains all the functions
  139. * related to XML-RPC processing, as well as the module interface.
  140. */
  141. /*
  142. * FIXME: Decouple code and reason phrase from reply body
  143. * Escape special characters in strings
  144. */
  145. MODULE_VERSION
  146. #if defined (__OS_darwin) || defined (__OS_freebsd)
  147. /* redeclaration of functions from stdio.h throws errors */
  148. #else
  149. int snprintf(char *str, size_t size, const char *format, ...);
  150. int vsnprintf(char *str, size_t size, const char *format, va_list ap);
  151. #endif
  152. static int process_xmlrpc(sip_msg_t* msg);
  153. static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2);
  154. static int xmlrpc_reply(sip_msg_t* msg, char* code, char* reason);
  155. static int mod_init(void);
  156. /* first line (w/o the version) of the sip msg created from the http xmlrpc */
  157. #define XMLRPC_URI "sip:127.0.0.1:9"
  158. #define XMLRPC_URI_LEN (sizeof(XMLRPC_URI)-1)
  159. #define HTTP_GET "GET"
  160. #define HTTP_GET_LEN (sizeof(HTTP_GET)-1)
  161. #define HTTP_POST "POST"
  162. #define HTTP_POST_LEN (sizeof(HTTP_POST)-1)
  163. #define N_HTTP_GET 0x00746567U
  164. #define N_HTTP_POST 0x74736f70U
  165. #define LF "\n"
  166. /** The beginning of XML document indicating an error.
  167. *
  168. * This is the beginning of the XML document that will be sent back to the
  169. * client when the server encountered an error. It will be immediately
  170. * followed by a reason phrase.
  171. */
  172. #define FAULT_PREFIX \
  173. "<?xml version=\"1.0\"?>" LF \
  174. "<methodResponse>" LF \
  175. "<fault>" LF \
  176. "<value>" LF \
  177. "<struct>" LF \
  178. "<member>" LF \
  179. "<name>faultCode</name>" LF \
  180. "<value><int>"
  181. /** The text of XML document indicating error that goes between reason code
  182. * and reason phrase.
  183. */
  184. #define FAULT_BODY \
  185. "</int></value>" LF \
  186. "</member>" LF \
  187. "<member>" LF \
  188. "<name>faultString</name>" LF \
  189. "<value><string>"
  190. /** The end of XML document that indicates an error.
  191. *
  192. * This is the closing part of the XML-RPC document that indicates an error on
  193. * the server.
  194. */
  195. #define FAULT_SUFFIX \
  196. "</string></value>" LF \
  197. "</member>" LF \
  198. "</struct>" LF \
  199. "</value>" LF \
  200. "</fault>" LF \
  201. "</methodResponse>"
  202. /** The beginning of XML-RPC reply sent to the client.
  203. */
  204. #define SUCCESS_PREFIX \
  205. "<?xml version=\"1.0\"?>" LF \
  206. "<methodResponse>" LF \
  207. "<params>" LF \
  208. "<param>" LF \
  209. "<value>"
  210. /** The closing part of XML-RPC reply document sent to
  211. * the client.
  212. */
  213. #define SUCCESS_SUFFIX \
  214. "</value>" LF \
  215. "</param>" LF \
  216. "</params>" LF \
  217. "</methodResponse>"
  218. static str fault_prefix = STR_STATIC_INIT(FAULT_PREFIX);
  219. static str fault_body = STR_STATIC_INIT(FAULT_BODY);
  220. static str fault_suffix = STR_STATIC_INIT(FAULT_SUFFIX);
  221. static str success_prefix = STR_STATIC_INIT(SUCCESS_PREFIX);
  222. static str success_suffix = STR_STATIC_INIT(SUCCESS_SUFFIX);
  223. static str lf = STR_STATIC_INIT(LF);
  224. static str int_prefix = STR_STATIC_INIT("<int>");
  225. static str int_suffix = STR_STATIC_INIT("</int>");
  226. static str double_prefix = STR_STATIC_INIT("<double>");
  227. static str double_suffix = STR_STATIC_INIT("</double>");
  228. static str string_prefix = STR_STATIC_INIT("<string>");
  229. static str string_suffix = STR_STATIC_INIT("</string>");
  230. static str date_prefix = STR_STATIC_INIT("<dateTime.iso8601>");
  231. static str date_suffix = STR_STATIC_INIT("</dateTime.iso8601>");
  232. static str bool_prefix = STR_STATIC_INIT("<boolean>");
  233. static str bool_suffix = STR_STATIC_INIT("</boolean>");
  234. static str value_prefix = STR_STATIC_INIT("<value>");
  235. static str value_suffix = STR_STATIC_INIT("</value>");
  236. static str array_prefix = STR_STATIC_INIT("<array><data>" LF);
  237. static str array_suffix = STR_STATIC_INIT("</data></array>");
  238. static str struct_prefix = STR_STATIC_INIT("<struct>");
  239. static str struct_suffix = STR_STATIC_INIT("</struct>");
  240. static str member_prefix = STR_STATIC_INIT("<member>");
  241. static str member_suffix = STR_STATIC_INIT("</member>");
  242. static str name_prefix = STR_STATIC_INIT("<name>");
  243. static str name_suffix = STR_STATIC_INIT("</name>");
  244. /** Garbage collection data structure.
  245. *
  246. * This is the data structure used by the garbage collector in this module.
  247. * When the xmlrpc SER module identifies the management function to be called,
  248. * it calls corresponding function in SER. The function being called adds data
  249. * to the reply, that will be later sent to the client, as it executes. This
  250. * module needs to allocate memory for such data and the memory will be
  251. * re-claimed after the reply was sent out. All the memory allocated this way
  252. * is recorded in this data structure so that it can be identified and
  253. * re-claimed later (when the reply is being sent out).
  254. *
  255. */
  256. static struct garbage {
  257. enum {
  258. JUNK_XMLCHAR,
  259. JUNK_RPCSTRUCT, /**< This type indicates that the memory block was
  260. * allocated for the RPC structure data type, this
  261. * type needs to be freed differently as it may
  262. * contain more allocated memory blocks
  263. */
  264. JUNK_PKGCHAR /** This type indicates a mxr_malloc'ed string */
  265. } type; /**< Type of the memory block */
  266. void* ptr; /**< Pointer to the memory block obtained from
  267. mxr_malloc */
  268. struct garbage* next; /**< The linked list of all allocated memory
  269. blocks */
  270. } *waste_bin = 0;
  271. /** Representation of the XML-RPC reply being constructed.
  272. *
  273. * This data structure describes the XML-RPC reply that is being constructed
  274. * and will be sent to the client.
  275. */
  276. struct xmlrpc_reply {
  277. int code; /**< Reply code which indicates the type of the reply */
  278. char* reason; /**< Reason phrase text which provides human-readable
  279. * description that augments the reply code */
  280. str body; /**< The XML-RPC document body built so far */
  281. str buf; /**< The memory buffer allocated for the reply, this is
  282. * where the body attribute of the structure points to
  283. */
  284. };
  285. /** The context of the XML-RPC request being processed.
  286. *
  287. * This is the data structure that contains all data related to the XML-RPC
  288. * request being processed, such as the reply code and reason, data to be sent
  289. * to the client in the reply, and so on.
  290. *
  291. * There is always one context per XML-RPC request.
  292. */
  293. typedef struct rpc_ctx {
  294. sip_msg_t* msg; /**< The SIP/HTTP through which the RPC has been
  295. received */
  296. struct xmlrpc_reply reply; /**< XML-RPC reply to be sent to the client */
  297. struct rpc_struct* structs; /**< Structures to be added to the reply */
  298. int msg_shm_block_size; /**< non-zero for delayed reply contexts with
  299. shm cloned msgs */
  300. int reply_sent; /**< The flag is set after a reply is sent,
  301. this prevents a single reply being sent
  302. twice */
  303. char* method; /**< Name of the management function to be
  304. called */
  305. unsigned int flags; /**< Various flags, such as return value
  306. type */
  307. xmlDocPtr doc; /**< Pointer to the XML-RPC request
  308. document */
  309. xmlNodePtr act_param; /**< Pointer to the parameter being processed
  310. in the XML-RPC request document */
  311. } rpc_ctx_t;
  312. /* extra rpc_ctx_t flags */
  313. /* first 8 bits reserved for rpc flags (e.g. RET_ARRAY) */
  314. #define XMLRPC_DELAYED_CTX_F 256
  315. #define XMLRPC_DELAYED_REPLY_F 512
  316. /** The structure represents a XML-RPC document structure.
  317. *
  318. * This is the data structure that represents XML-RPC structures that are sent
  319. * to the client in the XML-RPC reply documents. A XML-RPC document structure
  320. * is compound consting of name-value pairs.
  321. * @sa http://www.xml-rpc.com
  322. */
  323. struct rpc_struct {
  324. int vtype;
  325. xmlNodePtr struct_in; /**< Pointer to the structure parameter */
  326. struct xmlrpc_reply struct_out; /**< Structure to be sent in reply */
  327. struct xmlrpc_reply* reply; /**< Print errors here */
  328. int n; /**< Number of structure members
  329. created */
  330. xmlDocPtr doc; /**< XML-RPC document */
  331. int offset; /**< Offset in the reply where the
  332. structure should be printed */
  333. struct rpc_struct* nnext; /**< nested structure support - a recursive list of nested structrures */
  334. struct rpc_struct* parent; /**< access to parent structure - used for flattening structure before reply */
  335. struct rpc_struct* next;
  336. };
  337. /** The context of the XML-RPC request being processed.
  338. *
  339. * This is a global variable that records the context of the XML-RPC request
  340. * being currently processed.
  341. * @sa rpc_ctx
  342. */
  343. static rpc_ctx_t ctx;
  344. static void close_doc(rpc_ctx_t* ctx);
  345. static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...);
  346. static int fixup_xmlrpc_reply(void** param, int param_no);
  347. /** Pointers to the functions that implement the RPC interface
  348. * of xmlrpc SER module
  349. */
  350. static rpc_t func_param;
  351. /** Enable/disable additional introspection methods. If set to 1 then the
  352. * functions defined in http://scripts.incutio.com/xmlrpc/introspection.html
  353. * will be available on the server. If set to 0 then the functions will be
  354. * disabled.
  355. */
  356. static char* xmlrpc_route=0; /* default is the main route */
  357. /** Reference to the sl (stateless replies) module of SER The sl module of SER
  358. * is needed so that the xmlrpc SER module can send replies back to clients
  359. */
  360. sl_api_t slb;
  361. static int xmlrpc_route_no=DEFAULT_RT;
  362. /* if set, try autoconverting to the requested type if possible
  363. (e.g. convert 1 to "1" if string is requested) */
  364. static int autoconvert=0;
  365. /* in replies, escape CR to &#xD (according to the xml specs) */
  366. static int escape_cr=1; /* default on */
  367. /* convert double LF to CR LF (when on, LFLF becomes an escape for CRLF, needed
  368. with some xmlrpc clients that are not escaping CR to &#xD; )*/
  369. static int lflf2crlf=0; /* default off */
  370. /* do not register for non-sip requests */
  371. static int xmlrpc_mode = 0;
  372. static char* xmlrpc_url_match = NULL;
  373. static regex_t xmlrpc_url_match_regexp;
  374. static char* xmlrpc_url_skip = NULL;
  375. static regex_t xmlrpc_url_skip_regexp;
  376. /*
  377. * Exported functions
  378. */
  379. static cmd_export_t cmds[] = {
  380. {"dispatch_rpc", dispatch_rpc, 0, 0, REQUEST_ROUTE},
  381. {"xmlrpc_reply", xmlrpc_reply, 2, fixup_xmlrpc_reply, REQUEST_ROUTE},
  382. {0, 0, 0, 0, 0}
  383. };
  384. /*
  385. * Exported parameters
  386. */
  387. static param_export_t params[] = {
  388. {"route", PARAM_STRING, &xmlrpc_route},
  389. {"autoconversion", PARAM_INT, &autoconvert},
  390. {"escape_cr", PARAM_INT, &escape_cr},
  391. {"double_lf_to_crlf", PARAM_INT, &lflf2crlf},
  392. {"mode", PARAM_INT, &xmlrpc_mode},
  393. {"url_match", PARAM_STRING, &xmlrpc_url_match},
  394. {"url_skip", PARAM_STRING, &xmlrpc_url_skip},
  395. {0, 0, 0}
  396. };
  397. struct module_exports exports = {
  398. "xmlrpc",
  399. cmds, /* Exported commands */
  400. 0, /* Exported RPC methods */
  401. params, /* Exported parameters */
  402. mod_init, /* module initialization function */
  403. 0, /* response function*/
  404. 0, /* destroy function */
  405. 0, /* oncancel function */
  406. 0 /* per-child init function */
  407. };
  408. /* XML-RPC reply helper functions */
  409. #define ESC_LT "&lt;"
  410. #define ESC_AMP "&amp;"
  411. #define ESC_CR "&#xD;"
  412. static void clean_context(rpc_ctx_t* ctx);
  413. /** Adds arbitrary text to the XML-RPC reply being constructed, special
  414. * characters < and & will be escaped.
  415. *
  416. * This function adds arbitrary text to the body of the XML-RPC reply being
  417. * constructed. Note well that the function does not check whether the XML
  418. * document being constructed is well-formed or valid. Use with care.
  419. *
  420. * @param reply Pointer to the structure representing the XML-RPC reply
  421. * being constructed.
  422. * @param text The text to be appended to the XML-RPC reply.
  423. * @return -1 on error, 0 if the text was added successfuly.
  424. * @sa add_xmlrpc_reply()
  425. */
  426. static int add_xmlrpc_reply_esc(struct xmlrpc_reply* reply, str* text)
  427. {
  428. char* p;
  429. int i;
  430. for(i = 0; i < text->len; i++) {
  431. /* 10 must be bigger than size of longest escape sequence */
  432. if (reply->body.len >= reply->buf.len - 10) {
  433. p = mxr_malloc(reply->buf.len + 1024);
  434. if (!p) {
  435. set_fault(reply, 500,
  436. "Internal Server Error (No memory left)");
  437. ERR("No memory left: %d\n", reply->body.len + 1024);
  438. return -1;
  439. }
  440. memcpy(p, reply->body.s, reply->body.len);
  441. mxr_free(reply->buf.s);
  442. reply->buf.s = p;
  443. reply->buf.len += 1024;
  444. reply->body.s = p;
  445. }
  446. switch(text->s[i]) {
  447. case '<':
  448. memcpy(reply->body.s + reply->body.len, ESC_LT,
  449. sizeof(ESC_LT) - 1);
  450. reply->body.len += sizeof(ESC_LT) - 1;
  451. break;
  452. case '&':
  453. memcpy(reply->body.s + reply->body.len, ESC_AMP,
  454. sizeof(ESC_AMP) - 1);
  455. reply->body.len += sizeof(ESC_AMP) - 1;
  456. break;
  457. case '\r':
  458. if (likely(escape_cr)){
  459. memcpy(reply->body.s + reply->body.len, ESC_CR,
  460. sizeof(ESC_CR) - 1);
  461. reply->body.len += sizeof(ESC_CR) - 1;
  462. break;
  463. }
  464. /* no break */
  465. default:
  466. reply->body.s[reply->body.len] = text->s[i];
  467. reply->body.len++;
  468. break;
  469. }
  470. }
  471. return 0;
  472. }
  473. /** Add arbitrary text to the XML-RPC reply being constructed, no escaping
  474. * done.
  475. *
  476. * This is a more efficient version of add_xmlrpc_reply_esc(), the function
  477. * appends arbitrary text to the end of the XML-RPC reply being constructed,
  478. * but the text must not contain any characters that need to be escaped in
  479. * XML, such as < and & (or the characters must be escaped already).
  480. *
  481. * @param reply Pointer to the structure representing the XML-RPC reply
  482. * being constructed.
  483. * @param text The text to be appended to the XML-RPC reply.
  484. * @return -1 on error, 0 if the text was added successfuly.
  485. * @sa add_xmlrpc_reply_esc()
  486. */
  487. static int add_xmlrpc_reply(struct xmlrpc_reply* reply, str* text)
  488. {
  489. char* p;
  490. if (text->len > (reply->buf.len - reply->body.len)) {
  491. p = mxr_malloc(reply->buf.len + text->len + 1024);
  492. if (!p) {
  493. set_fault(reply, 500, "Internal Server Error (No memory left)");
  494. ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
  495. return -1;
  496. }
  497. memcpy(p, reply->body.s, reply->body.len);
  498. mxr_free(reply->buf.s);
  499. reply->buf.s = p;
  500. reply->buf.len += text->len + 1024;
  501. reply->body.s = p;
  502. }
  503. memcpy(reply->body.s + reply->body.len, text->s, text->len);
  504. reply->body.len += text->len;
  505. return 0;
  506. }
  507. /** Adds arbitrary text to the XML-RPC reply being constructed, the text will
  508. * be inserted at a specified offset within the XML-RPC reply.
  509. *
  510. * This function inserts arbitrary text in the XML-RPC reply that is being
  511. * constructed, unlike add_xmlrp_reply(), this function will not append the
  512. * text at the end of the reply, but it will insert the text in the middle of
  513. * the reply at the position provided to the function in "offset"
  514. * parameter. The function does not escape special characters and thus the
  515. * text must not contain such characters (or the must be escaped already).
  516. *
  517. * @param reply The XML-RPC reply structure representing the reply being
  518. * constructed.
  519. * @param offset The position of the first character where the text should be
  520. * inserted.
  521. * @param text The text to be inserted.
  522. * @return 0 of the text was inserted successfuly, a negative number on error.
  523. */
  524. static int add_xmlrpc_reply_offset(struct xmlrpc_reply* reply, unsigned int offset, str* text)
  525. {
  526. char* p;
  527. if (text->len > (reply->buf.len - reply->body.len)) {
  528. p = mxr_malloc(reply->buf.len + text->len + 1024);
  529. if (!p) {
  530. set_fault(reply, 500, "Internal Server Error (No memory left)");
  531. ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
  532. return -1;
  533. }
  534. memcpy(p, reply->body.s, reply->body.len);
  535. mxr_free(reply->buf.s);
  536. reply->buf.s = p;
  537. reply->buf.len += text->len + 1024;
  538. reply->body.s = p;
  539. }
  540. memmove(reply->body.s + offset + text->len, reply->body.s + offset,
  541. reply->body.len - offset);
  542. memcpy(reply->body.s + offset, text->s, text->len);
  543. reply->body.len += text->len;
  544. return 0;
  545. }
  546. /** Returns the current length of the XML-RPC reply body.
  547. *
  548. * @param reply The XML-RPC reply being constructed
  549. * @return Number of bytes of the XML-RPC reply body.
  550. */
  551. static unsigned int get_reply_len(struct xmlrpc_reply* reply)
  552. {
  553. return reply->body.len;
  554. }
  555. /* Resets XMLRPC reply body.
  556. *
  557. * This function discards everything that has been written so far and starts
  558. * constructing the XML-RPC reply body from the beginning.
  559. *
  560. * @param reply The XML-RPC reply being constructed.
  561. */
  562. static void reset_xmlrpc_reply(struct xmlrpc_reply* reply)
  563. {
  564. reply->body.len = 0;
  565. }
  566. /** Initialize XML-RPC reply data structure.
  567. *
  568. * This function initializes the data structure that contains all data related
  569. * to the XML-RPC reply being created. The function must be called before any
  570. * other function that adds data to the reply.
  571. * @param reply XML-RPC reply structure to be initialized.
  572. * @return 0 on success, a negative number on error.
  573. */
  574. static int init_xmlrpc_reply(struct xmlrpc_reply* reply)
  575. {
  576. reply->code = 200;
  577. reply->reason = "OK";
  578. reply->buf.s = mxr_malloc(1024);
  579. if (!reply->buf.s) {
  580. set_fault(reply, 500, "Internal Server Error (No memory left)");
  581. ERR("No memory left\n");
  582. return -1;
  583. }
  584. reply->buf.len = 1024;
  585. reply->body.s = reply->buf.s;
  586. reply->body.len = 0;
  587. return 0;
  588. }
  589. /** Clear the XML-RPC reply code and sets it back to a success reply.
  590. *
  591. * @param reply XML-RPC reply structure to be cleared.
  592. */
  593. static void clear_xmlrpc_reply(struct xmlrpc_reply* reply)
  594. {
  595. reply->code = 200;
  596. reply->reason = "OK";
  597. }
  598. /* if this a delayed reply context, and it's never been use before, fix it */
  599. static int fix_delayed_reply_ctx(rpc_ctx_t* ctx)
  600. {
  601. if ((ctx->flags & XMLRPC_DELAYED_CTX_F) && (ctx->reply.buf.s==0)){
  602. if (init_xmlrpc_reply(&ctx->reply) <0) return -1;
  603. add_xmlrpc_reply(&ctx->reply, &success_prefix);
  604. if (ctx->flags & RET_ARRAY)
  605. return add_xmlrpc_reply(&ctx->reply, &array_prefix);
  606. }
  607. return 0;
  608. }
  609. /** Free all memory used by the XML-RPC reply structure. */
  610. static void clean_xmlrpc_reply(struct xmlrpc_reply* reply)
  611. {
  612. if (reply->buf.s) mxr_free(reply->buf.s);
  613. }
  614. /** Create XML-RPC reply that indicates an error to the caller.
  615. *
  616. * This function is used to build the XML-RPC reply body that indicates that
  617. * an error ocurred on the server. It is called when a management function in
  618. * SER reports an error. The reply will contain the reason code and reason
  619. * phrase text provided by the management function that indicated the error.
  620. */
  621. static int build_fault_reply(struct xmlrpc_reply* reply)
  622. {
  623. str reason_s, code_s;
  624. reason_s.s = reply->reason;
  625. reason_s.len = strlen(reply->reason);
  626. code_s.s = int2str(reply->code, &code_s.len);
  627. reset_xmlrpc_reply(reply);
  628. if (add_xmlrpc_reply(reply, &fault_prefix) < 0) return -1;
  629. if (add_xmlrpc_reply_esc(reply, &code_s) < 0) return -1;
  630. if (add_xmlrpc_reply(reply, &fault_body) < 0) return -1;
  631. if (add_xmlrpc_reply_esc(reply, &reason_s) < 0) return -1;
  632. if (add_xmlrpc_reply(reply, &fault_suffix) < 0) return -1;
  633. return 0;
  634. }
  635. /** Add a memory registion to the list of memory blocks that
  636. * need to be re-claimed later.
  637. *
  638. * @param type The type of the memory block (ordinary text or structure).
  639. * @param ptr A pointer to the memory block.
  640. * @param reply The XML-RPC the memory block is associated with.
  641. * @return 0 on success, a negative number on error.
  642. * @sa collect_garbage()
  643. */
  644. static int add_garbage(int type, void* ptr, struct xmlrpc_reply* reply)
  645. {
  646. struct garbage* p;
  647. p = (struct garbage*)mxr_malloc(sizeof(struct garbage));
  648. if (!p) {
  649. set_fault(reply, 500, "Internal Server Error (No memory left)");
  650. ERR("Not enough memory\n");
  651. return -1;
  652. }
  653. p->type = type;
  654. p->ptr = ptr;
  655. p->next = waste_bin;
  656. waste_bin = p;
  657. return 0;
  658. }
  659. /** Re-claims all memory allocated in the process of building XML-RPC
  660. * reply.
  661. */
  662. static void collect_garbage(void)
  663. {
  664. struct rpc_struct* s;
  665. struct garbage* p;
  666. /* Collect garbage */
  667. while(waste_bin) {
  668. p = waste_bin;
  669. waste_bin = waste_bin->next;
  670. switch(p->type) {
  671. case JUNK_XMLCHAR:
  672. if (p->ptr) xmlFree(p->ptr);
  673. break;
  674. case JUNK_RPCSTRUCT:
  675. s = (struct rpc_struct*)p->ptr;
  676. if (s && s->struct_out.buf.s) mxr_free(s->struct_out.buf.s);
  677. if (s) mxr_free(s);
  678. break;
  679. case JUNK_PKGCHAR:
  680. if (p->ptr){
  681. mxr_free(p->ptr);
  682. p->ptr=0;
  683. }
  684. break;
  685. default:
  686. ERR("BUG: Unsupported junk type\n");
  687. }
  688. mxr_free(p);
  689. }
  690. }
  691. /** Extract XML-RPC query from a SIP/HTTP message.
  692. *
  693. * @param doc A pointer to string descriptor that will be filled
  694. * with the pointer to the beginning of the XML-RPC
  695. * document and length of the document.
  696. * @param msg A structure representing the SIP/HTTP message
  697. * carrying the XML-RPC document in body.
  698. */
  699. static int get_rpc_document(str* doc, sip_msg_t* msg)
  700. {
  701. doc->s = get_body(msg);
  702. if (!doc->s) {
  703. ERR("Error while extracting message body\n");
  704. return -1;
  705. }
  706. doc->len = strlen(doc->s);
  707. return 0;
  708. }
  709. /** Send a reply to the client with given body.
  710. *
  711. * This function sends a 200 OK reply back to the client, the body of the
  712. * reply will contain text provided to the function in "body" parameter.
  713. *
  714. * @param msg The request that generated the reply.
  715. * @param body The text that will be put in the body of the reply.
  716. */
  717. static int send_reply(sip_msg_t* msg, str* body)
  718. {
  719. if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) < 0) {
  720. ERR("Error while adding reply lump\n");
  721. return -1;
  722. }
  723. if (slb.zreply(msg, 200, "OK") == -1) {
  724. ERR("Error while sending reply\n");
  725. return -1;
  726. }
  727. return 0;
  728. }
  729. static int flatten_nests(struct rpc_struct* st, struct xmlrpc_reply* reply) {
  730. if (!st)
  731. return 1;
  732. if (!st->nnext) {
  733. if(st->vtype == RET_ARRAY) {
  734. if (add_xmlrpc_reply(&st->struct_out, &array_suffix) < 0) return -1;
  735. } else {
  736. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  737. }
  738. if (add_xmlrpc_reply_offset(&st->parent->struct_out, st->offset, &st->struct_out.body) < 0) return -1;
  739. } else {
  740. flatten_nests(st->nnext, reply);
  741. if(st->vtype == RET_ARRAY) {
  742. if (add_xmlrpc_reply(&st->struct_out, &array_suffix) < 0) return -1;
  743. } else {
  744. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  745. }
  746. if (add_xmlrpc_reply_offset(&st->parent->struct_out, st->offset, &st->struct_out.body) < 0) return -1;
  747. }
  748. return 1;
  749. }
  750. static int print_structures(struct xmlrpc_reply* reply,
  751. struct rpc_struct* st)
  752. {
  753. while(st) {
  754. /* Close the structure first */
  755. if(st->vtype == RET_ARRAY) {
  756. if (add_xmlrpc_reply(&st->struct_out, &array_suffix) < 0) return -1;
  757. } else {
  758. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  759. }
  760. if (flatten_nests(st->nnext, &st->struct_out) < 0) return -1;
  761. if (add_xmlrpc_reply_offset(reply, st->offset, &st->struct_out.body) < 0) return -1;
  762. st = st->next;
  763. }
  764. return 0;
  765. }
  766. /** Implementation of rpc_send function required by the management API in SER.
  767. *
  768. * This is the function that will be called whenever a management function in
  769. * SER asks the management interface to send the reply to the client. The
  770. * function will generate the XML-RPC document, put it in body of a SIP
  771. * response and send the response to the client. The SIP/HTTP reply sent to
  772. * the client will be always 200 OK, if an error ocurred on the server then it
  773. * will be indicated in the XML document in body.
  774. *
  775. * @param ctx A pointer to the context structure of the XML-RPC request that
  776. * generated the reply.
  777. * @return 1 if the reply was already sent, 0 on success, a negative number on
  778. * error
  779. */
  780. static int rpc_send(rpc_ctx_t* ctx)
  781. {
  782. struct xmlrpc_reply* reply;
  783. if (ctx->reply_sent) return 1;
  784. reply = &ctx->reply;
  785. if (reply->code >= 300) {
  786. if (build_fault_reply(reply) < 0) return -1;
  787. } else {
  788. if (ctx->flags & RET_ARRAY &&
  789. add_xmlrpc_reply(reply, &array_suffix) < 0) return -1;
  790. if (ctx->structs &&
  791. print_structures(reply, ctx->structs) < 0) return -1;
  792. if (add_xmlrpc_reply(reply, &success_suffix) < 0) return -1;
  793. }
  794. if (send_reply(ctx->msg, &reply->body) < 0) return -1;
  795. ctx->reply_sent = 1;
  796. return 0;
  797. }
  798. #define REASON_BUF_LEN 1024
  799. static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...)
  800. {
  801. static char buf[REASON_BUF_LEN];
  802. va_list ap;
  803. reply->code = code;
  804. va_start(ap, fmt);
  805. vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
  806. va_end(ap);
  807. reply->reason = buf;
  808. }
  809. /** Implementation of rpc_fault function required by the management API in
  810. * SER.
  811. *
  812. * This function will be called whenever a management function in SER
  813. * indicates that an error ocurred while it was processing the request. The
  814. * function takes the reply code and reason phrase as parameters, these will
  815. * be put in the body of the reply.
  816. *
  817. * @param ctx A pointer to the context structure of the request being
  818. * processed.
  819. * @param code Reason code.
  820. * @param fmt Formatting string used to build the reason phrase.
  821. */
  822. static void rpc_fault(rpc_ctx_t* ctx, int code, char* fmt, ...)
  823. {
  824. static char buf[REASON_BUF_LEN];
  825. va_list ap;
  826. ctx->reply.code = code;
  827. va_start(ap, fmt);
  828. vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
  829. va_end(ap);
  830. ctx->reply.reason = buf;
  831. }
  832. /** Create and initialize a new rpc_structure data structure.
  833. *
  834. * This function allocates and initializes memory for a new rpc_struct
  835. * structure. If the caller provided non-NULL pointers in doc and structure
  836. * parameters then the structure is coming from an XML-RPC request. If either
  837. * of the pointers is NULL then we are creating a structure that will be
  838. * attached to a XML-RPC reply sent to the client. The memory allocated in
  839. * this function will be added to the garbage collection list.
  840. *
  841. * @param doc A pointer to the XML-RPC request document or NULL if we create
  842. * a structure that will be put in a reply.
  843. * @param structure A pointer to opening tag of the structure in the XML-RPC
  844. * request document or NULL if we create a structure that
  845. * will be put in a XML-RPC reply.
  846. * @param reply A pointer to xml_reply structure, NULL if it is a structure
  847. * coming from a XML-RPC request.
  848. */
  849. static struct rpc_struct* new_rpcstruct(xmlDocPtr doc, xmlNodePtr structure,
  850. struct xmlrpc_reply* reply, int vtype)
  851. {
  852. struct rpc_struct* p;
  853. p = (struct rpc_struct*)mxr_malloc(sizeof(struct rpc_struct));
  854. if (!p) {
  855. set_fault(reply, 500, "Internal Server Error (No Memory Left");
  856. return 0;
  857. }
  858. memset(p, 0, sizeof(struct rpc_struct));
  859. p->struct_in = structure;
  860. p->reply = reply;
  861. p->n = 0;
  862. p->vtype = vtype;
  863. if (doc && structure) {
  864. /* We will be parsing structure from request */
  865. p->doc = doc;
  866. p->struct_in = structure;
  867. } else {
  868. /* We will build a reply structure */
  869. if (init_xmlrpc_reply(&p->struct_out) < 0) goto err;
  870. if(vtype==RET_ARRAY) {
  871. if (add_xmlrpc_reply(&p->struct_out, &array_prefix) < 0) goto err;
  872. } else {
  873. if (add_xmlrpc_reply(&p->struct_out, &struct_prefix) < 0) goto err;
  874. }
  875. }
  876. if (add_garbage(JUNK_RPCSTRUCT, p, reply) < 0) goto err;
  877. return p;
  878. err:
  879. if (p->struct_out.buf.s) mxr_free(p->struct_out.buf.s);
  880. mxr_free(p);
  881. return 0;
  882. }
  883. /** Converts the variables provided in parameter ap according to formatting
  884. * string provided in parameter fmt into parameters in XML-RPC format.
  885. *
  886. * This function takes the parameters provided in ap parameter and creates
  887. * XML-RPC formatted parameters that will be put in the document in res
  888. * parameter. The format of input parameters is described in formatting string
  889. * fmt which follows the syntax of the management API in SER. In the case of
  890. * an error the function will generate an error reply in err_reply parameter
  891. * instead.
  892. * @param res A pointer to the XML-RPC result structure where the parameters
  893. * will be written.
  894. * @param err_reply An error reply document will be generated here if the
  895. * function encounters a problem while processing input
  896. * parameters.
  897. * @param fmt Formatting string of the management API in SER.
  898. * @param ap A pointer to the array of input parameters.
  899. *
  900. */
  901. static int print_value(struct xmlrpc_reply* res,
  902. struct xmlrpc_reply* err_reply, char fmt, va_list* ap)
  903. {
  904. str prefix, body, suffix;
  905. str* sp;
  906. char buf[256];
  907. time_t dt;
  908. struct tm* t;
  909. switch(fmt) {
  910. case 'd':
  911. prefix = int_prefix;
  912. suffix = int_suffix;
  913. body.s = sint2str(va_arg(*ap, int), &body.len);
  914. break;
  915. case 'u':
  916. prefix = int_prefix;
  917. suffix = int_suffix;
  918. body.s = int2str(va_arg(*ap, unsigned int), &body.len);
  919. break;
  920. case 'f':
  921. prefix = double_prefix;
  922. suffix = double_suffix;
  923. body.s = buf;
  924. body.len = snprintf(buf, 256, "%f", va_arg(*ap, double));
  925. if (body.len < 0) {
  926. set_fault(err_reply, 400, "Error While Converting double");
  927. ERR("Error while converting double\n");
  928. goto err;
  929. }
  930. break;
  931. case 'b':
  932. prefix = bool_prefix;
  933. suffix = bool_suffix;
  934. body.len = 1;
  935. body.s = ((va_arg(*ap, int) == 0) ? "0" : "1");
  936. break;
  937. case 't':
  938. prefix = date_prefix;
  939. suffix = date_suffix;
  940. body.s = buf;
  941. body.len = sizeof("19980717T14:08:55") - 1;
  942. dt = va_arg(*ap, time_t);
  943. t = gmtime(&dt);
  944. if (strftime(buf, 256, "%Y%m%dT%H:%M:%S", t) == 0) {
  945. set_fault(err_reply, 400, "Error While Converting datetime");
  946. ERR("Error while converting time\n");
  947. goto err;
  948. }
  949. break;
  950. case 's':
  951. prefix = string_prefix;
  952. suffix = string_suffix;
  953. body.s = va_arg(*ap, char*);
  954. body.len = strlen(body.s);
  955. break;
  956. case 'S':
  957. prefix = string_prefix;
  958. suffix = string_suffix;
  959. sp = va_arg(*ap, str*);
  960. body = *sp;
  961. break;
  962. default:
  963. set_fault(err_reply, 500, "Bug In SER (Invalid formatting character)");
  964. ERR("Invalid formatting character [%c]\n", fmt);
  965. goto err;
  966. }
  967. if (add_xmlrpc_reply(res, &prefix) < 0) goto err;
  968. if (add_xmlrpc_reply_esc(res, &body) < 0) goto err;
  969. if (add_xmlrpc_reply(res, &suffix) < 0) goto err;
  970. return 0;
  971. err:
  972. return -1;
  973. }
  974. /** Implementation of rpc_add function required by the management API in SER.
  975. *
  976. * This function will be called when a management function in SER calls
  977. * rpc->add to add a parameter to the XML-RPC reply being generated.
  978. */
  979. static int rpc_add(rpc_ctx_t* ctx, char* fmt, ...)
  980. {
  981. void* void_ptr;
  982. va_list ap;
  983. struct xmlrpc_reply* reply;
  984. struct rpc_struct* p;
  985. fix_delayed_reply_ctx(ctx);
  986. va_start(ap, fmt);
  987. reply = &ctx->reply;
  988. while(*fmt) {
  989. if (ctx->flags & RET_ARRAY &&
  990. add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  991. if (*fmt == '{' || *fmt == '[') {
  992. void_ptr = va_arg(ap, void**);
  993. p = new_rpcstruct(0, 0, reply, (*fmt=='[')?RET_ARRAY:0);
  994. if (!p) goto err;
  995. *(struct rpc_struct**)void_ptr = p;
  996. p->offset = get_reply_len(reply);
  997. p->next = ctx->structs;
  998. ctx->structs = p;
  999. } else {
  1000. if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
  1001. }
  1002. if (ctx->flags & RET_ARRAY &&
  1003. add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1004. if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
  1005. fmt++;
  1006. }
  1007. va_end(ap);
  1008. return 0;
  1009. err:
  1010. va_end(ap);
  1011. return -1;
  1012. }
  1013. /** Convert time in XML-RPC format to time_t */
  1014. static time_t xmlrpc2time(const char* str)
  1015. {
  1016. struct tm time;
  1017. memset(&time, '\0', sizeof(struct tm));
  1018. strptime(str, "%Y%m%dT%H:%M:%S", &time);
  1019. time.tm_isdst = -1;
  1020. #ifdef HAVE_TIMEGM
  1021. return timegm(&time);
  1022. #else
  1023. return _timegm(&time);
  1024. #endif /* HAVE_TIMEGM */
  1025. }
  1026. /* get_* flags: */
  1027. #define GET_X_AUTOCONV 1
  1028. #define GET_X_NOREPLY 2
  1029. #define GET_X_LFLF2CRLF 4 /* replace "\n\n" with "\r\n" */
  1030. /* xml value types */
  1031. enum xmlrpc_val_type{
  1032. XML_T_STR,
  1033. XML_T_TXT,
  1034. XML_T_INT,
  1035. XML_T_BOOL,
  1036. XML_T_DATE,
  1037. XML_T_DOUBLE,
  1038. XML_T_ERR=-1
  1039. };
  1040. /** Returns the XML-RPC value type.
  1041. * @return value type (>= on success, XML_T_ERR on error/unknown type)
  1042. */
  1043. static enum xmlrpc_val_type xml_get_type(xmlNodePtr value)
  1044. {
  1045. if (!xmlStrcmp(value->name, BAD_CAST "string")){
  1046. return XML_T_STR;
  1047. } else if (!xmlStrcmp(value->name, BAD_CAST "text")) {
  1048. return XML_T_TXT;
  1049. } else if ( !xmlStrcmp(value->name, BAD_CAST "i4") ||
  1050. !xmlStrcmp(value->name, BAD_CAST "int")) {
  1051. return XML_T_INT;
  1052. } else if (!xmlStrcmp(value->name, BAD_CAST "boolean")) {
  1053. return XML_T_BOOL;
  1054. } else if (!xmlStrcmp(value->name, BAD_CAST "dateTime.iso8601")) {
  1055. return XML_T_DATE;
  1056. }else if (!(xmlStrcmp(value->name, BAD_CAST "double"))){
  1057. return XML_T_DOUBLE;
  1058. }
  1059. return XML_T_ERR;
  1060. }
  1061. /** Converts an XML-RPC encoded parameter into integer if possible.
  1062. *
  1063. * This function receives a pointer to a parameter encoded in XML-RPC format
  1064. * and tries to convert the value of the parameter into integer. Only
  1065. * &lt;i4&gt;, &lt;int&gt;, &lt;boolean&gt;, &lt;dateTime.iso8601&gt; XML-RPC
  1066. * parameters can be converted to integer, attempts to conver other types will
  1067. * fail.
  1068. * @param val A pointer to an integer variable where the result will be
  1069. * stored.
  1070. * @param reply A pointer to XML-RPC reply being constructed (used to
  1071. * indicate conversion errors).
  1072. * @param doc A pointer to the XML-RPC request document.
  1073. * @param value A pointer to the element containing the parameter to be
  1074. * converted within the document.
  1075. * @param flags : GET_X_AUTOCONV - try autoconverting
  1076. * GET_X_NOREPLY - do not reply
  1077. * @return <0 on error, 0 on success
  1078. */
  1079. static int get_int(int* val, struct xmlrpc_reply* reply,
  1080. xmlDocPtr doc, xmlNodePtr value, int flags)
  1081. {
  1082. enum xmlrpc_val_type type;
  1083. int ret;
  1084. xmlNodePtr i4;
  1085. char* val_str;
  1086. char* end_ptr;
  1087. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1088. if (!(flags & GET_X_NOREPLY))
  1089. set_fault(reply, 400, "Invalid parameter value");
  1090. return -1;
  1091. }
  1092. i4 = value->xmlChildrenNode;
  1093. if (!i4){
  1094. if (!(flags & GET_X_NOREPLY))
  1095. set_fault(reply, 400, "Invalid Parameter Type");
  1096. return -1;
  1097. }
  1098. type=xml_get_type(i4);
  1099. switch(type){
  1100. case XML_T_INT:
  1101. case XML_T_BOOL:
  1102. case XML_T_DATE:
  1103. break;
  1104. case XML_T_DOUBLE:
  1105. case XML_T_STR:
  1106. case XML_T_TXT:
  1107. if (flags & GET_X_AUTOCONV)
  1108. break;
  1109. case XML_T_ERR:
  1110. if (!(flags & GET_X_NOREPLY))
  1111. set_fault(reply, 400, "Invalid Parameter Type");
  1112. return -1;
  1113. }
  1114. if (type == XML_T_TXT)
  1115. val_str = (char*)i4->content;
  1116. else
  1117. val_str = (char*)xmlNodeListGetString(doc, i4->xmlChildrenNode, 1);
  1118. if (!val_str) {
  1119. if (!(flags & GET_X_NOREPLY))
  1120. set_fault(reply, 400, "Empty Parameter Value");
  1121. return -1;
  1122. }
  1123. ret=0;
  1124. switch(type){
  1125. case XML_T_INT:
  1126. case XML_T_BOOL:
  1127. case XML_T_STR:
  1128. case XML_T_TXT:
  1129. /* Integer/bool conversion */
  1130. *val = strtol(val_str, &end_ptr, 10);
  1131. if (val_str==end_ptr)
  1132. ret=-1;
  1133. break;
  1134. case XML_T_DATE:
  1135. *val = xmlrpc2time(val_str);
  1136. break;
  1137. case XML_T_DOUBLE:
  1138. *val = (int)strtod(val_str, &end_ptr);
  1139. if (val_str==end_ptr)
  1140. ret=-1;
  1141. break;
  1142. case XML_T_ERR:
  1143. *val=0;
  1144. ret=-1;
  1145. break;
  1146. }
  1147. xmlFree(val_str);
  1148. if (ret==-1 && !(flags & GET_X_NOREPLY))
  1149. set_fault(reply, 400, "Invalid Value");
  1150. return ret;
  1151. }
  1152. /** Converts an XML-RPC encoded parameter into double if possible.
  1153. *
  1154. * This function receives a pointer to a parameter encoded in XML-RPC format
  1155. * and tries to convert the value of the parameter into double. Only
  1156. * &lt;i4&gt;, &lt;int&gt;, &lt;double&gt; XML-RPC parameters can be converted
  1157. * to double, attempts to conver other types will fail.
  1158. * @param val A pointer to an integer variable where the result will be
  1159. * stored.
  1160. * @param reply A pointer to XML-RPC reply being constructed (used to indicate
  1161. * conversion errors).
  1162. * @param doc A pointer to the XML-RPC request document.
  1163. * @param value A pointer to the element containing the parameter to be
  1164. * converted within the document.
  1165. * @param flags : GET_X_AUTOCONV - try autoconverting
  1166. * GET_X_NOREPLY - do not reply
  1167. * @return <0 on error, 0 on success
  1168. */
  1169. static int get_double(double* val, struct xmlrpc_reply* reply,
  1170. xmlDocPtr doc, xmlNodePtr value, int flags)
  1171. {
  1172. xmlNodePtr dbl;
  1173. char* val_str;
  1174. char* end_ptr;
  1175. enum xmlrpc_val_type type;
  1176. int ret;
  1177. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1178. if (!(flags & GET_X_NOREPLY))
  1179. set_fault(reply, 400, "Invalid Parameter Value");
  1180. return -1;
  1181. }
  1182. dbl = value->xmlChildrenNode;
  1183. if (!dbl){
  1184. if (!(flags & GET_X_NOREPLY))
  1185. set_fault(reply, 400, "Invalid Parameter Type");
  1186. return -1;
  1187. }
  1188. type=xml_get_type(dbl);
  1189. switch(type){
  1190. case XML_T_DOUBLE:
  1191. case XML_T_INT:
  1192. break;
  1193. case XML_T_BOOL:
  1194. case XML_T_DATE:
  1195. case XML_T_STR:
  1196. case XML_T_TXT:
  1197. if (flags & GET_X_AUTOCONV)
  1198. break;
  1199. case XML_T_ERR:
  1200. if (!(flags & GET_X_NOREPLY))
  1201. set_fault(reply, 400, "Invalid Parameter Type");
  1202. return -1;
  1203. }
  1204. if (type == XML_T_TXT)
  1205. val_str = (char*)dbl->content;
  1206. else
  1207. val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
  1208. if (!val_str) {
  1209. if (!(flags & GET_X_NOREPLY))
  1210. set_fault(reply, 400, "Empty Double Parameter");
  1211. return -1;
  1212. }
  1213. ret=0;
  1214. switch(type){
  1215. case XML_T_DOUBLE:
  1216. case XML_T_INT:
  1217. case XML_T_BOOL:
  1218. case XML_T_STR:
  1219. case XML_T_TXT:
  1220. *val = strtod(val_str, &end_ptr);
  1221. if (val_str==end_ptr)
  1222. ret=-1;
  1223. break;
  1224. case XML_T_DATE:
  1225. *val = (double)xmlrpc2time(val_str);
  1226. break;
  1227. case XML_T_ERR:
  1228. *val=0;
  1229. ret=-1;
  1230. break;
  1231. }
  1232. xmlFree(val_str);
  1233. if (ret==-1 && !(flags & GET_X_NOREPLY))
  1234. set_fault(reply, 400, "Invalid Value");
  1235. return ret;
  1236. }
  1237. /** Convert a parameter encoded in XML-RPC to a zero terminated string.
  1238. *
  1239. * @param val A pointer to a char* variable where the result will be
  1240. * stored (the result is dynamically allocated, but it's garbage
  1241. * collected, so it doesn't have to be freed)
  1242. * @param reply A pointer to XML-RPC reply being constructed (used to indicate
  1243. * conversion errors).
  1244. * @param doc A pointer to the XML-RPC request document.
  1245. * @param value A pointer to the element containing the parameter to be
  1246. * converted within the document.
  1247. * @param flags
  1248. * - GET_X_AUTOCONV - try autoconverting
  1249. * - GET_X_LFLF2CRLF - replace double '\\n' with `\\r\\n'
  1250. * - GET_X_NOREPLY - do not reply
  1251. * @return <0 on error, 0 on success
  1252. */
  1253. static int get_string(char** val, struct xmlrpc_reply* reply,
  1254. xmlDocPtr doc, xmlNodePtr value, int flags)
  1255. {
  1256. static char* null_str = "";
  1257. xmlNodePtr dbl;
  1258. char* val_str;
  1259. char* end_ptr;
  1260. char* s;
  1261. char* p;
  1262. int i;
  1263. int len;
  1264. enum xmlrpc_val_type type;
  1265. int ret;
  1266. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1267. if (!(flags & GET_X_NOREPLY))
  1268. set_fault(reply, 400, "Invalid Parameter Value");
  1269. return -1;
  1270. }
  1271. dbl = value->xmlChildrenNode;
  1272. if (!dbl){
  1273. if (!(flags & GET_X_NOREPLY))
  1274. set_fault(reply, 400, "Invalid Parameter Type");
  1275. return -1;
  1276. }
  1277. type=xml_get_type(dbl);
  1278. switch(type){
  1279. case XML_T_STR:
  1280. case XML_T_TXT:
  1281. break;
  1282. case XML_T_INT:
  1283. case XML_T_BOOL:
  1284. case XML_T_DATE:
  1285. case XML_T_DOUBLE:
  1286. if (flags & GET_X_AUTOCONV)
  1287. break;
  1288. case XML_T_ERR:
  1289. if (!(flags & GET_X_NOREPLY))
  1290. set_fault(reply, 400, "Invalid Parameter Type");
  1291. return -1;
  1292. }
  1293. if (type == XML_T_TXT)
  1294. val_str = (char*)dbl->content;
  1295. else
  1296. val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
  1297. if (!val_str) {
  1298. if (type==XML_T_STR || type==XML_T_TXT){
  1299. *val = null_str;
  1300. return 0;
  1301. }else{
  1302. if (!(flags & GET_X_NOREPLY))
  1303. set_fault(reply, 400, "Empty Parameter Value");
  1304. return -1;
  1305. }
  1306. }
  1307. ret=0;
  1308. switch(type){
  1309. case XML_T_STR:
  1310. case XML_T_TXT:
  1311. if (flags & GET_X_LFLF2CRLF){
  1312. p=val_str;
  1313. while(*p){
  1314. if (*p=='\n' && *(p+1)=='\n'){
  1315. *p='\r';
  1316. p+=2;
  1317. continue;
  1318. }
  1319. p++;
  1320. }
  1321. }
  1322. /* no break */
  1323. case XML_T_DATE: /* no special conversion */
  1324. case XML_T_DOUBLE: /* no special conversion */
  1325. if (add_garbage(JUNK_XMLCHAR, val_str, reply) < 0){
  1326. xmlFree(val_str);
  1327. return -1;
  1328. }
  1329. *val = val_str;
  1330. break;
  1331. case XML_T_INT:
  1332. case XML_T_BOOL:
  1333. /* convert str to int an back to str */
  1334. i = strtol(val_str, &end_ptr, 10);
  1335. if (val_str==end_ptr){
  1336. ret=-1;
  1337. }else{
  1338. s=sint2str(i, &len);
  1339. p=mxr_malloc(len+1);
  1340. if (p && add_garbage(JUNK_PKGCHAR, p, reply) == 0){
  1341. memcpy(p, s, len);
  1342. p[len]=0;
  1343. *val=p;
  1344. }else{
  1345. ret=-1;
  1346. if (p) mxr_free(p);
  1347. }
  1348. }
  1349. xmlFree(val_str);
  1350. break;
  1351. case XML_T_ERR:
  1352. xmlFree(val_str);
  1353. ret=-1;
  1354. break;
  1355. }
  1356. return ret;
  1357. }
  1358. /** Implementation of rpc->scan function required by the management API in
  1359. * SER.
  1360. *
  1361. * This is the function that will be called whenever a management function in
  1362. * SER calls rpc->scan to get the value of parameter from the XML-RPC
  1363. * request. This function will extract the current parameter from the XML-RPC
  1364. * document and attempts to convert it to the type requested by the management
  1365. * function that called it.
  1366. */
  1367. static int rpc_scan(rpc_ctx_t* ctx, char* fmt, ...)
  1368. {
  1369. int read;
  1370. int ival;
  1371. int* int_ptr;
  1372. unsigned int* uint_ptr;
  1373. char** char_ptr;
  1374. str* str_ptr;
  1375. double* double_ptr;
  1376. void** void_ptr;
  1377. xmlNodePtr value;
  1378. struct xmlrpc_reply* reply;
  1379. struct rpc_struct* p;
  1380. int modifiers;
  1381. int f;
  1382. va_list ap;
  1383. int nofault;
  1384. reply = &ctx->reply;
  1385. /* clear the previously saved error code */
  1386. clear_xmlrpc_reply(reply);
  1387. va_start(ap, fmt);
  1388. modifiers=0;
  1389. read = 0;
  1390. nofault = 0;
  1391. f=(autoconvert?GET_X_AUTOCONV:0) |
  1392. (lflf2crlf?GET_X_LFLF2CRLF:0);
  1393. while(*fmt) {
  1394. if (!ctx->act_param) goto error;
  1395. value = ctx->act_param->xmlChildrenNode;
  1396. switch(*fmt) {
  1397. case '*': /* start of optional parameters */
  1398. modifiers++;
  1399. read++;
  1400. fmt++;
  1401. nofault=1;
  1402. f|=GET_X_NOREPLY;
  1403. continue; /* do not advance ctx->act-param */
  1404. case '.': /* autoconvert */
  1405. modifiers++;
  1406. read++;
  1407. fmt++;
  1408. f|=GET_X_AUTOCONV;
  1409. continue; /* do not advance ctx->act-param */
  1410. case 'b': /* Bool */
  1411. case 't': /* Date and time */
  1412. case 'd': /* Integer */
  1413. int_ptr = va_arg(ap, int*);
  1414. if (get_int(int_ptr, reply, ctx->doc, value, f) < 0) goto error;
  1415. break;
  1416. case 'u': /* Integer */
  1417. uint_ptr = va_arg(ap, unsigned int*);
  1418. if (get_int(&ival, reply, ctx->doc, value, f) < 0) goto error;
  1419. *uint_ptr = (unsigned int)ival;
  1420. break;
  1421. case 'f': /* double */
  1422. double_ptr = va_arg(ap, double*);
  1423. if (get_double(double_ptr, reply, ctx->doc, value, f) < 0) {
  1424. goto error;
  1425. }
  1426. break;
  1427. case 's': /* zero terminated string */
  1428. char_ptr = va_arg(ap, char**);
  1429. if (get_string(char_ptr, reply, ctx->doc, value, f) < 0)
  1430. goto error;
  1431. break;
  1432. case 'S': /* str structure */
  1433. str_ptr = va_arg(ap, str*);
  1434. if (get_string(&str_ptr->s, reply, ctx->doc, value, f) < 0) {
  1435. goto error;
  1436. }
  1437. str_ptr->len = strlen(str_ptr->s);
  1438. break;
  1439. case '{':
  1440. void_ptr = va_arg(ap, void**);
  1441. if (!value->xmlChildrenNode) goto error;
  1442. p = new_rpcstruct(ctx->doc, value->xmlChildrenNode, reply, 0);
  1443. if (!p) goto error;
  1444. *void_ptr = p;
  1445. break;
  1446. default:
  1447. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1448. set_fault(reply, 500,
  1449. "Server Internal Error (Invalid Formatting String)");
  1450. goto error;
  1451. }
  1452. ctx->act_param = ctx->act_param->next;
  1453. /* clear autoconv if not globally on */
  1454. f=autoconvert?GET_X_AUTOCONV:(f&~GET_X_AUTOCONV);
  1455. read++;
  1456. fmt++;
  1457. }
  1458. va_end(ap);
  1459. return read-modifiers;
  1460. error:
  1461. va_end(ap);
  1462. if(nofault==0)
  1463. return -(read-modifiers);
  1464. else
  1465. return read-modifiers;
  1466. }
  1467. #define RPC_BUF_SIZE 1024
  1468. /** Implementation of rpc_rpl_printf function required by the management API in
  1469. * SER.
  1470. *
  1471. * This function will be called whenever a management function in SER calls
  1472. * rpc-printf to add a parameter to the XML-RPC reply being constructed.
  1473. */
  1474. static int rpc_rpl_printf(rpc_ctx_t* ctx, char* fmt, ...)
  1475. {
  1476. int n, buf_size;
  1477. char* buf;
  1478. va_list ap;
  1479. str s;
  1480. struct xmlrpc_reply* reply;
  1481. fix_delayed_reply_ctx(ctx);
  1482. reply = &ctx->reply;
  1483. buf = (char*)mxr_malloc(RPC_BUF_SIZE);
  1484. if (!buf) {
  1485. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1486. ERR("No memory left\n");
  1487. return -1;
  1488. }
  1489. buf_size = RPC_BUF_SIZE;
  1490. while (1) {
  1491. /* Try to print in the allocated space. */
  1492. va_start(ap, fmt);
  1493. n = vsnprintf(buf, buf_size, fmt, ap);
  1494. va_end(ap);
  1495. /* If that worked, return the string. */
  1496. if (n > -1 && n < buf_size) {
  1497. s.s = buf;
  1498. s.len = n;
  1499. if (ctx->flags & RET_ARRAY &&
  1500. add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  1501. if (add_xmlrpc_reply(reply, &string_prefix) < 0) goto err;
  1502. if (add_xmlrpc_reply_esc(reply, &s) < 0) goto err;
  1503. if (add_xmlrpc_reply(reply, &string_suffix) < 0) goto err;
  1504. if (ctx->flags & RET_ARRAY &&
  1505. add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1506. if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
  1507. mxr_free(buf);
  1508. return 0;
  1509. }
  1510. /* Else try again with more space. */
  1511. if (n > -1) { /* glibc 2.1 */
  1512. buf_size = n + 1; /* precisely what is needed */
  1513. } else { /* glibc 2.0 */
  1514. buf_size *= 2; /* twice the old size */
  1515. }
  1516. if ((buf = mxr_realloc(buf, buf_size)) == 0) {
  1517. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1518. ERR("No memory left\n");
  1519. goto err;
  1520. }
  1521. }
  1522. return 0;
  1523. err:
  1524. if (buf) mxr_free(buf);
  1525. return -1;
  1526. }
  1527. /* Structure manipulation functions */
  1528. /** Find a structure member by name.
  1529. */
  1530. static int find_member(xmlNodePtr* value, xmlDocPtr doc, xmlNodePtr structure,
  1531. struct xmlrpc_reply* reply, char* member_name)
  1532. {
  1533. char* name_str;
  1534. xmlNodePtr member, name;
  1535. if (!structure) {
  1536. set_fault(reply, 400, "Invalid Structure Parameter");
  1537. return -1;
  1538. }
  1539. member = structure->xmlChildrenNode;
  1540. while(member) {
  1541. name = member->xmlChildrenNode;
  1542. /* Find <name> node in the member */
  1543. while(name) {
  1544. if (!xmlStrcmp(name->name, BAD_CAST "name")) break;
  1545. name = name->next;
  1546. }
  1547. if (!name) {
  1548. set_fault(reply, 400, "Member Name Not Found In Structure");
  1549. return -1;
  1550. }
  1551. /* Check the value of <name> node in the structure member */
  1552. name_str = (char*)xmlNodeListGetString(doc, name->xmlChildrenNode, 1);
  1553. if (!name_str) {
  1554. set_fault(reply, 400, "Empty name Element of Structure Parameter");
  1555. return -1;
  1556. }
  1557. if (strcmp(name_str, member_name)) {
  1558. xmlFree(name_str);
  1559. goto skip;
  1560. }
  1561. xmlFree(name_str);
  1562. *value = member->xmlChildrenNode;
  1563. while(*value) {
  1564. if (!xmlStrcmp((*value)->name, BAD_CAST "value")) break;
  1565. (*value) = (*value)->next;
  1566. }
  1567. if (!(*value)) {
  1568. set_fault(reply, 400, "Member Value Not Found In Structure");
  1569. return -1;
  1570. }
  1571. return 0;
  1572. skip:
  1573. member = member->next;
  1574. }
  1575. return 1;
  1576. }
  1577. /** Adds a new member to structure.
  1578. */
  1579. static int rpc_struct_add(struct rpc_struct* s, char* fmt, ...)
  1580. {
  1581. va_list ap;
  1582. str member_name;
  1583. struct xmlrpc_reply* reply;
  1584. void* void_ptr;
  1585. struct rpc_struct* p, *tmp;
  1586. reply = &s->struct_out;
  1587. va_start(ap, fmt);
  1588. while(*fmt) {
  1589. member_name.s = va_arg(ap, char*);
  1590. member_name.len = (member_name.s ? strlen(member_name.s) : 0);
  1591. if(s->vtype==RET_ARRAY && *fmt == '{') {
  1592. if (add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  1593. if (add_xmlrpc_reply(reply, &struct_prefix) < 0) goto err;
  1594. }
  1595. if (add_xmlrpc_reply(reply, &member_prefix) < 0) goto err;
  1596. if (add_xmlrpc_reply(reply, &name_prefix) < 0) goto err;
  1597. if (add_xmlrpc_reply_esc(reply, &member_name) < 0) goto err;
  1598. if (add_xmlrpc_reply(reply, &name_suffix) < 0) goto err;
  1599. if (add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  1600. if (*fmt == '{' || *fmt == '[') {
  1601. void_ptr = va_arg(ap, void**);
  1602. p = new_rpcstruct(0, 0, s->reply, (*fmt=='[')?RET_ARRAY:0);
  1603. if (!p)
  1604. goto err;
  1605. *(struct rpc_struct**) void_ptr = p;
  1606. p->offset = get_reply_len(reply);
  1607. p->parent = s;
  1608. if (!s->nnext) {
  1609. s->nnext = p;
  1610. } else {
  1611. for (tmp = s; tmp->nnext; tmp=tmp->nnext);
  1612. tmp->nnext = p;
  1613. }
  1614. } else {
  1615. if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
  1616. }
  1617. if (add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1618. if (add_xmlrpc_reply(reply, &member_suffix) < 0) goto err;
  1619. if(s->vtype==RET_ARRAY && *fmt == '{') {
  1620. if (add_xmlrpc_reply(reply, &struct_suffix) < 0) goto err;
  1621. if (add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1622. }
  1623. fmt++;
  1624. }
  1625. va_end(ap);
  1626. return 0;
  1627. err:
  1628. va_end(ap);
  1629. return -1;
  1630. }
  1631. /** Adds a new value to an array.
  1632. */
  1633. static int rpc_array_add(struct rpc_struct* s, char* fmt, ...)
  1634. {
  1635. va_list ap;
  1636. struct xmlrpc_reply* reply;
  1637. void* void_ptr;
  1638. struct rpc_struct* p, *tmp;
  1639. reply = &s->struct_out;
  1640. if(s->vtype!=RET_ARRAY) {
  1641. LM_ERR("parent structure is not an array\n");
  1642. goto err;
  1643. }
  1644. va_start(ap, fmt);
  1645. while(*fmt) {
  1646. if (*fmt == '{' || *fmt == '[') {
  1647. void_ptr = va_arg(ap, void**);
  1648. p = new_rpcstruct(0, 0, s->reply, (*fmt=='[')?RET_ARRAY:0);
  1649. if (!p)
  1650. goto err;
  1651. *(struct rpc_struct**) void_ptr = p;
  1652. p->offset = get_reply_len(reply);
  1653. p->parent = s;
  1654. if (!s->nnext) {
  1655. s->nnext = p;
  1656. } else {
  1657. for (tmp = s; tmp->nnext; tmp=tmp->nnext);
  1658. tmp->nnext = p;
  1659. }
  1660. } else {
  1661. if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
  1662. }
  1663. fmt++;
  1664. }
  1665. va_end(ap);
  1666. return 0;
  1667. err:
  1668. va_end(ap);
  1669. return -1;
  1670. }
  1671. /** Create a new member from formatting string and add it to a structure.
  1672. */
  1673. static int rpc_struct_printf(struct rpc_struct* s, char* member_name,
  1674. char* fmt, ...)
  1675. {
  1676. int n, buf_size;
  1677. char* buf;
  1678. va_list ap;
  1679. str st, name;
  1680. struct xmlrpc_reply* reply;
  1681. struct xmlrpc_reply* out;
  1682. out = &s->struct_out;
  1683. buf = (char*)mxr_malloc(RPC_BUF_SIZE);
  1684. reply = s->reply;
  1685. if (!buf) {
  1686. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1687. ERR("No memory left\n");
  1688. return -1;
  1689. }
  1690. buf_size = RPC_BUF_SIZE;
  1691. while (1) {
  1692. /* Try to print in the allocated space. */
  1693. va_start(ap, fmt);
  1694. n = vsnprintf(buf, buf_size, fmt, ap);
  1695. va_end(ap);
  1696. /* If that worked, return the string. */
  1697. if (n > -1 && n < buf_size) {
  1698. st.s = buf;
  1699. st.len = n;
  1700. name.s = member_name;
  1701. name.len = strlen(member_name);
  1702. if (add_xmlrpc_reply(out, &member_prefix) < 0) goto err;
  1703. if (add_xmlrpc_reply(out, &name_prefix) < 0) goto err;
  1704. if (add_xmlrpc_reply_esc(out, &name) < 0) goto err;
  1705. if (add_xmlrpc_reply(out, &name_suffix) < 0) goto err;
  1706. if (add_xmlrpc_reply(out, &value_prefix) < 0) goto err;
  1707. if (add_xmlrpc_reply(out, &string_prefix) < 0) goto err;
  1708. if (add_xmlrpc_reply_esc(out, &st) < 0) goto err;
  1709. if (add_xmlrpc_reply(out, &string_suffix) < 0) goto err;
  1710. if (add_xmlrpc_reply(out, &value_suffix) < 0) goto err;
  1711. if (add_xmlrpc_reply(out, &member_suffix) < 0) goto err;
  1712. return 0;
  1713. }
  1714. /* Else try again with more space. */
  1715. if (n > -1) { /* glibc 2.1 */
  1716. buf_size = n + 1; /* precisely what is needed */
  1717. } else { /* glibc 2.0 */
  1718. buf_size *= 2; /* twice the old size */
  1719. }
  1720. if ((buf = mxr_realloc(buf, buf_size)) == 0) {
  1721. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1722. ERR("No memory left\n");
  1723. goto err;
  1724. }
  1725. }
  1726. return 0;
  1727. err:
  1728. if (buf) mxr_free(buf);
  1729. return -1;
  1730. }
  1731. static int rpc_struct_scan(struct rpc_struct* s, char* fmt, ...)
  1732. {
  1733. int read;
  1734. int ival;
  1735. va_list ap;
  1736. int* int_ptr;
  1737. unsigned int* uint_ptr;
  1738. double* double_ptr;
  1739. char** char_ptr;
  1740. str* str_ptr;
  1741. xmlNodePtr value;
  1742. char* member_name;
  1743. struct xmlrpc_reply* reply;
  1744. int ret;
  1745. int f;
  1746. read = 0;
  1747. f=(autoconvert?GET_X_AUTOCONV:0) |
  1748. (lflf2crlf?GET_X_LFLF2CRLF:0);
  1749. va_start(ap, fmt);
  1750. while(*fmt) {
  1751. member_name = va_arg(ap, char*);
  1752. reply = s->reply;
  1753. /* clear the previously saved error code */
  1754. clear_xmlrpc_reply(reply);
  1755. ret = find_member(&value, s->doc, s->struct_in, reply, member_name);
  1756. if (ret != 0) goto error;
  1757. switch(*fmt) {
  1758. case 'b': /* Bool */
  1759. case 't': /* Date and time */
  1760. case 'd': /* Integer */
  1761. int_ptr = va_arg(ap, int*);
  1762. if (get_int(int_ptr, reply, s->doc, value, f) < 0) goto error;
  1763. break;
  1764. case 'u': /* Integer */
  1765. uint_ptr = va_arg(ap, unsigned int*);
  1766. if (get_int(&ival, reply, s->doc, value, f) < 0) goto error;
  1767. *uint_ptr = (unsigned int)ival;
  1768. break;
  1769. case 'f': /* double */
  1770. double_ptr = va_arg(ap, double*);
  1771. if (get_double(double_ptr, reply, s->doc, value, f) < 0)
  1772. goto error;
  1773. break;
  1774. case 's': /* zero terminated string */
  1775. char_ptr = va_arg(ap, char**);
  1776. if (get_string(char_ptr, reply, s->doc, value, f) < 0) goto error;
  1777. break;
  1778. case 'S': /* str structure */
  1779. str_ptr = va_arg(ap, str*);
  1780. if (get_string(&str_ptr->s, reply, s->doc, value, f) < 0)
  1781. goto error;
  1782. str_ptr->len = strlen(str_ptr->s);
  1783. break;
  1784. default:
  1785. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1786. return -1;
  1787. }
  1788. fmt++;
  1789. read++;
  1790. }
  1791. va_end(ap);
  1792. return read;
  1793. error:
  1794. va_end(ap);
  1795. return -read;
  1796. }
  1797. /** Returns the RPC capabilities supported by the xmlrpc driver.
  1798. */
  1799. static rpc_capabilities_t rpc_capabilities(rpc_ctx_t* ctx)
  1800. {
  1801. return RPC_DELAYED_REPLY;
  1802. }
  1803. /** Returns a new "delayed reply" context.
  1804. * Creates a new delayed reply context in shm and returns it.
  1805. * @return 0 - not supported, already replied, or no more memory;
  1806. * !=0 pointer to the special delayed ctx.
  1807. * Note1: one should use the returned ctx reply context to build a reply and
  1808. * when finished call rpc_delayed_ctx_close().
  1809. * Note2: adding pieces to the reply in different processes is not supported.
  1810. */
  1811. static struct rpc_delayed_ctx* rpc_delayed_ctx_new(rpc_ctx_t* ctx)
  1812. {
  1813. struct rpc_delayed_ctx* ret;
  1814. int size;
  1815. rpc_ctx_t* r_ctx;
  1816. struct sip_msg* shm_msg;
  1817. int len;
  1818. ret=0;
  1819. shm_msg=0;
  1820. if (ctx->reply_sent)
  1821. return 0; /* no delayed reply if already replied */
  1822. /* clone the sip msg */
  1823. shm_msg=sip_msg_shm_clone(ctx->msg, &len, 1);
  1824. if (shm_msg==0)
  1825. goto error;
  1826. /* alloc into one block */
  1827. size=ROUND_POINTER(sizeof(*ret))+sizeof(rpc_ctx_t);
  1828. if ((ret=shm_malloc(size))==0)
  1829. goto error;
  1830. memset(ret, 0, size);
  1831. ret->rpc=func_param;
  1832. ret->reply_ctx=(char*)ret+ROUND_POINTER(sizeof(*ret));
  1833. r_ctx=ret->reply_ctx;
  1834. r_ctx->flags=ctx->flags | XMLRPC_DELAYED_CTX_F;
  1835. ctx->flags |= XMLRPC_DELAYED_REPLY_F;
  1836. r_ctx->msg=shm_msg;
  1837. r_ctx->msg_shm_block_size=len;
  1838. return ret;
  1839. error:
  1840. if (shm_msg)
  1841. shm_free(shm_msg);
  1842. if (ret)
  1843. shm_free(ret);
  1844. return 0;
  1845. }
  1846. /** Closes a "delayed reply" context and sends the reply.
  1847. * If no reply has been sent the reply will be built and sent automatically.
  1848. * See the notes from rpc_new_delayed_ctx()
  1849. */
  1850. static void rpc_delayed_ctx_close(struct rpc_delayed_ctx* dctx)
  1851. {
  1852. rpc_ctx_t* r_ctx;
  1853. struct hdr_field* hdr;
  1854. r_ctx=dctx->reply_ctx;
  1855. if (unlikely(!(r_ctx->flags & XMLRPC_DELAYED_CTX_F))){
  1856. BUG("reply ctx not marked as async/delayed\n");
  1857. goto error;
  1858. }
  1859. if (fix_delayed_reply_ctx(r_ctx)<0)
  1860. goto error;
  1861. if (!r_ctx->reply_sent){
  1862. rpc_send(r_ctx);
  1863. }
  1864. error:
  1865. clean_context(r_ctx);
  1866. /* collect possible garbage (e.g. generated by structures) */
  1867. collect_garbage();
  1868. /* free added lumps (rpc_send adds a body lump) */
  1869. del_nonshm_lump( &(r_ctx->msg->add_rm) );
  1870. del_nonshm_lump( &(r_ctx->msg->body_lumps) );
  1871. del_nonshm_lump_rpl( &(r_ctx->msg->reply_lump) );
  1872. /* free header's parsed structures that were added by failure handlers */
  1873. for( hdr=r_ctx->msg->headers ; hdr ; hdr=hdr->next ) {
  1874. if ( hdr->parsed && hdr_allocs_parse(hdr) &&
  1875. (hdr->parsed<(void*)r_ctx->msg ||
  1876. hdr->parsed>=(void*)(r_ctx->msg+r_ctx->msg_shm_block_size))) {
  1877. /* header parsed filed doesn't point inside uas.request memory
  1878. * chunck -> it was added by failure funcs.-> free it as pkg */
  1879. DBG("DBG:free_faked_req: removing hdr->parsed %d\n",
  1880. hdr->type);
  1881. clean_hdr_field(hdr);
  1882. hdr->parsed = 0;
  1883. }
  1884. }
  1885. shm_free(r_ctx->msg);
  1886. r_ctx->msg=0;
  1887. dctx->reply_ctx=0;
  1888. shm_free(dctx);
  1889. }
  1890. /** Starts parsing XML-RPC document, get the name of the method to be called
  1891. * and position the cursor at the first parameter in the document.
  1892. */
  1893. static int open_doc(rpc_ctx_t* ctx, sip_msg_t* msg)
  1894. {
  1895. str doc = {NULL,0};
  1896. xmlNodePtr root;
  1897. xmlNodePtr cur;
  1898. struct xmlrpc_reply* reply;
  1899. reply = &ctx->reply;
  1900. if (get_rpc_document(&doc, msg) < 0) {
  1901. set_fault(reply, 400, "Malformed Message Body");
  1902. ERR("Error extracting message body\n");
  1903. return -1;
  1904. }
  1905. ctx->doc = xmlReadMemory(doc.s, doc.len, 0, 0,
  1906. XML_PARSE_NOBLANKS |
  1907. XML_PARSE_NONET |
  1908. XML_PARSE_NOCDATA);
  1909. if (!ctx->doc) {
  1910. set_fault(reply, 400, "Invalid XML-RPC Document");
  1911. ERR("Invalid XML-RPC document: \n[%.*s]\n", doc.len, doc.s);
  1912. goto err;
  1913. }
  1914. root = xmlDocGetRootElement(ctx->doc);
  1915. if (!root) {
  1916. set_fault(reply, 400, "Empty XML-RPC Document");
  1917. ERR("Empty XML-RPC document\n");
  1918. goto err;
  1919. }
  1920. if (xmlStrcmp(root->name, (const xmlChar*)"methodCall")) {
  1921. set_fault(reply, 400, "Root Element Is Not methodCall");
  1922. ERR("Root element is not methodCall\n");
  1923. goto err;
  1924. }
  1925. cur = root->xmlChildrenNode;
  1926. while(cur) {
  1927. if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
  1928. ctx->method = (char*)xmlNodeListGetString(ctx->doc, cur->xmlChildrenNode, 1);
  1929. if (!ctx->method) {
  1930. set_fault(reply, 400, "Cannot Extract Method Name");
  1931. ERR("Cannot extract method name\n");
  1932. goto err;
  1933. }
  1934. break;
  1935. }
  1936. cur = cur->next;
  1937. }
  1938. if (!cur) {
  1939. set_fault(reply, 400, "Method Name Not Found");
  1940. ERR("Method name not found\n");
  1941. goto err;
  1942. }
  1943. cur = root->xmlChildrenNode;
  1944. while(cur) {
  1945. if (!xmlStrcmp(cur->name, (const xmlChar*)"params")) {
  1946. ctx->act_param = cur->xmlChildrenNode;
  1947. break;
  1948. }
  1949. cur = cur->next;
  1950. }
  1951. if (!cur) ctx->act_param = 0;
  1952. return 0;
  1953. err:
  1954. close_doc(ctx);
  1955. return -1;
  1956. }
  1957. static void close_doc(rpc_ctx_t* ctx)
  1958. {
  1959. if (ctx->method) xmlFree(ctx->method);
  1960. if (ctx->doc) xmlFreeDoc(ctx->doc);
  1961. ctx->method = 0;
  1962. ctx->doc = 0;
  1963. }
  1964. static int init_context(rpc_ctx_t* ctx, sip_msg_t* msg)
  1965. {
  1966. ctx->msg = msg;
  1967. ctx->msg_shm_block_size=0;
  1968. ctx->method = 0;
  1969. ctx->reply_sent = 0;
  1970. ctx->act_param = 0;
  1971. ctx->doc = 0;
  1972. ctx->structs = 0;
  1973. if (init_xmlrpc_reply(&ctx->reply) < 0) return -1;
  1974. add_xmlrpc_reply(&ctx->reply, &success_prefix);
  1975. if (open_doc(ctx, msg) < 0) return -1;
  1976. return 0;
  1977. }
  1978. static void clean_context(rpc_ctx_t* ctx)
  1979. {
  1980. if (!ctx) return;
  1981. clean_xmlrpc_reply(&ctx->reply);
  1982. close_doc(ctx);
  1983. }
  1984. /** Creates a SIP message (in "buffer" form) from a HTTP XML-RPC request).
  1985. *
  1986. * NOTE: the result must be mxr_free()'ed when not needed anymore.
  1987. * @return 0 on error, buffer allocated using mxr_malloc on success.
  1988. */
  1989. static char* http_xmlrpc2sip(sip_msg_t* msg, int* new_msg_len)
  1990. {
  1991. unsigned int len, via_len;
  1992. char* via, *new_msg, *p;
  1993. str ip, port;
  1994. struct hostport hp;
  1995. struct dest_info dst;
  1996. /* create a via */
  1997. ip.s = ip_addr2a(&msg->rcv.src_ip);
  1998. ip.len = strlen(ip.s);
  1999. port.s = int2str(msg->rcv.src_port, &port.len);
  2000. hp.host = &ip;
  2001. hp.port = &port;
  2002. init_dst_from_rcv(&dst, &msg->rcv);
  2003. via = via_builder(&via_len, &dst, 0, 0, &hp);
  2004. if (via == 0) {
  2005. DEBUG("failed to build via\n");
  2006. return 0;
  2007. }
  2008. len = msg->first_line.u.request.method.len + 1 /* space */ +
  2009. XMLRPC_URI_LEN + 1 /* space */ +
  2010. msg->first_line.u.request.version.len + CRLF_LEN + via_len +
  2011. (msg->len-msg->first_line.len);
  2012. p = new_msg = mxr_malloc(len + 1);
  2013. if (new_msg == 0) {
  2014. DEBUG("memory allocation failure (%d bytes)\n", len);
  2015. pkg_free(via);
  2016. return 0;
  2017. }
  2018. /* new message:
  2019. * <orig_http_method> sip:127.0.0.1:9 HTTP/1.x
  2020. * Via: <faked via>
  2021. * <orig. http message w/o the first line>
  2022. */
  2023. memcpy(p, msg->first_line.u.request.method.s,
  2024. msg->first_line.u.request.method.len);
  2025. p += msg->first_line.u.request.method.len;
  2026. *p = ' ';
  2027. p++;
  2028. memcpy(p, XMLRPC_URI, XMLRPC_URI_LEN);
  2029. p += XMLRPC_URI_LEN;
  2030. *p = ' ';
  2031. p++;
  2032. memcpy(p, msg->first_line.u.request.version.s,
  2033. msg->first_line.u.request.version.len);
  2034. p += msg->first_line.u.request.version.len;
  2035. memcpy(p, CRLF, CRLF_LEN);
  2036. p += CRLF_LEN;
  2037. memcpy(p, via, via_len);
  2038. p += via_len;
  2039. memcpy(p, SIP_MSG_START(msg) + msg->first_line.len,
  2040. msg->len - msg->first_line.len);
  2041. new_msg[len] = 0; /* null terminate, required by receive_msg() */
  2042. pkg_free(via);
  2043. *new_msg_len = len;
  2044. return new_msg;
  2045. }
  2046. /** Emulate receive_msg for an XML-RPC request .
  2047. */
  2048. static int em_receive_request(sip_msg_t* orig_msg,
  2049. char* new_buf, unsigned int new_len)
  2050. {
  2051. int ret;
  2052. sip_msg_t tmp_msg, *msg;
  2053. struct run_act_ctx ra_ctx;
  2054. ret=0;
  2055. if (new_buf && new_len) {
  2056. memset(&tmp_msg, 0, sizeof(sip_msg_t));
  2057. tmp_msg.buf = new_buf;
  2058. tmp_msg.len = new_len;
  2059. tmp_msg.rcv = orig_msg->rcv;
  2060. tmp_msg.id = orig_msg->id;
  2061. tmp_msg.set_global_address = orig_msg->set_global_address;
  2062. tmp_msg.set_global_port = orig_msg->set_global_port;
  2063. if (parse_msg(new_buf, new_len, &tmp_msg) != 0) {
  2064. ERR("xmlrpc: parse_msg failed\n");
  2065. goto error;
  2066. }
  2067. msg = &tmp_msg;
  2068. } else {
  2069. msg = orig_msg;
  2070. }
  2071. /* not needed, performed by the "real" receive_msg()
  2072. clear_branches();
  2073. reset_static_buffer();
  2074. */
  2075. if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
  2076. (msg->via1->error != PARSE_OK)) {
  2077. BUG("xmlrpc: strange message: %.*s\n", msg->len, msg->buf);
  2078. goto error;
  2079. }
  2080. if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) {
  2081. goto end; /* drop request */
  2082. }
  2083. /* exec routing script */
  2084. init_run_actions_ctx(&ra_ctx);
  2085. if (run_actions(&ra_ctx, main_rt.rlist[xmlrpc_route_no], msg) < 0) {
  2086. ret=-1;
  2087. DBG("xmlrpc: error while trying script\n");
  2088. goto end;
  2089. }
  2090. end:
  2091. exec_post_script_cb(msg, REQUEST_CB_TYPE); /* needed for example if tm is used */
  2092. /* reset_avps(); non needed, performed by the real receive_msg */
  2093. if (msg != orig_msg) { /* avoid double free (freed from receive_msg
  2094. too) */
  2095. free_sip_msg(msg);
  2096. }
  2097. return ret;
  2098. error:
  2099. return -1;
  2100. }
  2101. /** The main handler that will be called when SER core receives a non-SIP
  2102. * request (i.e. HTTP request carrying XML-RPC document in the body).
  2103. */
  2104. static int process_xmlrpc(sip_msg_t* msg)
  2105. {
  2106. int ret;
  2107. char* fake_msg;
  2108. int fake_msg_len;
  2109. unsigned char* method;
  2110. unsigned int method_len, n_method;
  2111. regmatch_t pmatch;
  2112. char c;
  2113. ret=NONSIP_MSG_DROP;
  2114. if (!IS_HTTP(msg))
  2115. return NONSIP_MSG_PASS;
  2116. if(xmlrpc_url_skip!=NULL || xmlrpc_url_match!=NULL)
  2117. {
  2118. c = msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len];
  2119. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2120. = '\0';
  2121. if (xmlrpc_url_skip!=NULL &&
  2122. regexec(&xmlrpc_url_skip_regexp, msg->first_line.u.request.uri.s,
  2123. 1, &pmatch, 0)==0)
  2124. {
  2125. LM_DBG("URL matched skip re\n");
  2126. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2127. = c;
  2128. return NONSIP_MSG_PASS;
  2129. }
  2130. if (xmlrpc_url_match!=NULL &&
  2131. regexec(&xmlrpc_url_match_regexp, msg->first_line.u.request.uri.s,
  2132. 1, &pmatch, 0)!=0)
  2133. {
  2134. LM_DBG("URL not matched\n");
  2135. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2136. = c;
  2137. return NONSIP_MSG_PASS;
  2138. }
  2139. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len] = c;
  2140. }
  2141. method = (unsigned char*)msg->first_line.u.request.method.s;
  2142. method_len = msg->first_line.u.request.method.len;
  2143. /* first line is always > 4, so it's always safe to try to read the
  2144. * 1st 4 bytes from method, even if method is shorter*/
  2145. n_method = method[0] + (method[1] << 8) + (method[2] << 16) +
  2146. (method[3] << 24);
  2147. n_method |= 0x20202020;
  2148. n_method &= ((method_len < 4) * (1U << method_len * 8) - 1);
  2149. /* accept only GET or POST */
  2150. if ((n_method == N_HTTP_GET) ||
  2151. ((n_method == N_HTTP_POST) && (method_len == HTTP_POST_LEN))) {
  2152. if (msg->via1 == 0){
  2153. /* create a fake sip message */
  2154. fake_msg = http_xmlrpc2sip(msg, &fake_msg_len);
  2155. if (fake_msg == 0) {
  2156. ERR("xmlrpc: out of memory\n");
  2157. ret=NONSIP_MSG_ERROR;
  2158. } else {
  2159. /* send it */
  2160. DBG("new fake xml msg created (%d bytes):\n<%.*s>\n",
  2161. fake_msg_len, fake_msg_len, fake_msg);
  2162. if (em_receive_request(msg, fake_msg, fake_msg_len)<0)
  2163. ret=NONSIP_MSG_ERROR;
  2164. mxr_free(fake_msg);
  2165. }
  2166. return ret; /* we "ate" the message, stop processing */
  2167. } else { /* the message has a via */
  2168. DBG("http xml msg unchanged (%d bytes):\n<%.*s>\n",
  2169. msg->len, msg->len, msg->buf);
  2170. if (em_receive_request(msg, 0, 0)<0)
  2171. ret=NONSIP_MSG_ERROR;
  2172. return ret;
  2173. }
  2174. } else {
  2175. ERR("xmlrpc: bad HTTP request method: \"%.*s\"\n",
  2176. msg->first_line.u.request.method.len,
  2177. msg->first_line.u.request.method.s);
  2178. /* the message was for us, but it is an error */
  2179. return NONSIP_MSG_ERROR;
  2180. }
  2181. return NONSIP_MSG_PASS; /* message not for us, maybe somebody
  2182. else needs it */
  2183. }
  2184. /** The main processing function of xmlrpc module.
  2185. *
  2186. * This is the main function of this module. It extracts the name
  2187. * of the method to be called from XML-RPC request and then it
  2188. * searches through the list of all available management function,
  2189. * when a function with matching name is found then it will be
  2190. * executed.
  2191. */
  2192. static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2)
  2193. {
  2194. rpc_export_t* exp;
  2195. int ret = 1;
  2196. if (init_context(&ctx, msg) < 0) goto skip;
  2197. exp = find_rpc_export(ctx.method, 0);
  2198. if (!exp || !exp->function) {
  2199. rpc_fault(&ctx, 500, "Method Not Found");
  2200. goto skip;
  2201. }
  2202. ctx.flags = exp->flags;
  2203. if (exp->flags & RET_ARRAY &&
  2204. add_xmlrpc_reply(&ctx.reply, &array_prefix) < 0) goto skip;
  2205. exp->function(&func_param, &ctx);
  2206. skip:
  2207. /* The function may have sent the reply itself */
  2208. if (!ctx.reply_sent && !(ctx.flags&XMLRPC_DELAYED_REPLY_F)) {
  2209. ret = rpc_send(&ctx);
  2210. }
  2211. clean_context(&ctx);
  2212. collect_garbage();
  2213. if (ret < 0) return -1;
  2214. else return 1;
  2215. }
  2216. /** This function can be called from SER scripts to generate
  2217. * an XML-RPC reply.
  2218. */
  2219. static int xmlrpc_reply(sip_msg_t* msg, char* p1, char* p2)
  2220. {
  2221. str reason;
  2222. static str succ = STR_STATIC_INIT("1");
  2223. struct xmlrpc_reply reply;
  2224. memset(&reply, 0, sizeof(struct xmlrpc_reply));
  2225. if (init_xmlrpc_reply(&reply) < 0) return -1;
  2226. if (get_int_fparam(&reply.code, msg, (fparam_t*)p1) < 0) return -1;
  2227. if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) return -1;
  2228. reply.reason = as_asciiz(&reason);
  2229. if (reply.reason == NULL) {
  2230. ERR("No memory left\n");
  2231. return -1;
  2232. }
  2233. if (reply.code >= 300) {
  2234. if (build_fault_reply(&reply) < 0) goto error;
  2235. } else {
  2236. if (add_xmlrpc_reply(&reply, &success_prefix) < 0) goto error;
  2237. if (add_xmlrpc_reply(&reply, &int_prefix) < 0) goto error;
  2238. if (add_xmlrpc_reply_esc(&reply, &succ) < 0) goto error;
  2239. if (add_xmlrpc_reply(&reply, &int_suffix) < 0) goto error;
  2240. if (add_xmlrpc_reply(&reply, &success_suffix) < 0) return -1;
  2241. }
  2242. if (send_reply(msg, &reply.body) < 0) goto error;
  2243. if (reply.reason) pkg_free(reply.reason);
  2244. clean_xmlrpc_reply(&reply);
  2245. return 1;
  2246. error:
  2247. if (reply.reason) pkg_free(reply.reason);
  2248. clean_xmlrpc_reply(&reply);
  2249. return -1;
  2250. }
  2251. /** Implementation of \@xmlrpc.method select that can be used in
  2252. * SER scripts to retrieve the method string from XML-RPC documents
  2253. */
  2254. static int select_method(str* res, struct select* s, sip_msg_t* msg)
  2255. {
  2256. static char buf[1024];
  2257. str doc = {NULL,0};
  2258. xmlDocPtr xmldoc;
  2259. xmlNodePtr cur;
  2260. char* method;
  2261. xmldoc = 0;
  2262. method = 0;
  2263. if (get_rpc_document(&doc, msg) < 0) goto err;
  2264. xmldoc = xmlReadMemory(doc.s, doc.len, 0, 0,
  2265. XML_PARSE_NOBLANKS |
  2266. XML_PARSE_NONET |
  2267. XML_PARSE_NOCDATA);
  2268. if (!xmldoc) goto err;
  2269. cur = xmlDocGetRootElement(xmldoc);
  2270. if (!cur) goto err;
  2271. if (xmlStrcmp(cur->name, (const xmlChar*)"methodCall")) goto err;
  2272. cur = cur->xmlChildrenNode;
  2273. while(cur) {
  2274. if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
  2275. method = (char*)xmlNodeListGetString(xmldoc, cur->xmlChildrenNode,
  2276. 1);
  2277. if (!method) goto err;
  2278. break;
  2279. }
  2280. cur = cur->next;
  2281. }
  2282. if (!cur) goto err;
  2283. res->len = strlen(method);
  2284. if (res->len >= 1024) goto err;
  2285. memcpy(buf, method, res->len);
  2286. res->s = buf;
  2287. return 0;
  2288. err:
  2289. if (method) xmlFree(method);
  2290. if (xmldoc) xmlFreeDoc(xmldoc);
  2291. return -1;
  2292. }
  2293. static ABSTRACT_F(select_xmlrpc);
  2294. select_row_t xmlrpc_sel[] = {
  2295. { NULL, SEL_PARAM_STR, STR_STATIC_INIT("xmlrpc"), select_xmlrpc, SEL_PARAM_EXPECTED},
  2296. { select_xmlrpc, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_method, 0},
  2297. { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
  2298. };
  2299. static int mod_init(void)
  2300. {
  2301. struct nonsip_hook nsh;
  2302. int route_no;
  2303. /* try to fix the xmlrpc route */
  2304. if (xmlrpc_route){
  2305. route_no=route_get(&main_rt, xmlrpc_route);
  2306. if (route_no==-1){
  2307. ERR("xmlrpc: failed to fix route \"%s\": route_get() failed\n",
  2308. xmlrpc_route);
  2309. return -1;
  2310. }
  2311. if (main_rt.rlist[route_no]==0){
  2312. WARN("xmlrpc: xmlrpc route \"%s\" is empty / doesn't exist\n",
  2313. xmlrpc_route);
  2314. }
  2315. xmlrpc_route_no=route_no;
  2316. }
  2317. /* bind the SL API */
  2318. if (sl_load_api(&slb)!=0) {
  2319. LM_ERR("cannot bind to SL API\n");
  2320. return -1;
  2321. }
  2322. memset(&func_param, 0, sizeof(func_param));
  2323. func_param.send = (rpc_send_f)rpc_send;
  2324. func_param.fault = (rpc_fault_f)rpc_fault;
  2325. func_param.add = (rpc_add_f)rpc_add;
  2326. func_param.scan = (rpc_scan_f)rpc_scan;
  2327. func_param.rpl_printf = (rpc_rpl_printf_f)rpc_rpl_printf;
  2328. func_param.struct_add = (rpc_struct_add_f)rpc_struct_add;
  2329. func_param.array_add = (rpc_array_add_f)rpc_array_add;
  2330. func_param.struct_scan = (rpc_struct_scan_f)rpc_struct_scan;
  2331. func_param.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
  2332. func_param.capabilities = (rpc_capabilities_f)rpc_capabilities;
  2333. func_param.delayed_ctx_new = (rpc_delayed_ctx_new_f)rpc_delayed_ctx_new;
  2334. func_param.delayed_ctx_close =
  2335. (rpc_delayed_ctx_close_f)rpc_delayed_ctx_close;
  2336. register_select_table(xmlrpc_sel);
  2337. /* register non-sip hooks */
  2338. if(xmlrpc_mode==0)
  2339. {
  2340. memset(&nsh, 0, sizeof(nsh));
  2341. nsh.name="xmlrpc";
  2342. nsh.destroy=0;
  2343. nsh.on_nonsip_req=process_xmlrpc;
  2344. if (register_nonsip_msg_hook(&nsh)<0){
  2345. ERR("Failed to register non sip msg hooks\n");
  2346. return -1;
  2347. }
  2348. }
  2349. if(xmlrpc_url_match!=NULL)
  2350. {
  2351. memset(&xmlrpc_url_match_regexp, 0, sizeof(regex_t));
  2352. if (regcomp(&xmlrpc_url_match_regexp, xmlrpc_url_match, REG_EXTENDED)!=0) {
  2353. LM_ERR("bad match re %s\n", xmlrpc_url_match);
  2354. return E_BAD_RE;
  2355. }
  2356. }
  2357. if(xmlrpc_url_skip!=NULL)
  2358. {
  2359. memset(&xmlrpc_url_skip_regexp, 0, sizeof(regex_t));
  2360. if (regcomp(&xmlrpc_url_skip_regexp, xmlrpc_url_skip, REG_EXTENDED)!=0) {
  2361. LM_ERR("bad skip re %s\n", xmlrpc_url_skip);
  2362. return E_BAD_RE;
  2363. }
  2364. }
  2365. return 0;
  2366. }
  2367. /**
  2368. * advertise that sip workers handle rpc commands
  2369. */
  2370. int mod_register(char *path, int *dlflags, void *p1, void *p2)
  2371. {
  2372. set_child_sip_rpc_mode();
  2373. return 0;
  2374. }
  2375. static int fixup_xmlrpc_reply(void** param, int param_no)
  2376. {
  2377. int ret;
  2378. if (param_no == 1) {
  2379. ret = fix_param(FPARAM_AVP, param);
  2380. if (ret <= 0) return ret;
  2381. if (fix_param(FPARAM_INT, param) != 0) return -1;
  2382. } else if (param_no == 2) {
  2383. return fixup_var_str_12(param, 2);
  2384. }
  2385. return 0;
  2386. }
  2387. /** @} */