You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_config.c 115KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "lua_common.h"
  17. #include "libmime/message.h"
  18. #include "libutil/expression.h"
  19. #include "src/libserver/composites/composites.h"
  20. #include "libserver/cfg_file_private.h"
  21. #include "libmime/lang_detection.h"
  22. #include "lua/lua_map.h"
  23. #include "lua/lua_thread_pool.h"
  24. #include "utlist.h"
  25. #include <math.h>
  26. /***
  27. * This module is used to configure rspamd and is normally available as global
  28. * variable named `rspamd_config`. Unlike other modules, it is not necessary to
  29. * require it before usage.
  30. * @module rspamd_config
  31. * @example
  32. -- Register some callback symbol
  33. local function foo(task)
  34. -- do something
  35. end
  36. rspamd_config:register_symbol('SYMBOL', 1.0, foo)
  37. -- Get configuration
  38. local tab = rspamd_config:get_all_opt('module') -- get table for module's options
  39. local opts = rspamd_config:get_key('options') -- get content of the specified key in rspamd configuration
  40. */
  41. /* Config file methods */
  42. /***
  43. * @method rspamd_config:get_module_opt(mname, optname)
  44. * Returns value of specified option `optname` for a module `mname`,
  45. * @param {string} mname name of module
  46. * @param {string} optname option to get
  47. * @return {string or table} value of the option or `nil` if option is not found
  48. */
  49. LUA_FUNCTION_DEF (config, get_module_opt);
  50. /***
  51. * @method rspamd_config:get_all_opt(mname)
  52. * Returns value of all options for a module `mname`, flattening values into a single table consisting
  53. * of all sections with such a name.
  54. * @param {string} mname name of module
  55. * @return {table} table of all options for `mname` or `nil` if a module's configuration is not found
  56. */
  57. LUA_FUNCTION_DEF (config, get_all_opt);
  58. /***
  59. * @method rspamd_config:get_ucl()
  60. * Returns full configuration as a native Lua object (ucl to lua conversion).
  61. * This method uses caching if possible.
  62. * @return {table} table of all options in the configuration
  63. */
  64. LUA_FUNCTION_DEF (config, get_ucl);
  65. /***
  66. * @method rspamd_config:get_mempool()
  67. * Returns static configuration memory pool.
  68. * @return {mempool} [memory pool](mempool.md) object
  69. */
  70. LUA_FUNCTION_DEF (config, get_mempool);
  71. /***
  72. * @method rspamd_config:get_resolver()
  73. * Returns DNS resolver.
  74. * @return {dns_resolver} opaque DNS resolver pointer if any
  75. */
  76. LUA_FUNCTION_DEF (config, get_resolver);
  77. /***
  78. * @method rspamd_config:add_radix_map(mapline[, description])
  79. * Creates new dynamic map of IP/mask addresses.
  80. * @param {string} mapline URL for a map
  81. * @param {string} description optional map description
  82. * @return {map} radix tree object
  83. * @example
  84. local ip_map = rspamd_config:add_radix_map ('file:///path/to/file', 'my radix map')
  85. ...
  86. local function foo(task)
  87. local ip = task:get_from_ip()
  88. if ip_map:get_key(ip) then
  89. return true
  90. end
  91. return false
  92. end
  93. */
  94. /***
  95. * @method rspamd_config:radix_from_config(mname, optname)
  96. * Creates new embedded map of IP/mask addresses from config.
  97. * @param {string} mname name of module
  98. * @param {string} optname option to get
  99. * @return {map} radix tree object
  100. * @example
  101. local ip_map = rspamd_config:radix_from_config ('mymodule', 'ips')
  102. ...
  103. local function foo(task)
  104. local ip = task:get_from_ip()
  105. if ip_map:get_key(ip) then
  106. return true
  107. end
  108. return false
  109. end
  110. */
  111. /***
  112. * @method rspamd_config:radix_from_ucl(obj)
  113. * Creates new embedded map of IP/mask addresses from object.
  114. * @param {ucl} obj object
  115. * @return {map} radix tree object
  116. */
  117. /***
  118. * @method rspamd_config:add_hash_map(mapline[, description])
  119. * Creates new dynamic map string objects.
  120. * @param {string} mapline URL for a map
  121. * @param {string} description optional map description
  122. * @return {map} hash set object
  123. * @example
  124. local hash_map = rspamd_config:add_hash_map ('file:///path/to/file', 'my hash map')
  125. ...
  126. local function foo(task)
  127. local from = task:get_from()
  128. if hash_map:get_key(from['user']) then
  129. return true
  130. end
  131. return false
  132. end
  133. */
  134. /***
  135. * @method rspamd_config:add_kv_map(mapline[, description])
  136. * Creates new dynamic map of key/values associations.
  137. * @param {string} mapline URL for a map
  138. * @param {string} description optional map description
  139. * @return {map} hash table object
  140. * @example
  141. local kv_map = rspamd_config:add_kv_map ('file:///path/to/file', 'my kv map')
  142. ...
  143. local function foo(task)
  144. local from = task:get_from()
  145. if from then
  146. local value = kv_map:get_key(from['user'])
  147. if value then
  148. return true,value
  149. end
  150. end
  151. return false
  152. end
  153. */
  154. /***
  155. * @method rspamd_config:add_map({args})
  156. * Creates new dynamic map according to the attributes passed.
  157. *
  158. * - `type`: type of map to be created, can be one of the following set:
  159. * + `set`: set of strings
  160. * + `radix`: map of IP addresses to strings
  161. * + `map`: map of strings to strings
  162. * + `regexp`: map of regexps to strings
  163. * + `callback`: map processed by lua callback
  164. * - `url`: url to load map from
  165. * - `description`: map's description
  166. * - `callback`: lua callback for the map
  167. *
  168. * @return {map} `true` if map has been added
  169. * @example
  170. local str = ''
  171. local function process_map(in)
  172. str = in
  173. end
  174. rspamd_config:add_map('http://example.com/map', "settings map", process_map)
  175. */
  176. /***
  177. * @method rspamd_config:get_maps()
  178. * Get all maps defined as an array of rspamd{map} objects
  179. *
  180. * @return {table|rspamd{map}}
  181. */
  182. /***
  183. * @method rspamd_config:get_classifier(name)
  184. * Returns classifier config.
  185. * @param {string} name name of classifier (e.g. `bayes`)
  186. * @return {classifier} classifier object or `nil`
  187. */
  188. LUA_FUNCTION_DEF (config, get_classifier);
  189. /***
  190. * @method rspamd_config:register_symbol(table)
  191. * Register symbol of a specified type in rspamd. This function accepts table of arguments:
  192. *
  193. * - `name`: name of symbol (can be missing for callback symbols)
  194. * - `callback`: function to be called for symbol's check (can be absent for virtual symbols)
  195. * - `weight`: weight of symbol (should normally be 1 or missing)
  196. * - `priority`: priority of symbol (normally 0 or missing)
  197. * - `type`: type of symbol:
  198. * + `normal`: executed after prefilters, according to dependency graph or in undefined order
  199. * + `callback`: a check that merely inserts virtual symbols
  200. * + `connfilter`: executed early; before message body is available
  201. * + `idempotent`: cannot change result in any way; executed last
  202. * + `postfilter`: executed after most other checks
  203. * + `prefilter`: executed before most other checks
  204. * + `virtual`: a symbol inserted by its parent check
  205. * - `flags`: various flags split by commas or spaces:
  206. * + `nice` if symbol can produce negative score;
  207. * + `empty` if symbol can be called for empty messages
  208. * + `skip` if symbol should be skipped now
  209. * + `nostat` if symbol should be excluded from stat tokens
  210. * + `trivial` symbol is trivial (e.g. no network requests)
  211. * + `explicit_disable` requires explicit disabling (e.g. via settings)
  212. * + `ignore_passthrough` executed even if passthrough result has been set
  213. * - `parent`: id of parent symbol (useful for virtual symbols)
  214. *
  215. * @return {number} id of symbol registered
  216. */
  217. LUA_FUNCTION_DEF (config, register_symbol);
  218. /***
  219. * @method rspamd_config:register_symbols(callback, [weight], callback_name, [, symbol, ...])
  220. * Register callback function to be called for a set of symbols with initial weight.
  221. * @param {function} callback callback function to be called for a specified symbol
  222. * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
  223. * @param {string} callback_name symbolic name of callback
  224. * @param {list of strings} symbol list of symbols registered by this function
  225. */
  226. LUA_FUNCTION_DEF (config, register_symbols);
  227. /***
  228. * @method rspamd_config:register_virtual_symbol(name, weight,)
  229. * Register virtual symbol that is not associated with any callback.
  230. *
  231. * **This method is deprecated and should not be used in newly written code **
  232. * @param {string} virtual name symbol's name
  233. * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
  234. */
  235. LUA_FUNCTION_DEF (config, register_virtual_symbol);
  236. /***
  237. * @method rspamd_config:register_callback_symbol(name, weight, callback)
  238. * Register callback function to be called for a specified symbol with initial weight. Symbol itself is
  239. * not registered in the metric and is not intended to be visible by a user.
  240. *
  241. * **This method is deprecated and should not be used in newly written code **
  242. * @param {string} name symbol's name (just for unique id purposes)
  243. * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
  244. * @param {function} callback callback function to be called for a specified symbol
  245. */
  246. LUA_FUNCTION_DEF (config, register_callback_symbol);
  247. LUA_FUNCTION_DEF (config, register_callback_symbol_priority);
  248. /***
  249. * @method rspamd_config:register_dependency(id|name, depname)
  250. * Create a dependency on symbol identified by name for symbol identified by ID or name.
  251. * This affects order of checks only (a symbol is still checked if its dependencys are disabled).
  252. * @param {number|string} id id or name of source (numeric id is returned by all register_*_symbol)
  253. * @param {string} depname dependency name
  254. * @example
  255. local function cb(task)
  256. ...
  257. end
  258. local id = rspamd_config:register_symbol('SYM', 1.0, cb)
  259. rspamd_config:register_dependency(id, 'OTHER_SYM')
  260. -- Alternative form
  261. -- Symbol MY_RULE needs result from SPF_CHECK
  262. rspamd_config:register_dependency('MY_RULE', 'SPF_CHECK')
  263. */
  264. LUA_FUNCTION_DEF (config, register_dependency);
  265. /***
  266. * @method rspamd_config:get_symbol_flags(name)
  267. * Returns symbol flags
  268. * @param {string} name symbols's name
  269. * @return {table|string} list of flags for symbol or nil
  270. */
  271. LUA_FUNCTION_DEF (config, get_symbol_flags);
  272. /***
  273. * @method rspamd_config:add_symbol_flags(name, flags)
  274. * Adds flags to a symbol
  275. * @param {string} name symbols's name
  276. * @param {table|string} flags flags to add
  277. * @return {table|string} new set of flags
  278. */
  279. LUA_FUNCTION_DEF (config, add_symbol_flags);
  280. /**
  281. * @method rspamd_config:register_re_selector(name, selector_str, [delimiter, [flatten]])
  282. * Registers selector with the specific name to use in regular expressions in form
  283. * name=/re/$ or name=/re/{selector}
  284. * @param {string} name name of the selector
  285. * @param {string} selector_str selector definition
  286. * @param {string} delimiter delimiter to use when joining strings if flatten is false
  287. * @param {bool} flatten if true then selector will return a table of captures instead of a single string
  288. * @return true if selector has been registered
  289. */
  290. LUA_FUNCTION_DEF (config, register_re_selector);
  291. /**
  292. * @method rspamd_config:set_symbol({table})
  293. * Sets the value of a specified symbol in a metric. This function accepts table with the following elements:
  294. *
  295. * - `name`: name of symbol (string)
  296. * - `score`: score for symbol (number)
  297. * - `metric`: name of metric (string, optional)
  298. * - `description`: description of symbol (string, optional)
  299. * - `group`: name of group for symbol (string, optional)
  300. * - `one_shot`: turn off multiple hits for a symbol (boolean, optional)
  301. * - `one_param`: turn off multiple options for a symbol (boolean, optional)
  302. * - `flags`: comma separated string of flags:
  303. * + `ignore`: do not strictly check validity of symbol and corresponding rule
  304. * + `one_shot`: turn off multiple hits for a symbol
  305. * + `one_param`: allow only one parameter for a symbol
  306. * - `priority`: priority of symbol's definition
  307. */
  308. LUA_FUNCTION_DEF (config, set_metric_symbol);
  309. /**
  310. * @method rspamd_config:set_action({table})
  311. * Sets the score of a specified action in a metric. This function accepts table with the following elements:
  312. *
  313. * - `action`: name of action (string)
  314. * - `score`: score for action (number)
  315. * - `metric`: name of metric (string, optional)
  316. * - `priority`: priority of action's definition
  317. */
  318. LUA_FUNCTION_DEF (config, set_metric_action);
  319. /**
  320. * @method rspamd_config:get_symbol(name)
  321. * Gets metric data for a specific symbol identified by `name`:
  322. *
  323. * - `score`: score for symbol (number)
  324. * - `description`: description of symbol (string, optional)
  325. * - `group`: name of group for symbol (string, optional)
  326. * - `one_shot`: turn off multiple hits for a symbol (boolean, optional)
  327. * - `flags`: comma separated string of flags:
  328. * + `ignore`: do not strictly check validity of symbol and corresponding rule
  329. * + `one_shot`: turn off multiple hits for a symbol
  330. *
  331. * @param {string} name name of symbol
  332. * @return {table} symbol's definition or nil in case of undefined symbol
  333. */
  334. LUA_FUNCTION_DEF (config, get_metric_symbol);
  335. /**
  336. * @method rspamd_config:get_action(name)
  337. * Gets data for a specific action in config. This function returns number reperesenting action's score
  338. *
  339. * @param {string} name name of action
  340. * @return {number} action's score or nil in case of undefined score or action
  341. */
  342. LUA_FUNCTION_DEF (config, get_metric_action);
  343. /**
  344. * @method rspamd_config:get_all_actions()
  345. * Gets data for all action in config
  346. * @return {table|str->num} action's score or nil in case of undefined score or action
  347. */
  348. LUA_FUNCTION_DEF (config, get_all_actions);
  349. /**
  350. * @method rspamd_config:add_composite(name, expression)
  351. * @param {string} name name of composite symbol
  352. * @param {string} expression symbolic expression of the composite rule
  353. * @return {bool} true if a composite has been added successfully
  354. */
  355. LUA_FUNCTION_DEF (config, add_composite);
  356. /***
  357. * @method rspamd_config:register_pre_filter(callback[, order])
  358. * Register function to be called prior to symbols processing.
  359. * @param {function} callback callback function
  360. * @param {number} order filters are called from lower orders to higher orders, order is equal to 0 by default
  361. * @example
  362. local function check_function(task)
  363. -- It is possible to manipulate the task object here: set settings, set pre-action and so on
  364. ...
  365. end
  366. rspamd_config:register_pre_filter(check_function)
  367. */
  368. LUA_FUNCTION_DEF (config, register_pre_filter);
  369. /***
  370. * @method rspamd_config:register_post_filter(callback[, order])
  371. * Register function to be called after symbols are processed.
  372. *
  373. * @param {function} callback callback function
  374. * @param {number} order filters are called from lower orders to higher orders, order is equal to 0 by default
  375. */
  376. LUA_FUNCTION_DEF (config, register_post_filter);
  377. /* XXX: obsoleted */
  378. LUA_FUNCTION_DEF (config, register_module_option);
  379. /* XXX: not needed now */
  380. LUA_FUNCTION_DEF (config, get_api_version);
  381. /***
  382. * @method rspamd_config:get_key(name)
  383. * Returns configuration section with the specified `name`.
  384. * @param {string} name name of config section
  385. * @return {variant} specific value of section
  386. * @example
  387. local set_section = rspamd_config:get_key("settings")
  388. if type(set_section) == "string" then
  389. -- Just a map of ucl
  390. if rspamd_config:add_map(set_section, "settings map", process_settings_map) then
  391. rspamd_config:register_pre_filter(check_settings)
  392. end
  393. elseif type(set_section) == "table" then
  394. if process_settings_table(set_section) then
  395. rspamd_config:register_pre_filter(check_settings)
  396. end
  397. end
  398. */
  399. LUA_FUNCTION_DEF (config, get_key);
  400. /***
  401. * @method rspamd_config:add_condition(symbol, condition)
  402. * Adds condition callback for specified symbol
  403. * @param {string} symbol symbol's name
  404. * @param {function} condition condition callback
  405. * @return {boolean} true if condition has been added
  406. * @example
  407. rspamd_config:add_condition('FUZZY_DENIED', function(task)
  408. if some_map:find_key(task:get_from()) then return false end
  409. return true
  410. end)
  411. */
  412. LUA_FUNCTION_DEF (config, add_condition);
  413. /***
  414. * @method rspamd_config:enable_symbol(symbol)
  415. * Enables execution for the specified symbol
  416. * @param {string} symbol symbol's name
  417. */
  418. LUA_FUNCTION_DEF (config, enable_symbol);
  419. /***
  420. * @method rspamd_config:disable_symbol(symbol, [disable_parent=true])
  421. * Disables execution for the specified symbol
  422. * @param {string} symbol symbol's name
  423. * @param {boolean} disable_parent if true then disable parent execution in case of a virtual symbol
  424. */
  425. LUA_FUNCTION_DEF (config, disable_symbol);
  426. /***
  427. * @method rspamd_config:get_symbol_parent(symbol)
  428. * Returns a parent symbol for specific symbol (or symbol itself if top level)
  429. * @param {string} symbol symbol's name
  430. */
  431. LUA_FUNCTION_DEF (config, get_symbol_parent);
  432. /***
  433. * @method rspamd_config:get_group_symbols(group)
  434. * Returns list of symbols for a specific group
  435. * @param {string} group group's name
  436. * @available 2.0+
  437. * @return {list|string} list of all symbols in a specific group
  438. */
  439. LUA_FUNCTION_DEF (config, get_group_symbols);
  440. /***
  441. * @method rspamd_config:get_groups([need_private])
  442. * Returns list of all groups defined
  443. * @param {boolean} need_private optional flag to include private groups
  444. * @available 2.3+
  445. * @return {list|table} list of all groups
  446. */
  447. LUA_FUNCTION_DEF (config, get_groups);
  448. /***
  449. * @method rspamd_config:register_settings_id(name, symbols_enabled, symbols_disabled)
  450. * Register new static settings id in config
  451. * @param {string} name id name (not numeric!)
  452. * @param {map|string->string} symbols_enabled map from symbol's name to boolean (currently)
  453. * @param {map|string->string} symbols_disabled map from symbol's name to boolean (currently)
  454. * @available 2.0+
  455. */
  456. LUA_FUNCTION_DEF (config, register_settings_id);
  457. /***
  458. * @method rspamd_config:__newindex(name, callback)
  459. * This metamethod is called if new indicies are added to the `rspamd_config` object.
  460. * Technically, it is the equivalent of @see rspamd_config:register_symbol where `weight` is 1.0.
  461. * There is also table form invocation that allows to control more things:
  462. *
  463. * - `callback`: has the same meaning and acts as function of task
  464. * - `score`: default score for a symbol
  465. * - `group`: default group for a symbol
  466. * - `description`: default symbol's description
  467. * - `priority`: additional priority value
  468. * - `one_shot`: default value for one shot attribute
  469. * - `condition`: function of task that can enable or disable this specific rule's execution
  470. * @param {string} name index name
  471. * @param {function/table} callback callback to be called
  472. * @return {number} id of the new symbol added
  473. * @example
  474. rspamd_config.R_EMPTY_IMAGE = function (task)
  475. parts = task:get_text_parts()
  476. if parts then
  477. for _,part in ipairs(parts) do
  478. if part:is_empty() then
  479. images = task:get_images()
  480. if images then
  481. -- Symbol `R_EMPTY_IMAGE` is inserted
  482. return true
  483. end
  484. return false
  485. end
  486. end
  487. end
  488. return false
  489. end
  490. rspamd_config.SYMBOL = {
  491. callback = function(task)
  492. ...
  493. end,
  494. score = 5.1,
  495. description = 'sample symbol',
  496. group = 'sample symbols',
  497. condition = function(task)
  498. if task:get_from()[1]['addr'] == 'user@example.com' then
  499. return false
  500. end
  501. return true
  502. end
  503. }
  504. */
  505. LUA_FUNCTION_DEF (config, newindex);
  506. /***
  507. * @method rspamd_config:register_regexp(params)
  508. * Registers new re for further cached usage
  509. * Params is the table with the following fields (mandatory fields are marked with `*`):
  510. * - `re`* : regular expression object
  511. * - `type`*: type of regular expression:
  512. * + `mime`: mime regexp
  513. * + `rawmime`: raw mime regexp
  514. * + `header`: header regexp
  515. * + `rawheader`: raw header expression
  516. * + `body`: raw body regexp
  517. * + `url`: url regexp
  518. * - `header`: for header and rawheader regexp means the name of header
  519. * - `pcre_only`: flag regexp as pcre only regexp
  520. */
  521. LUA_FUNCTION_DEF (config, register_regexp);
  522. /***
  523. * @method rspamd_config:replace_regexp(params)
  524. * Replaces regexp with a new one
  525. * Params is the table with the following fields (mandatory fields are marked with `*`):
  526. * - `old_re`* : old regular expression object (must be in the cache)
  527. * - `new_re`* : old regular expression object (must not be in the cache)
  528. */
  529. LUA_FUNCTION_DEF (config, replace_regexp);
  530. /***
  531. * @method rspamd_config:register_worker_script(worker_type, script)
  532. * Registers the following script for workers of a specified type. The exact type
  533. * of script function depends on worker type
  534. * @param {string} worker_type worker type (e.g. "normal")
  535. * @param {function} script script for a worker
  536. * @return {boolean} `true` if a script has been registered
  537. */
  538. LUA_FUNCTION_DEF (config, register_worker_script);
  539. /***
  540. * @method rspamd_config:add_on_load(function(cfg, ev_base, worker) ... end)
  541. * Registers the following script to be executed when configuration is completely loaded
  542. * and the worker is already started (forked)
  543. * @param {function} script function to be executed
  544. * @example
  545. rspamd_config:add_on_load(function(cfg, ev_base, worker)
  546. rspamd_config:add_periodic(ev_base, 1.0, function(cfg, ev_base)
  547. local logger = require "rspamd_logger"
  548. logger.infox(cfg, "periodic function in worker %s", worker:get_name())
  549. return true
  550. end)
  551. end)
  552. */
  553. LUA_FUNCTION_DEF (config, add_on_load);
  554. /***
  555. * @method rspamd_config:add_periodic(event_base, timeout, function(cfg, ev_base) ... end, [jitter = false])
  556. * Registers function to be periodically executed by Rspamd
  557. * @param {ev_base} event_base event base that is needed for async events
  558. * @param {number} timeout time in seconds (could be fractional)
  559. * @param {function} script function to be executed
  560. * @param {boolean} jitter `true` if timeout jittering is needed
  561. * @example
  562. rspamd_config:add_on_load(function(cfg, ev_base)
  563. rspamd_config:add_periodic(ev_base, 1.0, function(cfg, ev_base)
  564. local logger = require "rspamd_logger"
  565. logger.infox(cfg, "periodic function")
  566. return true -- if return numeric, a new interval is set. if return false, then the periodic event is removed
  567. end)
  568. end)
  569. */
  570. LUA_FUNCTION_DEF (config, add_periodic);
  571. /***
  572. * @method rspamd_config:add_post_init(function(cfg) ... end)
  573. * Registers the following script to be executed when configuration is completely loaded
  574. * @available 2.0+
  575. * @param {function} script function to be executed
  576. */
  577. LUA_FUNCTION_DEF (config, add_post_init);
  578. /***
  579. * @method rspamd_config:add_config_unload(function(cfg) ... end)
  580. * Registers the following script to be executed when configuration is unloaded
  581. * @available 2.0+
  582. * @param {function} script function to be executed
  583. */
  584. LUA_FUNCTION_DEF (config, add_config_unload);
  585. /***
  586. * @method rspamd_config:get_symbols_count()
  587. * Returns number of symbols registered in rspamd configuration
  588. * @return {number} number of symbols registered in the configuration
  589. */
  590. LUA_FUNCTION_DEF (config, get_symbols_count);
  591. /***
  592. * @method rspamd_config:get_symbols_cksum()
  593. * Returns checksum for all symbols in the cache
  594. * @return {int64} boxed value of the 64 bit checksum
  595. */
  596. LUA_FUNCTION_DEF (config, get_symbols_cksum);
  597. /***
  598. * @method rspamd_config:get_symbols_counters()
  599. * Returns table of all counters in the cache (weights, frequencies etc)
  600. * @return {table|tables} all symbols indexed by name
  601. */
  602. LUA_FUNCTION_DEF (config, get_symbols_counters);
  603. /***
  604. * @method rspamd_config:get_symbols()
  605. * Returns table of all scores defined in config. From version 2.0 returns table:
  606. * - name
  607. * - score
  608. * - flags (e.g. `ignore` or `oneparam`)
  609. * - nshots (== maxhits)
  610. * - group - main group
  611. * - groups - array of all groups
  612. * @available 2.0+
  613. * @return {table|tables} all symbols indexed by name
  614. */
  615. LUA_FUNCTION_DEF (config, get_symbols);
  616. /***
  617. * @method rspamd_config:get_symbol_callback(name)
  618. * Returns callback function for the specified symbol if it is a lua registered callback
  619. * @return {function} callback function or nil
  620. */
  621. LUA_FUNCTION_DEF (config, get_symbol_callback);
  622. /***
  623. * @method rspamd_config:get_symbol_stat(name)
  624. * Returns table with statistics for a specific symbol:
  625. * - `frequency`: frequency for symbol's hits
  626. * - `stddev`: standard deviation of `frequency`
  627. * - `time`: average time in seconds (floating point)
  628. * - `count`: total number of hits
  629. * @return {table} symbol stats
  630. */
  631. LUA_FUNCTION_DEF (config, get_symbol_stat);
  632. /***
  633. * @method rspamd_config:set_symbol_callback(name, callback)
  634. * Sets callback for the specified symbol
  635. * @return {boolean} true if function has been replaced
  636. */
  637. LUA_FUNCTION_DEF (config, set_symbol_callback);
  638. /***
  639. * @method rspamd_config:register_finish_script(callback)
  640. * Adds new callback that is called on worker process termination when all
  641. * tasks pending are processed
  642. *
  643. * @param callback {function} a function with one argument (rspamd_task)
  644. */
  645. LUA_FUNCTION_DEF (config, register_finish_script);
  646. /***
  647. * @method rspamd_config:register_monitored(url, type, [{params}])
  648. * Registers monitored resource to watch its availability. Supported types:
  649. *
  650. * - `dns`: DNS monitored object
  651. *
  652. * Params are optional table specific for each type. For DNS it supports the
  653. * following options:
  654. *
  655. * - `prefix`: prefix to add before making request
  656. * - `type`: type of request (e.g. 'a' or 'txt')
  657. * - `ipnet`: array of ip/networks to expect on reply
  658. * - `rcode`: expected return code (e.g. `nxdomain`)
  659. *
  660. * Returned object has the following methods:
  661. *
  662. * - `alive`: returns `true` if monitored resource is alive
  663. * - `offline`: returns number of seconds of the current offline period (or 0 if alive)
  664. * - `total_offline`: returns number of seconds of the overall offline
  665. * - `latency`: returns the current average latency in seconds (or 0 if offline)
  666. *
  667. * @param {string} url resource to monitor
  668. * @param {string} type type of monitoring
  669. * @param {table} opts optional parameters
  670. * @return {rspamd_monitored} rspamd monitored object
  671. */
  672. LUA_FUNCTION_DEF (config, register_monitored);
  673. /***
  674. * @method rspamd_config:add_doc(path, option, doc_string, [{params}])
  675. * Adds new documentation string for an option `option` at path `path`
  676. * Options defines optional params, such as:
  677. *
  678. * - `default`: default option value
  679. * - `type`: type of an option (`string`, `number`, `object`, `array` etc)
  680. * - `reqired`: if an option is required
  681. *
  682. * @param {string} path documentation path (e.g. module name)
  683. * @param {string} option name of the option
  684. * @param {string} doc_string documentation string
  685. * @param {table} params optional parameters
  686. */
  687. LUA_FUNCTION_DEF (config, add_doc);
  688. /***
  689. * @method rspamd_config:add_example(path, option, doc_string, example)
  690. * Adds new documentation
  691. *
  692. * @param {string} path documentation path (e.g. module name or nil for top)
  693. * @param {string} option name of the option
  694. * @param {string} doc_string documentation string
  695. * @param {string} example example in ucl format, comments are also parsed
  696. */
  697. LUA_FUNCTION_DEF (config, add_example);
  698. /***
  699. * @method rspamd_config:set_peak_cb(function)
  700. * Sets a function that will be called when frequency of some symbol goes out of
  701. * stddev * 2 over the last period of refreshment.
  702. *
  703. * @example
  704. rspamd_config:set_peak_cb(function(ev_base, sym, mean, stddev, value, error)
  705. -- ev_base: event base for async events (e.g. redis)
  706. -- sym: symbol's name
  707. -- mean: mean frequency value
  708. -- stddev: standard deviation of frequency
  709. -- value: current frequency value
  710. -- error: squared error
  711. local logger = require "rspamd_logger"
  712. logger.infox(rspamd_config, "symbol %s has changed frequency significantly: %s(%s) over %s(%s)",
  713. sym, value, error, mean, stddev)
  714. end)
  715. */
  716. LUA_FUNCTION_DEF (config, set_peak_cb);
  717. /***
  718. * @method rspamd_config:get_cpu_flags()
  719. * Returns architecture dependent flags supported by the CPU
  720. * Currently, only x86 flags are supported:
  721. * - 'ssse3'
  722. * - 'sse42'
  723. * - 'avx'
  724. * - 'avx2'
  725. * @return {table} flag -> true table
  726. */
  727. LUA_FUNCTION_DEF (config, get_cpu_flags);
  728. /***
  729. * @method rspamd_config:has_torch()
  730. * Returns true if Rspamd is compiled with torch support and the runtime CPU
  731. * supports sse4.2 required for torch.
  732. * @return {boolean} true if torch is compiled and supported
  733. */
  734. LUA_FUNCTION_DEF (config, has_torch);
  735. /***
  736. * @method rspamd_config:experimental_enabled()
  737. * Returns true if experimental plugins are enabled
  738. * @return {boolean} true if experimental plugins are enabled
  739. */
  740. LUA_FUNCTION_DEF (config, experimental_enabled);
  741. /***
  742. * @method rspamd_config:load_ucl(filename[, include_trace])
  743. * Loads config from the UCL file (but does not perform parsing using rcl)
  744. * @param {string} filename file to load
  745. * @return true or false + error message
  746. */
  747. LUA_FUNCTION_DEF (config, load_ucl);
  748. /***
  749. * @method rspamd_config:parse_rcl([skip_sections])
  750. * Parses RCL using loaded ucl file
  751. * @param {table|string} sections to skip
  752. * @return true or false + error message
  753. */
  754. LUA_FUNCTION_DEF (config, parse_rcl);
  755. /***
  756. * @method rspamd_config:init_modules()
  757. * Initialize lua and internal modules
  758. * @return true or false
  759. */
  760. LUA_FUNCTION_DEF (config, init_modules);
  761. /***
  762. * @method rspamd_config:init_subsystem(str)
  763. * Initialize config subsystem from a comma separated list:
  764. * - `modules` - init modules
  765. * - `langdet` - language detector
  766. * - `dns` - DNS resolver
  767. * - TODO: add more
  768. */
  769. LUA_FUNCTION_DEF (config, init_subsystem);
  770. /***
  771. * @method rspamd_config:get_tld_path()
  772. * Returns path to TLD file
  773. * @return {string} path to tld file
  774. */
  775. LUA_FUNCTION_DEF (config, get_tld_path);
  776. /***
  777. * @method rspamd_config:get_dns_max_requests()
  778. * Returns limit of DNS requests per task
  779. * @return {number} number of dns requests allowed
  780. */
  781. LUA_FUNCTION_DEF (config, get_dns_max_requests);
  782. static const struct luaL_reg configlib_m[] = {
  783. LUA_INTERFACE_DEF (config, get_module_opt),
  784. LUA_INTERFACE_DEF (config, get_mempool),
  785. LUA_INTERFACE_DEF (config, get_resolver),
  786. LUA_INTERFACE_DEF (config, get_all_opt),
  787. LUA_INTERFACE_DEF (config, get_ucl),
  788. LUA_INTERFACE_DEF (config, add_radix_map),
  789. LUA_INTERFACE_DEF (config, radix_from_config),
  790. LUA_INTERFACE_DEF (config, radix_from_ucl),
  791. LUA_INTERFACE_DEF (config, add_hash_map),
  792. LUA_INTERFACE_DEF (config, add_kv_map),
  793. LUA_INTERFACE_DEF (config, add_map),
  794. LUA_INTERFACE_DEF (config, get_maps),
  795. LUA_INTERFACE_DEF (config, get_classifier),
  796. LUA_INTERFACE_DEF (config, register_symbol),
  797. LUA_INTERFACE_DEF (config, register_symbols),
  798. LUA_INTERFACE_DEF (config, register_virtual_symbol),
  799. LUA_INTERFACE_DEF (config, register_callback_symbol),
  800. LUA_INTERFACE_DEF (config, register_callback_symbol_priority),
  801. LUA_INTERFACE_DEF (config, register_dependency),
  802. LUA_INTERFACE_DEF (config, register_settings_id),
  803. LUA_INTERFACE_DEF (config, get_symbol_flags),
  804. LUA_INTERFACE_DEF (config, add_symbol_flags),
  805. LUA_INTERFACE_DEF (config, set_metric_symbol),
  806. {"set_symbol", lua_config_set_metric_symbol},
  807. LUA_INTERFACE_DEF (config, set_metric_action),
  808. {"set_action", lua_config_set_metric_action},
  809. LUA_INTERFACE_DEF (config, get_metric_symbol),
  810. {"get_symbol", lua_config_get_metric_symbol},
  811. LUA_INTERFACE_DEF (config, get_metric_action),
  812. {"get_action", lua_config_get_metric_action},
  813. LUA_INTERFACE_DEF (config, get_all_actions),
  814. LUA_INTERFACE_DEF (config, add_composite),
  815. LUA_INTERFACE_DEF (config, register_module_option),
  816. LUA_INTERFACE_DEF (config, register_pre_filter),
  817. LUA_INTERFACE_DEF (config, register_post_filter),
  818. LUA_INTERFACE_DEF (config, get_api_version),
  819. LUA_INTERFACE_DEF (config, get_key),
  820. LUA_INTERFACE_DEF (config, add_condition),
  821. LUA_INTERFACE_DEF (config, enable_symbol),
  822. LUA_INTERFACE_DEF (config, disable_symbol),
  823. LUA_INTERFACE_DEF (config, register_regexp),
  824. LUA_INTERFACE_DEF (config, replace_regexp),
  825. LUA_INTERFACE_DEF (config, register_worker_script),
  826. LUA_INTERFACE_DEF (config, register_re_selector),
  827. LUA_INTERFACE_DEF (config, add_on_load),
  828. LUA_INTERFACE_DEF (config, add_periodic),
  829. LUA_INTERFACE_DEF (config, add_post_init),
  830. LUA_INTERFACE_DEF (config, add_config_unload),
  831. LUA_INTERFACE_DEF (config, get_symbols_count),
  832. LUA_INTERFACE_DEF (config, get_symbols_cksum),
  833. LUA_INTERFACE_DEF (config, get_symbols_counters),
  834. {"get_symbols_scores", lua_config_get_symbols},
  835. LUA_INTERFACE_DEF (config, get_symbols),
  836. LUA_INTERFACE_DEF (config, get_groups),
  837. LUA_INTERFACE_DEF (config, get_symbol_callback),
  838. LUA_INTERFACE_DEF (config, set_symbol_callback),
  839. LUA_INTERFACE_DEF (config, get_symbol_stat),
  840. LUA_INTERFACE_DEF (config, get_symbol_parent),
  841. LUA_INTERFACE_DEF (config, get_group_symbols),
  842. LUA_INTERFACE_DEF (config, register_finish_script),
  843. LUA_INTERFACE_DEF (config, register_monitored),
  844. LUA_INTERFACE_DEF (config, add_doc),
  845. LUA_INTERFACE_DEF (config, add_example),
  846. LUA_INTERFACE_DEF (config, set_peak_cb),
  847. LUA_INTERFACE_DEF (config, get_cpu_flags),
  848. LUA_INTERFACE_DEF (config, has_torch),
  849. LUA_INTERFACE_DEF (config, experimental_enabled),
  850. LUA_INTERFACE_DEF (config, load_ucl),
  851. LUA_INTERFACE_DEF (config, parse_rcl),
  852. LUA_INTERFACE_DEF (config, init_modules),
  853. LUA_INTERFACE_DEF (config, init_subsystem),
  854. LUA_INTERFACE_DEF (config, get_tld_path),
  855. LUA_INTERFACE_DEF (config, get_dns_max_requests),
  856. {"__tostring", rspamd_lua_class_tostring},
  857. {"__newindex", lua_config_newindex},
  858. {NULL, NULL}
  859. };
  860. LUA_FUNCTION_DEF (monitored, alive);
  861. LUA_FUNCTION_DEF (monitored, latency);
  862. LUA_FUNCTION_DEF (monitored, offline);
  863. LUA_FUNCTION_DEF (monitored, total_offline);
  864. static const struct luaL_reg monitoredlib_m[] = {
  865. LUA_INTERFACE_DEF (monitored, alive),
  866. LUA_INTERFACE_DEF (monitored, latency),
  867. LUA_INTERFACE_DEF (monitored, offline),
  868. LUA_INTERFACE_DEF (monitored, total_offline),
  869. {"__tostring", rspamd_lua_class_tostring},
  870. {NULL, NULL}
  871. };
  872. static const guint64 rspamd_lua_callback_magic = 0x32c118af1e3263c7ULL;
  873. struct rspamd_config *
  874. lua_check_config (lua_State * L, gint pos)
  875. {
  876. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{config}");
  877. luaL_argcheck (L, ud != NULL, pos, "'config' expected");
  878. return ud ? *((struct rspamd_config **)ud) : NULL;
  879. }
  880. static struct rspamd_monitored *
  881. lua_check_monitored (lua_State * L, gint pos)
  882. {
  883. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{monitored}");
  884. luaL_argcheck (L, ud != NULL, pos, "'monitored' expected");
  885. return ud ? *((struct rspamd_monitored **)ud) : NULL;
  886. }
  887. /*** Config functions ***/
  888. static gint
  889. lua_config_get_api_version (lua_State *L)
  890. {
  891. msg_warn ("get_api_version is deprecated, do not use it");
  892. lua_pushnumber (L, 100);
  893. return 1;
  894. }
  895. static gint
  896. lua_config_get_module_opt (lua_State * L)
  897. {
  898. LUA_TRACE_POINT;
  899. struct rspamd_config *cfg = lua_check_config (L, 1);
  900. const gchar *mname, *optname;
  901. const ucl_object_t *obj;
  902. if (cfg) {
  903. mname = luaL_checkstring (L, 2);
  904. optname = luaL_checkstring (L, 3);
  905. if (mname && optname) {
  906. obj = rspamd_config_get_module_opt (cfg, mname, optname);
  907. if (obj) {
  908. return ucl_object_push_lua (L, obj, TRUE);
  909. }
  910. }
  911. }
  912. lua_pushnil (L);
  913. return 1;
  914. }
  915. static int
  916. lua_config_get_mempool (lua_State * L)
  917. {
  918. LUA_TRACE_POINT;
  919. rspamd_mempool_t **ppool;
  920. struct rspamd_config *cfg = lua_check_config (L, 1);
  921. if (cfg != NULL) {
  922. ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *));
  923. rspamd_lua_setclass (L, "rspamd{mempool}", -1);
  924. *ppool = cfg->cfg_pool;
  925. }
  926. else {
  927. lua_pushnil (L);
  928. }
  929. return 1;
  930. }
  931. static int
  932. lua_config_get_resolver (lua_State * L)
  933. {
  934. LUA_TRACE_POINT;
  935. struct rspamd_dns_resolver **pres;
  936. struct rspamd_config *cfg = lua_check_config (L, 1);
  937. if (cfg != NULL && cfg->dns_resolver) {
  938. pres = lua_newuserdata (L, sizeof (*pres));
  939. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  940. *pres = cfg->dns_resolver;
  941. }
  942. else {
  943. lua_pushnil (L);
  944. }
  945. return 1;
  946. }
  947. static gint
  948. lua_config_get_all_opt (lua_State * L)
  949. {
  950. LUA_TRACE_POINT;
  951. struct rspamd_config *cfg = lua_check_config (L, 1);
  952. const gchar *mname;
  953. const ucl_object_t *obj, *cur, *cur_elt;
  954. ucl_object_iter_t it = NULL;
  955. gint i;
  956. if (cfg) {
  957. mname = luaL_checkstring (L, 2);
  958. if (mname) {
  959. obj = ucl_obj_get_key (cfg->rcl_obj, mname);
  960. /* Flatten object */
  961. if (obj != NULL && (ucl_object_type (obj) == UCL_OBJECT ||
  962. ucl_object_type (obj) == UCL_ARRAY)) {
  963. lua_newtable (L);
  964. it = ucl_object_iterate_new (obj);
  965. LL_FOREACH (obj, cur) {
  966. it = ucl_object_iterate_reset (it, cur);
  967. while ((cur_elt = ucl_object_iterate_safe (it, true))) {
  968. lua_pushstring (L, ucl_object_key (cur_elt));
  969. ucl_object_push_lua (L, cur_elt, true);
  970. lua_settable (L, -3);
  971. }
  972. }
  973. ucl_object_iterate_free (it);
  974. return 1;
  975. }
  976. else if (obj != NULL) {
  977. lua_newtable (L);
  978. i = 1;
  979. LL_FOREACH (obj, cur) {
  980. lua_pushinteger (L, i++);
  981. ucl_object_push_lua (L, cur, true);
  982. lua_settable (L, -3);
  983. }
  984. return 1;
  985. }
  986. }
  987. }
  988. lua_pushnil (L);
  989. return 1;
  990. }
  991. struct rspamd_lua_cached_config {
  992. lua_State *L;
  993. gint ref;
  994. };
  995. static void
  996. lua_config_ucl_dtor (gpointer p)
  997. {
  998. struct rspamd_lua_cached_config *cached = p;
  999. luaL_unref (cached->L, LUA_REGISTRYINDEX, cached->ref);
  1000. }
  1001. static gint
  1002. lua_config_get_ucl (lua_State * L)
  1003. {
  1004. LUA_TRACE_POINT;
  1005. struct rspamd_config *cfg = lua_check_config (L, 1);
  1006. struct rspamd_lua_cached_config *cached;
  1007. if (cfg) {
  1008. cached = rspamd_mempool_get_variable (cfg->cfg_pool, "ucl_cached");
  1009. if (cached) {
  1010. lua_rawgeti (L, LUA_REGISTRYINDEX, cached->ref);
  1011. }
  1012. else {
  1013. if (cfg->rcl_obj) {
  1014. ucl_object_push_lua(L, cfg->rcl_obj, true);
  1015. lua_pushvalue(L, -1);
  1016. cached = rspamd_mempool_alloc (cfg->cfg_pool, sizeof(*cached));
  1017. cached->L = L;
  1018. cached->ref = luaL_ref(L, LUA_REGISTRYINDEX);
  1019. rspamd_mempool_set_variable(cfg->cfg_pool, "ucl_cached",
  1020. cached, lua_config_ucl_dtor);
  1021. }
  1022. else {
  1023. lua_pushnil (L);
  1024. }
  1025. }
  1026. }
  1027. else {
  1028. return luaL_error (L, "invalid arguments");
  1029. }
  1030. return 1;
  1031. }
  1032. static gint
  1033. lua_config_get_classifier (lua_State * L)
  1034. {
  1035. LUA_TRACE_POINT;
  1036. struct rspamd_config *cfg = lua_check_config (L, 1);
  1037. struct rspamd_classifier_config *clc = NULL, **pclc = NULL;
  1038. const gchar *name;
  1039. GList *cur;
  1040. if (cfg) {
  1041. name = luaL_checkstring (L, 2);
  1042. cur = g_list_first (cfg->classifiers);
  1043. while (cur) {
  1044. clc = cur->data;
  1045. if (g_ascii_strcasecmp (clc->name, name) == 0) {
  1046. pclc = &clc;
  1047. break;
  1048. }
  1049. cur = g_list_next (cur);
  1050. }
  1051. if (pclc) {
  1052. pclc = lua_newuserdata (L,
  1053. sizeof (struct rspamd_classifier_config *));
  1054. rspamd_lua_setclass (L, "rspamd{classifier}", -1);
  1055. *pclc = clc;
  1056. return 1;
  1057. }
  1058. }
  1059. lua_pushnil (L);
  1060. return 1;
  1061. }
  1062. struct lua_callback_data {
  1063. guint64 magic;
  1064. lua_State *L;
  1065. gchar *symbol;
  1066. union {
  1067. gchar *name;
  1068. gint ref;
  1069. } callback;
  1070. gboolean cb_is_ref;
  1071. /* Dynamic data */
  1072. gint stack_level;
  1073. gint order;
  1074. struct rspamd_symcache_item *item;
  1075. };
  1076. /*
  1077. * Unref symbol if it is local reference
  1078. */
  1079. static void
  1080. lua_destroy_cfg_symbol (gpointer ud)
  1081. {
  1082. struct lua_callback_data *cd = ud;
  1083. /* Unref callback */
  1084. if (cd->cb_is_ref) {
  1085. luaL_unref (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
  1086. }
  1087. }
  1088. static gint
  1089. lua_config_register_module_option (lua_State *L)
  1090. {
  1091. return 0;
  1092. }
  1093. static gint
  1094. rspamd_compare_order_func (gconstpointer a, gconstpointer b)
  1095. {
  1096. const struct lua_callback_data *cb1 = a, *cb2 = b;
  1097. /* order of call goes from lower to higher */
  1098. return cb2->order - cb1->order;
  1099. }
  1100. static void
  1101. lua_metric_symbol_callback (struct rspamd_task *task,
  1102. struct rspamd_symcache_item *item,
  1103. gpointer ud)
  1104. {
  1105. struct lua_callback_data *cd = ud;
  1106. struct rspamd_task **ptask;
  1107. gint level = lua_gettop (cd->L), nresults, err_idx, ret;
  1108. lua_State *L = cd->L;
  1109. struct rspamd_symbol_result *s;
  1110. cd->item = item;
  1111. rspamd_symcache_item_async_inc (task, item, "lua symbol");
  1112. lua_pushcfunction (L, &rspamd_lua_traceback);
  1113. err_idx = lua_gettop (L);
  1114. level ++;
  1115. if (cd->cb_is_ref) {
  1116. lua_rawgeti (L, LUA_REGISTRYINDEX, cd->callback.ref);
  1117. }
  1118. else {
  1119. lua_getglobal (L, cd->callback.name);
  1120. }
  1121. ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
  1122. rspamd_lua_setclass (L, "rspamd{task}", -1);
  1123. *ptask = task;
  1124. if ((ret = lua_pcall (L, 1, LUA_MULTRET, err_idx)) != 0) {
  1125. msg_err_task ("call to (%s) failed (%d): %s", cd->symbol, ret,
  1126. lua_tostring (L, -1));
  1127. lua_settop (L, err_idx); /* Not -1 here, as err_func is popped below */
  1128. }
  1129. else {
  1130. nresults = lua_gettop (L) - level;
  1131. if (nresults >= 1) {
  1132. /* Function returned boolean, so maybe we need to insert result? */
  1133. gint res = 0;
  1134. gint i;
  1135. gdouble flag = 1.0;
  1136. gint type;
  1137. type = lua_type (cd->L, level + 1);
  1138. if (type == LUA_TBOOLEAN) {
  1139. res = lua_toboolean (L, level + 1);
  1140. }
  1141. else if (type == LUA_TNUMBER) {
  1142. res = lua_tonumber (L, level + 1);
  1143. }
  1144. else if (type == LUA_TNIL) {
  1145. /* Can happen sometimes... */
  1146. res = FALSE;
  1147. }
  1148. else {
  1149. g_assert_not_reached ();
  1150. }
  1151. if (res) {
  1152. gint first_opt = 2;
  1153. if (lua_type (L, level + 2) == LUA_TNUMBER) {
  1154. flag = lua_tonumber (L, level + 2);
  1155. /* Shift opt index */
  1156. first_opt = 3;
  1157. }
  1158. else {
  1159. flag = res;
  1160. }
  1161. s = rspamd_task_insert_result (task, cd->symbol, flag, NULL);
  1162. if (s) {
  1163. guint last_pos = lua_gettop (L);
  1164. for (i = level + first_opt; i <= last_pos; i++) {
  1165. if (lua_type (L, i) == LUA_TSTRING) {
  1166. gsize optlen;
  1167. const char *opt = lua_tolstring (L, i, &optlen);
  1168. rspamd_task_add_result_option (task, s, opt, optlen);
  1169. }
  1170. else if (lua_type (L, i) == LUA_TUSERDATA) {
  1171. struct rspamd_lua_text *t = lua_check_text (L, i);
  1172. if (t) {
  1173. rspamd_task_add_result_option (task, s, t->start,
  1174. t->len);
  1175. }
  1176. }
  1177. else if (lua_type (L, i) == LUA_TTABLE) {
  1178. gsize objlen = rspamd_lua_table_size (L, i);
  1179. for (guint j = 1; j <= objlen; j ++) {
  1180. lua_rawgeti (L, i, j);
  1181. if (lua_type (L, -1) == LUA_TSTRING) {
  1182. gsize optlen;
  1183. const char *opt = lua_tolstring (L, -1, &optlen);
  1184. rspamd_task_add_result_option (task, s, opt, optlen);
  1185. }
  1186. else if (lua_type (L, -1) == LUA_TUSERDATA) {
  1187. struct rspamd_lua_text *t = lua_check_text (L, -1);
  1188. if (t) {
  1189. rspamd_task_add_result_option (task, s, t->start,
  1190. t->len);
  1191. }
  1192. }
  1193. lua_pop (L, 1);
  1194. }
  1195. }
  1196. }
  1197. }
  1198. }
  1199. lua_pop (L, nresults);
  1200. }
  1201. }
  1202. lua_pop (L, 1); /* Error function */
  1203. rspamd_symcache_item_async_dec_check (task, cd->item, "lua symbol");
  1204. g_assert (lua_gettop (L) == level - 1);
  1205. }
  1206. static void lua_metric_symbol_callback_return (struct thread_entry *thread_entry,
  1207. int ret);
  1208. static void lua_metric_symbol_callback_error (struct thread_entry *thread_entry,
  1209. int ret,
  1210. const char *msg);
  1211. static void
  1212. lua_metric_symbol_callback_coro (struct rspamd_task *task,
  1213. struct rspamd_symcache_item *item,
  1214. gpointer ud)
  1215. {
  1216. struct lua_callback_data *cd = ud;
  1217. struct rspamd_task **ptask;
  1218. struct thread_entry *thread_entry;
  1219. rspamd_symcache_item_async_inc (task, item, "lua coro symbol");
  1220. thread_entry = lua_thread_pool_get_for_task (task);
  1221. g_assert(thread_entry->cd == NULL);
  1222. thread_entry->cd = cd;
  1223. lua_State *thread = thread_entry->lua_state;
  1224. cd->stack_level = lua_gettop (thread);
  1225. cd->item = item;
  1226. if (cd->cb_is_ref) {
  1227. lua_rawgeti (thread, LUA_REGISTRYINDEX, cd->callback.ref);
  1228. }
  1229. else {
  1230. lua_getglobal (thread, cd->callback.name);
  1231. }
  1232. ptask = lua_newuserdata (thread, sizeof (struct rspamd_task *));
  1233. rspamd_lua_setclass (thread, "rspamd{task}", -1);
  1234. *ptask = task;
  1235. thread_entry->finish_callback = lua_metric_symbol_callback_return;
  1236. thread_entry->error_callback = lua_metric_symbol_callback_error;
  1237. lua_thread_call (thread_entry, 1);
  1238. }
  1239. static void
  1240. lua_metric_symbol_callback_error (struct thread_entry *thread_entry,
  1241. int ret,
  1242. const char *msg)
  1243. {
  1244. struct lua_callback_data *cd = thread_entry->cd;
  1245. struct rspamd_task *task = thread_entry->task;
  1246. msg_err_task ("call to coroutine (%s) failed (%d): %s", cd->symbol, ret, msg);
  1247. rspamd_symcache_item_async_dec_check (task, cd->item, "lua coro symbol");
  1248. }
  1249. static void
  1250. lua_metric_symbol_callback_return (struct thread_entry *thread_entry, int ret)
  1251. {
  1252. struct lua_callback_data *cd = thread_entry->cd;
  1253. struct rspamd_task *task = thread_entry->task;
  1254. int nresults;
  1255. struct rspamd_symbol_result *s;
  1256. (void)ret;
  1257. lua_State *L = thread_entry->lua_state;
  1258. nresults = lua_gettop (L) - cd->stack_level;
  1259. if (nresults >= 1) {
  1260. /* Function returned boolean, so maybe we need to insert result? */
  1261. gint res = 0;
  1262. gint i;
  1263. gdouble flag = 1.0;
  1264. gint type;
  1265. type = lua_type (L, cd->stack_level + 1);
  1266. if (type == LUA_TBOOLEAN) {
  1267. res = lua_toboolean (L, cd->stack_level + 1);
  1268. }
  1269. else if (type == LUA_TFUNCTION) {
  1270. g_assert_not_reached ();
  1271. }
  1272. else {
  1273. res = lua_tonumber (L, cd->stack_level + 1);
  1274. }
  1275. if (res) {
  1276. gint first_opt = 2;
  1277. if (lua_type (L, cd->stack_level + 2) == LUA_TNUMBER) {
  1278. flag = lua_tonumber (L, cd->stack_level + 2);
  1279. /* Shift opt index */
  1280. first_opt = 3;
  1281. }
  1282. else {
  1283. flag = res;
  1284. }
  1285. s = rspamd_task_insert_result (task, cd->symbol, flag, NULL);
  1286. if (s) {
  1287. guint last_pos = lua_gettop (L);
  1288. for (i = cd->stack_level + first_opt; i <= last_pos; i++) {
  1289. if (lua_type (L, i) == LUA_TSTRING) {
  1290. gsize optlen;
  1291. const char *opt = lua_tolstring (L, i, &optlen);
  1292. rspamd_task_add_result_option (task, s, opt, optlen);
  1293. }
  1294. else if (lua_type (L, i) == LUA_TUSERDATA) {
  1295. struct rspamd_lua_text *t = lua_check_text (L, i);
  1296. if (t) {
  1297. rspamd_task_add_result_option (task, s, t->start,
  1298. t->len);
  1299. }
  1300. }
  1301. else if (lua_type (L, i) == LUA_TTABLE) {
  1302. gsize objlen = rspamd_lua_table_size (L, i);
  1303. for (guint j = 1; j <= objlen; j ++) {
  1304. lua_rawgeti (L, i, j);
  1305. if (lua_type (L, -1) == LUA_TSTRING) {
  1306. gsize optlen;
  1307. const char *opt = lua_tolstring (L, -1, &optlen);
  1308. rspamd_task_add_result_option (task, s, opt, optlen);
  1309. }
  1310. else if (lua_type (L, -1) == LUA_TUSERDATA) {
  1311. struct rspamd_lua_text *t = lua_check_text (L, -1);
  1312. if (t) {
  1313. rspamd_task_add_result_option (task, s, t->start,
  1314. t->len);
  1315. }
  1316. }
  1317. lua_pop (L, 1);
  1318. }
  1319. }
  1320. }
  1321. }
  1322. }
  1323. lua_pop (L, nresults);
  1324. }
  1325. g_assert (lua_gettop (L) == cd->stack_level); /* we properly cleaned up the stack */
  1326. cd->stack_level = 0;
  1327. rspamd_symcache_item_async_dec_check (task, cd->item, "lua coro symbol");
  1328. }
  1329. static guint32*
  1330. rspamd_process_id_list (const gchar *entries, guint32 *plen)
  1331. {
  1332. gchar **sym_elts;
  1333. guint32 *ids, nids;
  1334. sym_elts = g_strsplit_set (entries, ",;", -1);
  1335. nids = g_strv_length (sym_elts);
  1336. ids = g_malloc (nids * sizeof (guint32));
  1337. for (guint i = 0; i < nids; i ++) {
  1338. ids[i] = rspamd_config_name_to_id (sym_elts[i], strlen (sym_elts[i]));
  1339. }
  1340. *plen = nids;
  1341. g_strfreev (sym_elts);
  1342. return ids;
  1343. }
  1344. static gint
  1345. rspamd_register_symbol_fromlua (lua_State *L,
  1346. struct rspamd_config *cfg,
  1347. const gchar *name,
  1348. gint ref,
  1349. gdouble weight,
  1350. gint priority,
  1351. enum rspamd_symbol_type type,
  1352. gint parent,
  1353. const gchar *allowed_ids,
  1354. const gchar *forbidden_ids,
  1355. gboolean optional)
  1356. {
  1357. struct lua_callback_data *cd;
  1358. gint ret = -1;
  1359. guint32 *ids, nids;
  1360. if (priority == 0 && weight < 0) {
  1361. priority = 1;
  1362. }
  1363. if ((ret = rspamd_symcache_find_symbol (cfg->cache, name)) != -1) {
  1364. if (optional) {
  1365. msg_debug_config ("duplicate symbol: %s, skip registering", name);
  1366. return ret;
  1367. }
  1368. else {
  1369. msg_err_config ("duplicate symbol: %s, skip registering", name);
  1370. return -1;
  1371. }
  1372. }
  1373. if (allowed_ids && !(type & SYMBOL_TYPE_EXPLICIT_DISABLE)) {
  1374. /* Mark symbol as explicit allow */
  1375. msg_info_config ("mark symbol %s as explicit enable as its execution is"
  1376. "allowed merely on specific settings ids", name);
  1377. type |= SYMBOL_TYPE_EXPLICIT_ENABLE;
  1378. }
  1379. if (ref != -1) {
  1380. cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
  1381. sizeof (struct lua_callback_data));
  1382. cd->magic = rspamd_lua_callback_magic;
  1383. cd->cb_is_ref = TRUE;
  1384. cd->callback.ref = ref;
  1385. cd->L = L;
  1386. if (name) {
  1387. cd->symbol = rspamd_mempool_strdup (cfg->cfg_pool, name);
  1388. }
  1389. if (type & SYMBOL_TYPE_USE_CORO) {
  1390. ret = rspamd_symcache_add_symbol (cfg->cache,
  1391. name,
  1392. priority,
  1393. lua_metric_symbol_callback_coro,
  1394. cd,
  1395. type,
  1396. parent);
  1397. }
  1398. else {
  1399. ret = rspamd_symcache_add_symbol (cfg->cache,
  1400. name,
  1401. priority,
  1402. lua_metric_symbol_callback,
  1403. cd,
  1404. type,
  1405. parent);
  1406. }
  1407. rspamd_mempool_add_destructor (cfg->cfg_pool,
  1408. (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
  1409. cd);
  1410. }
  1411. else {
  1412. /* No callback */
  1413. ret = rspamd_symcache_add_symbol (cfg->cache,
  1414. name,
  1415. priority,
  1416. NULL,
  1417. NULL,
  1418. type,
  1419. parent);
  1420. }
  1421. if (allowed_ids) {
  1422. ids = rspamd_process_id_list (allowed_ids, &nids);
  1423. if (nids > 0) {
  1424. GString *dbg = g_string_new ("");
  1425. for (guint i = 0; i < nids; i ++) {
  1426. rspamd_printf_gstring (dbg, "%ud,", ids[i]);
  1427. }
  1428. dbg->len --;
  1429. msg_debug_config ("allowed ids for %s are: %v", name, dbg);
  1430. g_string_free (dbg, TRUE);
  1431. rspamd_symcache_set_allowed_settings_ids (cfg->cache, name,
  1432. ids, nids);
  1433. }
  1434. g_free (ids);
  1435. }
  1436. if (forbidden_ids) {
  1437. ids = rspamd_process_id_list (forbidden_ids, &nids);
  1438. if (nids > 0) {
  1439. GString *dbg = g_string_new ("");
  1440. for (guint i = 0; i < nids; i ++) {
  1441. rspamd_printf_gstring (dbg, "%ud,", ids[i]);
  1442. }
  1443. dbg->len --;
  1444. msg_debug_config ("forbidden ids for %s are: %v", name, dbg);
  1445. g_string_free (dbg, TRUE);
  1446. rspamd_symcache_set_forbidden_settings_ids (cfg->cache, name,
  1447. ids, nids);
  1448. }
  1449. g_free (ids);
  1450. }
  1451. return ret;
  1452. }
  1453. static gint
  1454. lua_config_register_post_filter (lua_State *L)
  1455. {
  1456. LUA_TRACE_POINT;
  1457. struct rspamd_config *cfg = lua_check_config (L, 1);
  1458. gint order = 0, cbref, ret;
  1459. if (cfg) {
  1460. if (lua_type (L, 3) == LUA_TNUMBER) {
  1461. order = lua_tonumber (L, 3);
  1462. }
  1463. if (lua_type (L, 2) == LUA_TFUNCTION) {
  1464. lua_pushvalue (L, 2);
  1465. /* Get a reference */
  1466. cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  1467. }
  1468. else {
  1469. return luaL_error (L, "invalid type for callback: %s",
  1470. lua_typename (L, lua_type (L, 2)));
  1471. }
  1472. msg_warn_config ("register_post_filter function is deprecated, "
  1473. "use register_symbol instead");
  1474. ret = rspamd_register_symbol_fromlua (L,
  1475. cfg,
  1476. NULL,
  1477. cbref,
  1478. 1.0,
  1479. order,
  1480. SYMBOL_TYPE_POSTFILTER|SYMBOL_TYPE_CALLBACK,
  1481. -1,
  1482. NULL, NULL,
  1483. FALSE);
  1484. lua_pushboolean (L, ret);
  1485. }
  1486. else {
  1487. return luaL_error (L, "invalid arguments");
  1488. }
  1489. return 1;
  1490. }
  1491. static gint
  1492. lua_config_register_pre_filter (lua_State *L)
  1493. {
  1494. LUA_TRACE_POINT;
  1495. struct rspamd_config *cfg = lua_check_config (L, 1);
  1496. gint order = 0, cbref, ret;
  1497. if (cfg) {
  1498. if (lua_type (L, 3) == LUA_TNUMBER) {
  1499. order = lua_tonumber (L, 3);
  1500. }
  1501. if (lua_type (L, 2) == LUA_TFUNCTION) {
  1502. lua_pushvalue (L, 2);
  1503. /* Get a reference */
  1504. cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  1505. }
  1506. else {
  1507. return luaL_error (L, "invalid type for callback: %s",
  1508. lua_typename (L, lua_type (L, 2)));
  1509. }
  1510. msg_warn_config ("register_pre_filter function is deprecated, "
  1511. "use register_symbol instead");
  1512. ret = rspamd_register_symbol_fromlua (L,
  1513. cfg,
  1514. NULL,
  1515. cbref,
  1516. 1.0,
  1517. order,
  1518. SYMBOL_TYPE_PREFILTER|SYMBOL_TYPE_CALLBACK,
  1519. -1,
  1520. NULL, NULL,
  1521. FALSE);
  1522. lua_pushboolean (L, ret);
  1523. }
  1524. else {
  1525. return luaL_error (L, "invalid arguments");
  1526. }
  1527. return 1;
  1528. }
  1529. static gint
  1530. lua_config_get_key (lua_State *L)
  1531. {
  1532. LUA_TRACE_POINT;
  1533. struct rspamd_config *cfg = lua_check_config (L, 1);
  1534. const gchar *name;
  1535. size_t namelen;
  1536. const ucl_object_t *val;
  1537. name = luaL_checklstring(L, 2, &namelen);
  1538. if (name && cfg) {
  1539. val = ucl_object_lookup_len(cfg->rcl_obj, name, namelen);
  1540. if (val != NULL) {
  1541. ucl_object_push_lua (L, val, val->type != UCL_ARRAY);
  1542. }
  1543. else {
  1544. lua_pushnil (L);
  1545. }
  1546. }
  1547. else {
  1548. return luaL_error (L, "invalid arguments");
  1549. }
  1550. return 1;
  1551. }
  1552. static guint
  1553. lua_parse_symbol_flags (const gchar *str)
  1554. {
  1555. guint ret = 0;
  1556. if (str) {
  1557. if (strstr (str, "fine") != NULL) {
  1558. ret |= SYMBOL_TYPE_FINE;
  1559. }
  1560. if (strstr (str, "nice") != NULL) {
  1561. ret |= SYMBOL_TYPE_FINE;
  1562. }
  1563. if (strstr (str, "empty") != NULL) {
  1564. ret |= SYMBOL_TYPE_EMPTY;
  1565. }
  1566. if (strstr (str, "skip") != NULL) {
  1567. ret |= SYMBOL_TYPE_SKIPPED;
  1568. }
  1569. if (strstr (str, "nostat") != NULL) {
  1570. ret |= SYMBOL_TYPE_NOSTAT;
  1571. }
  1572. if (strstr (str, "idempotent") != NULL) {
  1573. ret |= SYMBOL_TYPE_IDEMPOTENT;
  1574. }
  1575. if (strstr (str, "trivial") != NULL) {
  1576. ret |= SYMBOL_TYPE_TRIVIAL;
  1577. }
  1578. if (strstr (str, "ghost") != NULL) {
  1579. ret |= SYMBOL_TYPE_GHOST;
  1580. }
  1581. if (strstr (str, "mime") != NULL) {
  1582. ret |= SYMBOL_TYPE_MIME_ONLY;
  1583. }
  1584. if (strstr (str, "ignore_passthrough") != NULL) {
  1585. ret |= SYMBOL_TYPE_IGNORE_PASSTHROUGH;
  1586. }
  1587. if (strstr (str, "explicit_disable") != NULL) {
  1588. ret |= SYMBOL_TYPE_EXPLICIT_DISABLE;
  1589. }
  1590. if (strstr (str, "explicit_enable") != NULL) {
  1591. ret |= SYMBOL_TYPE_EXPLICIT_ENABLE;
  1592. }
  1593. if (strstr (str, "coro") != NULL) {
  1594. ret |= SYMBOL_TYPE_USE_CORO;
  1595. }
  1596. }
  1597. return ret;
  1598. }
  1599. static guint
  1600. lua_parse_symbol_type (const gchar *str)
  1601. {
  1602. guint ret = SYMBOL_TYPE_NORMAL;
  1603. gchar **vec;
  1604. guint i, l;
  1605. if (str) {
  1606. vec = g_strsplit_set (str, ",;", -1);
  1607. if (vec) {
  1608. l = g_strv_length (vec);
  1609. for (i = 0; i < l; i ++) {
  1610. str = vec[i];
  1611. if (g_ascii_strcasecmp (str, "virtual") == 0) {
  1612. ret |= SYMBOL_TYPE_VIRTUAL;
  1613. ret &= ~SYMBOL_TYPE_NORMAL;
  1614. ret &= ~SYMBOL_TYPE_CALLBACK;
  1615. }
  1616. else if (g_ascii_strcasecmp (str, "callback") == 0) {
  1617. ret |= SYMBOL_TYPE_CALLBACK;
  1618. ret &= ~SYMBOL_TYPE_NORMAL;
  1619. ret &= ~SYMBOL_TYPE_VIRTUAL;
  1620. }
  1621. else if (g_ascii_strcasecmp (str, "normal") == 0) {
  1622. ret |= SYMBOL_TYPE_NORMAL;
  1623. ret &= ~SYMBOL_TYPE_CALLBACK;
  1624. ret &= ~SYMBOL_TYPE_VIRTUAL;
  1625. }
  1626. else if (g_ascii_strcasecmp (str, "prefilter") == 0) {
  1627. ret |= SYMBOL_TYPE_PREFILTER | SYMBOL_TYPE_GHOST;
  1628. }
  1629. else if (g_ascii_strcasecmp (str, "postfilter") == 0) {
  1630. ret |= SYMBOL_TYPE_POSTFILTER | SYMBOL_TYPE_GHOST;
  1631. }
  1632. else if (g_ascii_strcasecmp (str, "connfilter") == 0 ||
  1633. g_ascii_strcasecmp (str, "conn_filter") == 0) {
  1634. ret |= SYMBOL_TYPE_CONNFILTER | SYMBOL_TYPE_GHOST;
  1635. }
  1636. else if (g_ascii_strcasecmp (str, "idempotent") == 0) {
  1637. ret |= SYMBOL_TYPE_POSTFILTER | SYMBOL_TYPE_GHOST |
  1638. SYMBOL_TYPE_IDEMPOTENT | SYMBOL_TYPE_CALLBACK;
  1639. }
  1640. else {
  1641. gint fl = 0;
  1642. fl = lua_parse_symbol_flags (str);
  1643. if (fl == 0) {
  1644. msg_warn ("bad type: %s", str);
  1645. }
  1646. else {
  1647. ret |= fl;
  1648. }
  1649. }
  1650. }
  1651. g_strfreev (vec);
  1652. }
  1653. }
  1654. return ret;
  1655. }
  1656. enum lua_push_symbol_flags_opts {
  1657. LUA_SYMOPT_FLAG_CREATE_ARRAY = 1u << 0u,
  1658. LUA_SYMOPT_FLAG_CREATE_MAP = 1u << 1u,
  1659. LUA_SYMOPT_FLAG_USE_MAP = 1u << 2u,
  1660. LUA_SYMOPT_FLAG_USE_ARRAY = 1u << 3u,
  1661. };
  1662. #define LUA_SYMOPT_IS_ARRAY(f) ((f) & (LUA_SYMOPT_FLAG_CREATE_ARRAY|LUA_SYMOPT_FLAG_USE_ARRAY))
  1663. #define LUA_SYMOPT_IS_CREATE(f) ((f) & (LUA_SYMOPT_FLAG_CREATE_ARRAY|LUA_SYMOPT_FLAG_CREATE_MAP))
  1664. #define LUA_OPTION_PUSH(nm) do { \
  1665. if (LUA_SYMOPT_IS_ARRAY(fl)) { \
  1666. lua_pushstring (L, #nm); \
  1667. lua_rawseti (L, -2, i++); \
  1668. } \
  1669. else { \
  1670. lua_pushboolean (L, true); \
  1671. lua_setfield (L, -2, #nm); \
  1672. } \
  1673. } while(0)
  1674. static void
  1675. lua_push_symbol_flags (lua_State *L, guint flags, enum lua_push_symbol_flags_opts fl)
  1676. {
  1677. guint i = 1;
  1678. if (LUA_SYMOPT_IS_CREATE (fl)) {
  1679. lua_newtable (L);
  1680. }
  1681. if (flags & SYMBOL_TYPE_FINE) {
  1682. LUA_OPTION_PUSH (fine);
  1683. }
  1684. if (flags & SYMBOL_TYPE_EMPTY) {
  1685. LUA_OPTION_PUSH (empty);
  1686. }
  1687. if (flags & SYMBOL_TYPE_EXPLICIT_DISABLE) {
  1688. LUA_OPTION_PUSH (explicit_disable);
  1689. }
  1690. if (flags & SYMBOL_TYPE_EXPLICIT_ENABLE) {
  1691. LUA_OPTION_PUSH (explicit_enable);
  1692. }
  1693. if (flags & SYMBOL_TYPE_IGNORE_PASSTHROUGH) {
  1694. LUA_OPTION_PUSH (ignore_passthrough);
  1695. }
  1696. if (flags & SYMBOL_TYPE_NOSTAT) {
  1697. LUA_OPTION_PUSH (nostat);
  1698. }
  1699. if (flags & SYMBOL_TYPE_IDEMPOTENT) {
  1700. LUA_OPTION_PUSH (idempotent);
  1701. }
  1702. if (flags & SYMBOL_TYPE_MIME_ONLY) {
  1703. LUA_OPTION_PUSH (mime);
  1704. }
  1705. if (flags & SYMBOL_TYPE_TRIVIAL) {
  1706. LUA_OPTION_PUSH (trivial);
  1707. }
  1708. if (flags & SYMBOL_TYPE_SKIPPED) {
  1709. LUA_OPTION_PUSH (skip);
  1710. }
  1711. if (flags & SYMBOL_TYPE_COMPOSITE) {
  1712. LUA_OPTION_PUSH (composite);
  1713. }
  1714. }
  1715. static gint
  1716. lua_config_get_symbol_flags (lua_State *L)
  1717. {
  1718. struct rspamd_config *cfg = lua_check_config (L, 1);
  1719. const gchar *name = luaL_checkstring (L, 2);
  1720. guint flags;
  1721. if (cfg && name) {
  1722. flags = rspamd_symcache_get_symbol_flags (cfg->cache,
  1723. name);
  1724. if (flags != 0) {
  1725. lua_push_symbol_flags (L, flags, LUA_SYMOPT_FLAG_CREATE_ARRAY);
  1726. }
  1727. else {
  1728. lua_pushnil (L);
  1729. }
  1730. }
  1731. else {
  1732. return luaL_error (L, "invalid arguments");
  1733. }
  1734. return 1;
  1735. }
  1736. static gint
  1737. lua_config_add_symbol_flags (lua_State *L)
  1738. {
  1739. struct rspamd_config *cfg = lua_check_config (L, 1);
  1740. const gchar *name = luaL_checkstring (L, 2);
  1741. guint flags, new_flags = 0;
  1742. if (cfg && name && lua_istable (L, 3)) {
  1743. for (lua_pushnil (L); lua_next (L, 3); lua_pop (L, 1)) {
  1744. new_flags |= lua_parse_symbol_flags (lua_tostring (L, -1));
  1745. }
  1746. flags = rspamd_symcache_get_symbol_flags (cfg->cache,
  1747. name);
  1748. if (flags != 0) {
  1749. rspamd_symcache_add_symbol_flags (cfg->cache, name, new_flags);
  1750. /* Push old flags */
  1751. lua_push_symbol_flags (L, flags, LUA_SYMOPT_FLAG_CREATE_ARRAY);
  1752. }
  1753. else {
  1754. lua_pushnil (L);
  1755. }
  1756. }
  1757. else {
  1758. return luaL_error (L, "invalid arguments");
  1759. }
  1760. return 1;
  1761. }
  1762. static gint
  1763. lua_config_register_symbol (lua_State * L)
  1764. {
  1765. LUA_TRACE_POINT;
  1766. struct rspamd_config *cfg = lua_check_config (L, 1);
  1767. const gchar *name = NULL, *flags_str = NULL, *type_str = NULL,
  1768. *description = NULL, *group = NULL, *allowed_ids = NULL,
  1769. *forbidden_ids = NULL;
  1770. double weight = 0, score = NAN, parent_float = NAN;
  1771. gboolean one_shot = FALSE;
  1772. gint ret = -1, cbref = -1, type, flags = 0;
  1773. gint64 parent = 0, priority = 0, nshots = 0;
  1774. GError *err = NULL;
  1775. if (cfg) {
  1776. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  1777. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  1778. "name=S;weight=N;callback=F;flags=S;type=S;priority=I;parent=D;"
  1779. "score=D;description=S;group=S;one_shot=B;nshots=I;"
  1780. "allowed_ids=S;forbidden_ids=S",
  1781. &name, &weight, &cbref, &flags_str, &type_str,
  1782. &priority, &parent_float,
  1783. &score, &description, &group, &one_shot, &nshots,
  1784. &allowed_ids, &forbidden_ids)) {
  1785. msg_err_config ("bad arguments: %e", err);
  1786. g_error_free (err);
  1787. return luaL_error (L, "invalid arguments");
  1788. }
  1789. if (nshots == 0) {
  1790. nshots = cfg->default_max_shots;
  1791. }
  1792. type = lua_parse_symbol_type (type_str);
  1793. if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
  1794. return luaL_error (L, "no symbol name but type is not callback");
  1795. }
  1796. else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
  1797. return luaL_error (L, "no callback for symbol %s", name);
  1798. }
  1799. if (flags_str) {
  1800. type |= lua_parse_symbol_flags (flags_str);
  1801. }
  1802. if (isnan (parent_float)) {
  1803. parent = -1;
  1804. }
  1805. else {
  1806. parent = parent_float;
  1807. }
  1808. ret = rspamd_register_symbol_fromlua (L,
  1809. cfg,
  1810. name,
  1811. cbref,
  1812. weight == 0 ? 1.0 : weight,
  1813. priority,
  1814. type,
  1815. parent,
  1816. allowed_ids, forbidden_ids,
  1817. FALSE);
  1818. if (!isnan (score) || group) {
  1819. if (one_shot) {
  1820. nshots = 1;
  1821. }
  1822. rspamd_config_add_symbol (cfg, name,
  1823. score, description, group, flags,
  1824. 0, nshots);
  1825. lua_pushstring (L, "groups");
  1826. lua_gettable (L, 2);
  1827. if (lua_istable (L, -1)) {
  1828. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  1829. if (lua_isstring (L, -1)) {
  1830. rspamd_config_add_symbol_group (cfg, name,
  1831. lua_tostring (L, -1));
  1832. }
  1833. else {
  1834. return luaL_error (L, "invalid groups element");
  1835. }
  1836. }
  1837. }
  1838. lua_pop (L, 1);
  1839. }
  1840. }
  1841. else {
  1842. return luaL_error (L, "invalid arguments");
  1843. }
  1844. lua_pushinteger (L, ret);
  1845. return 1;
  1846. }
  1847. static gint
  1848. lua_config_register_symbols (lua_State *L)
  1849. {
  1850. LUA_TRACE_POINT;
  1851. struct rspamd_config *cfg = lua_check_config (L, 1);
  1852. gint i, top, idx, ret = -1;
  1853. const gchar *sym;
  1854. gdouble weight = 1.0;
  1855. if (lua_gettop (L) < 3) {
  1856. if (cfg) {
  1857. msg_err_config ("not enough arguments to register a function");
  1858. }
  1859. lua_error (L);
  1860. return 0;
  1861. }
  1862. if (cfg) {
  1863. if (lua_type (L, 2) == LUA_TSTRING) {
  1864. lua_getglobal (L, luaL_checkstring (L, 2));
  1865. }
  1866. else {
  1867. lua_pushvalue (L, 2);
  1868. }
  1869. idx = luaL_ref (L, LUA_REGISTRYINDEX);
  1870. if (lua_type (L, 3) == LUA_TNUMBER) {
  1871. weight = lua_tonumber (L, 3);
  1872. top = 4;
  1873. }
  1874. else {
  1875. top = 3;
  1876. }
  1877. sym = luaL_checkstring (L, top ++);
  1878. ret = rspamd_register_symbol_fromlua (L,
  1879. cfg,
  1880. sym,
  1881. idx,
  1882. weight,
  1883. 0,
  1884. SYMBOL_TYPE_CALLBACK,
  1885. -1,
  1886. NULL, NULL,
  1887. FALSE);
  1888. for (i = top; i <= lua_gettop (L); i++) {
  1889. if (lua_type (L, i) == LUA_TTABLE) {
  1890. lua_pushvalue (L, i);
  1891. lua_pushnil (L);
  1892. while (lua_next (L, -2)) {
  1893. lua_pushvalue (L, -2);
  1894. sym = luaL_checkstring (L, -2);
  1895. rspamd_symcache_add_symbol (cfg->cache, sym,
  1896. 0, NULL, NULL,
  1897. SYMBOL_TYPE_VIRTUAL, ret);
  1898. lua_pop (L, 2);
  1899. }
  1900. lua_pop (L, 1);
  1901. }
  1902. else if (lua_type (L, i) == LUA_TSTRING) {
  1903. sym = luaL_checkstring (L, i);
  1904. rspamd_symcache_add_symbol (cfg->cache, sym,
  1905. 0, NULL, NULL,
  1906. SYMBOL_TYPE_VIRTUAL, ret);
  1907. }
  1908. }
  1909. }
  1910. lua_pushinteger (L, ret);
  1911. return 1;
  1912. }
  1913. static gint
  1914. lua_config_register_virtual_symbol (lua_State * L)
  1915. {
  1916. LUA_TRACE_POINT;
  1917. struct rspamd_config *cfg = lua_check_config (L, 1);
  1918. const gchar *name;
  1919. double weight;
  1920. gint ret = -1, parent = -1;
  1921. if (cfg) {
  1922. name = luaL_checkstring (L, 2);
  1923. weight = luaL_checknumber (L, 3);
  1924. if (lua_gettop (L) > 3) {
  1925. parent = lua_tonumber (L, 4);
  1926. }
  1927. if (name) {
  1928. ret = rspamd_symcache_add_symbol (cfg->cache, name,
  1929. weight > 0 ? 0 : -1, NULL, NULL,
  1930. SYMBOL_TYPE_VIRTUAL, parent);
  1931. }
  1932. }
  1933. lua_pushinteger (L, ret);
  1934. return 1;
  1935. }
  1936. static gint
  1937. lua_config_register_callback_symbol (lua_State * L)
  1938. {
  1939. LUA_TRACE_POINT;
  1940. struct rspamd_config *cfg = lua_check_config (L, 1);
  1941. const gchar *name = NULL;
  1942. double weight;
  1943. gint ret = -1, top = 2;
  1944. if (cfg) {
  1945. if (lua_type (L, 2) == LUA_TSTRING) {
  1946. /* Legacy syntax */
  1947. name = luaL_checkstring (L, 2);
  1948. top ++;
  1949. }
  1950. weight = luaL_checknumber (L, top);
  1951. if (lua_type (L, top + 1) == LUA_TSTRING) {
  1952. lua_getglobal (L, luaL_checkstring (L, top + 1));
  1953. }
  1954. else {
  1955. lua_pushvalue (L, top + 1);
  1956. }
  1957. ret = rspamd_register_symbol_fromlua (L,
  1958. cfg,
  1959. name,
  1960. luaL_ref (L, LUA_REGISTRYINDEX),
  1961. weight,
  1962. 0,
  1963. SYMBOL_TYPE_CALLBACK,
  1964. -1,
  1965. NULL, NULL,
  1966. FALSE);
  1967. }
  1968. lua_pushinteger (L, ret);
  1969. return 1;
  1970. }
  1971. static gint
  1972. lua_config_register_callback_symbol_priority (lua_State * L)
  1973. {
  1974. LUA_TRACE_POINT;
  1975. struct rspamd_config *cfg = lua_check_config (L, 1);
  1976. const gchar *name = NULL;
  1977. double weight;
  1978. gint priority, ret = -1, top = 2;
  1979. if (cfg) {
  1980. if (lua_type (L, 2) == LUA_TSTRING) {
  1981. /* Legacy syntax */
  1982. name = luaL_checkstring (L, 2);
  1983. top ++;
  1984. }
  1985. weight = luaL_checknumber (L, top);
  1986. priority = luaL_checknumber (L, top + 1);
  1987. if (lua_type (L, top + 2) == LUA_TSTRING) {
  1988. lua_getglobal (L, luaL_checkstring (L, top + 2));
  1989. }
  1990. else {
  1991. lua_pushvalue (L, top + 2);
  1992. }
  1993. ret = rspamd_register_symbol_fromlua (L,
  1994. cfg,
  1995. name,
  1996. luaL_ref (L, LUA_REGISTRYINDEX),
  1997. weight,
  1998. priority,
  1999. SYMBOL_TYPE_CALLBACK,
  2000. -1,
  2001. NULL, NULL,
  2002. FALSE);
  2003. }
  2004. lua_pushinteger (L, ret);
  2005. return 1;
  2006. }
  2007. static gint
  2008. lua_config_register_dependency (lua_State * L)
  2009. {
  2010. LUA_TRACE_POINT;
  2011. struct rspamd_config *cfg = lua_check_config (L, 1);
  2012. const gchar *parent = NULL, *child = NULL;
  2013. gint child_id;
  2014. if (cfg == NULL) {
  2015. lua_error (L);
  2016. return 0;
  2017. }
  2018. if (lua_type (L, 2) == LUA_TNUMBER) {
  2019. child_id = luaL_checknumber (L, 2);
  2020. parent = luaL_checkstring (L, 3);
  2021. msg_warn_config ("calling for obsolete method to register deps for symbol %d->%s",
  2022. child_id, parent);
  2023. if (child_id > 0 && parent != NULL) {
  2024. rspamd_symcache_add_dependency (cfg->cache, child_id, parent,
  2025. -1);
  2026. }
  2027. }
  2028. else {
  2029. child = luaL_checkstring (L,2);
  2030. parent = luaL_checkstring (L, 3);
  2031. if (child != NULL && parent != NULL) {
  2032. rspamd_symcache_add_delayed_dependency (cfg->cache, child,
  2033. parent);
  2034. }
  2035. }
  2036. return 0;
  2037. }
  2038. static gint
  2039. lua_config_set_metric_symbol (lua_State * L)
  2040. {
  2041. LUA_TRACE_POINT;
  2042. struct rspamd_config *cfg = lua_check_config (L, 1);
  2043. const gchar *description = NULL,
  2044. *group = NULL, *name = NULL, *flags_str = NULL;
  2045. double score;
  2046. gboolean one_shot = FALSE, one_param = FALSE;
  2047. GError *err = NULL;
  2048. gdouble priority = 0.0;
  2049. guint flags = 0;
  2050. gint64 nshots = 0;
  2051. if (cfg) {
  2052. if (lua_type (L, 2) == LUA_TTABLE) {
  2053. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  2054. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  2055. "*name=S;score=N;description=S;"
  2056. "group=S;one_shot=B;one_param=B;priority=N;flags=S;"
  2057. "nshots=I",
  2058. &name, &score, &description,
  2059. &group, &one_shot, &one_param,
  2060. &priority, &flags_str, &nshots)) {
  2061. msg_err_config ("bad arguments: %e", err);
  2062. g_error_free (err);
  2063. return 0;
  2064. }
  2065. }
  2066. else {
  2067. name = luaL_checkstring (L, 2);
  2068. score = luaL_checknumber (L, 3);
  2069. if (lua_gettop (L) > 3 && lua_type (L, 4) == LUA_TSTRING) {
  2070. description = luaL_checkstring (L, 4);
  2071. }
  2072. if (lua_gettop (L) > 4 && lua_type (L, 5) == LUA_TSTRING) {
  2073. /* XXX: metrics */
  2074. }
  2075. if (lua_gettop (L) > 5 && lua_type (L, 6) == LUA_TSTRING) {
  2076. group = luaL_checkstring (L, 6);
  2077. }
  2078. if (lua_gettop (L) > 6 && lua_type (L, 7) == LUA_TBOOLEAN) {
  2079. one_shot = lua_toboolean (L, 7);
  2080. }
  2081. }
  2082. if (nshots == 0) {
  2083. nshots = cfg->default_max_shots;
  2084. }
  2085. if (one_shot) {
  2086. nshots = 1;
  2087. }
  2088. if (one_param) {
  2089. flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
  2090. }
  2091. if (flags_str) {
  2092. if (strstr (flags_str, "one_shot") != NULL) {
  2093. nshots = 1;
  2094. }
  2095. if (strstr (flags_str, "ignore") != NULL) {
  2096. flags |= RSPAMD_SYMBOL_FLAG_IGNORE_METRIC;
  2097. }
  2098. if (strstr (flags_str, "one_param") != NULL) {
  2099. flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
  2100. }
  2101. }
  2102. rspamd_config_add_symbol (cfg, name,
  2103. score, description, group, flags, (guint) priority, nshots);
  2104. if (lua_type (L, 2) == LUA_TTABLE) {
  2105. lua_pushstring (L, "groups");
  2106. lua_gettable (L, 2);
  2107. if (lua_istable (L, -1)) {
  2108. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  2109. if (lua_isstring (L, -1)) {
  2110. rspamd_config_add_symbol_group (cfg, name,
  2111. lua_tostring (L, -1));
  2112. } else {
  2113. return luaL_error (L, "invalid groups element");
  2114. }
  2115. }
  2116. }
  2117. lua_pop (L, 1);
  2118. }
  2119. }
  2120. else {
  2121. return luaL_error (L, "invalid arguments, rspamd_config expected");
  2122. }
  2123. return 0;
  2124. }
  2125. static gint
  2126. lua_config_get_metric_symbol (lua_State * L)
  2127. {
  2128. LUA_TRACE_POINT;
  2129. struct rspamd_config *cfg = lua_check_config (L, 1);
  2130. const gchar *sym_name = luaL_checkstring (L, 2);
  2131. struct rspamd_symbol *sym_def;
  2132. struct rspamd_symbols_group *sym_group;
  2133. guint i;
  2134. if (cfg && sym_name) {
  2135. sym_def = g_hash_table_lookup (cfg->symbols, sym_name);
  2136. if (sym_def == NULL) {
  2137. lua_pushnil (L);
  2138. }
  2139. else {
  2140. lua_createtable (L, 0, 3);
  2141. lua_pushstring (L, "score");
  2142. lua_pushnumber (L, sym_def->score);
  2143. lua_settable (L, -3);
  2144. if (sym_def->description) {
  2145. lua_pushstring (L, "description");
  2146. lua_pushstring (L, sym_def->description);
  2147. lua_settable (L, -3);
  2148. }
  2149. if (sym_def->gr) {
  2150. lua_pushstring (L, "group");
  2151. lua_pushstring (L, sym_def->gr->name);
  2152. lua_settable (L, -3);
  2153. }
  2154. lua_pushstring (L, "groups");
  2155. lua_createtable (L, sym_def->groups->len, 0);
  2156. PTR_ARRAY_FOREACH (sym_def->groups, i, sym_group) {
  2157. lua_pushstring (L, sym_group->name);
  2158. lua_rawseti (L, -2, i + 1);
  2159. }
  2160. lua_settable (L, -3);
  2161. }
  2162. }
  2163. else {
  2164. luaL_error (L, "Invalid arguments");
  2165. }
  2166. return 1;
  2167. }
  2168. static gint
  2169. lua_config_set_metric_action (lua_State * L)
  2170. {
  2171. LUA_TRACE_POINT;
  2172. struct rspamd_config *cfg = lua_check_config (L, 1);
  2173. const gchar *name = NULL;
  2174. double threshold = NAN;
  2175. GError *err = NULL;
  2176. gdouble priority = 0.0;
  2177. ucl_object_t *obj_tbl = NULL;
  2178. if (cfg) {
  2179. if (lua_type (L, 2) == LUA_TTABLE) {
  2180. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  2181. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  2182. "*action=S;score=N;"
  2183. "priority=N",
  2184. &name, &threshold,
  2185. &priority)) {
  2186. msg_err_config ("bad arguments: %e", err);
  2187. g_error_free (err);
  2188. return 0;
  2189. }
  2190. }
  2191. else if (lua_type (L, 2) == LUA_TSTRING && lua_type (L, 3) == LUA_TTABLE) {
  2192. name = lua_tostring (L, 2);
  2193. obj_tbl = ucl_object_lua_import (L, 3);
  2194. if (obj_tbl) {
  2195. if (name) {
  2196. rspamd_config_set_action_score (cfg, name, obj_tbl);
  2197. ucl_object_unref (obj_tbl);
  2198. }
  2199. else {
  2200. ucl_object_unref (obj_tbl);
  2201. return luaL_error (L, "invalid first argument, action name expected");
  2202. }
  2203. }
  2204. else {
  2205. return luaL_error (L, "invalid second argument, table expected");
  2206. }
  2207. }
  2208. else {
  2209. return luaL_error (L, "invalid arguments, table expected");
  2210. }
  2211. if (name != NULL && !isnan (threshold) && threshold != 0) {
  2212. obj_tbl = ucl_object_typed_new (UCL_OBJECT);
  2213. ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (threshold),
  2214. "score", 0, false);
  2215. ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (priority),
  2216. "priority", 0, false);
  2217. rspamd_config_set_action_score (cfg, name, obj_tbl);
  2218. ucl_object_unref (obj_tbl);
  2219. }
  2220. }
  2221. else {
  2222. return luaL_error (L, "invalid arguments, rspamd_config expected");
  2223. }
  2224. return 0;
  2225. }
  2226. static gint
  2227. lua_config_get_metric_action (lua_State * L)
  2228. {
  2229. LUA_TRACE_POINT;
  2230. struct rspamd_config *cfg = lua_check_config (L, 1);
  2231. const gchar *act_name = luaL_checkstring (L, 2);
  2232. struct rspamd_action *act;
  2233. if (cfg && act_name) {
  2234. act = rspamd_config_get_action (cfg, act_name);
  2235. if (act) {
  2236. if (!isnan (act->threshold)) {
  2237. lua_pushnumber (L, act->threshold);
  2238. }
  2239. else {
  2240. lua_pushnil (L);
  2241. }
  2242. }
  2243. else {
  2244. lua_pushnil (L);
  2245. }
  2246. }
  2247. else {
  2248. return luaL_error (L, "invalid arguments, rspamd_config expected");
  2249. }
  2250. return 1;
  2251. }
  2252. static gint
  2253. lua_config_get_all_actions (lua_State * L)
  2254. {
  2255. LUA_TRACE_POINT;
  2256. struct rspamd_config *cfg = lua_check_config (L, 1);
  2257. struct rspamd_action *act, *tmp;
  2258. if (cfg) {
  2259. lua_createtable (L, 0, HASH_COUNT (cfg->actions));
  2260. HASH_ITER (hh, cfg->actions, act, tmp) {
  2261. if (!isnan (act->threshold)) {
  2262. lua_pushstring (L, act->name);
  2263. lua_pushnumber (L, act->threshold);
  2264. lua_settable (L, -3);
  2265. }
  2266. }
  2267. }
  2268. else {
  2269. return luaL_error (L, "invalid arguments, rspamd_config expected");
  2270. }
  2271. return 1;
  2272. }
  2273. static gint
  2274. lua_config_add_composite (lua_State * L)
  2275. {
  2276. LUA_TRACE_POINT;
  2277. struct rspamd_config *cfg = lua_check_config (L, 1);
  2278. gchar *name;
  2279. const gchar *expr_str;
  2280. struct rspamd_composite *composite;
  2281. gboolean ret = FALSE;
  2282. if (cfg) {
  2283. name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
  2284. expr_str = luaL_checkstring (L, 3);
  2285. if (name && expr_str) {
  2286. composite = rspamd_composites_manager_add_from_string(cfg->composites_manager,
  2287. name, expr_str);
  2288. if (composite) {
  2289. rspamd_symcache_add_symbol (cfg->cache, name,
  2290. 0, NULL, composite, SYMBOL_TYPE_COMPOSITE, -1);
  2291. ret = TRUE;
  2292. }
  2293. }
  2294. }
  2295. lua_pushboolean (L, ret);
  2296. return 1;
  2297. }
  2298. static gint
  2299. lua_config_newindex (lua_State *L)
  2300. {
  2301. LUA_TRACE_POINT;
  2302. struct rspamd_config *cfg = lua_check_config (L, 1);
  2303. const gchar *name, *allowed_ids = NULL, *forbidden_ids = NULL;
  2304. gint id, nshots, flags = 0;
  2305. gboolean optional = FALSE;
  2306. name = luaL_checkstring (L, 2);
  2307. if (cfg != NULL && name != NULL && lua_gettop (L) == 3) {
  2308. if (lua_type (L, 3) == LUA_TFUNCTION) {
  2309. /* Normal symbol from just a function */
  2310. lua_pushvalue (L, 3);
  2311. rspamd_register_symbol_fromlua (L,
  2312. cfg,
  2313. name,
  2314. luaL_ref (L, LUA_REGISTRYINDEX),
  2315. 1.0,
  2316. 0,
  2317. SYMBOL_TYPE_NORMAL,
  2318. -1,
  2319. NULL, NULL,
  2320. FALSE);
  2321. }
  2322. else if (lua_type (L, 3) == LUA_TTABLE) {
  2323. gint type = SYMBOL_TYPE_NORMAL, priority = 0, idx;
  2324. gdouble weight = 1.0, score = NAN;
  2325. const char *type_str, *group = NULL, *description = NULL;
  2326. /*
  2327. * Table can have the following attributes:
  2328. * "callback" - should be a callback function
  2329. * "weight" - optional weight
  2330. * "priority" - optional priority
  2331. * "type" - optional type (normal, virtual, callback)
  2332. * "flags" - optional flags
  2333. * -- Metric options
  2334. * "score" - optional default score (overridden by metric)
  2335. * "group" - optional default group
  2336. * "one_shot" - optional one shot mode
  2337. * "description" - optional description
  2338. */
  2339. lua_pushvalue (L, 3);
  2340. lua_pushstring (L, "callback");
  2341. lua_gettable (L, -2);
  2342. if (lua_type (L, -1) != LUA_TFUNCTION) {
  2343. lua_pop (L, 2);
  2344. msg_info_config ("cannot find callback definition for %s",
  2345. name);
  2346. return 0;
  2347. }
  2348. idx = luaL_ref (L, LUA_REGISTRYINDEX);
  2349. /* Optional fields */
  2350. lua_pushstring (L, "weight");
  2351. lua_gettable (L, -2);
  2352. if (lua_type (L, -1) == LUA_TNUMBER) {
  2353. weight = lua_tonumber (L, -1);
  2354. }
  2355. lua_pop (L, 1);
  2356. lua_pushstring (L, "priority");
  2357. lua_gettable (L, -2);
  2358. if (lua_type (L, -1) == LUA_TNUMBER) {
  2359. priority = lua_tonumber (L, -1);
  2360. }
  2361. lua_pop (L, 1);
  2362. lua_pushstring (L, "optional");
  2363. lua_gettable (L, -2);
  2364. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2365. optional = lua_toboolean (L, -1);
  2366. }
  2367. lua_pop (L, 1);
  2368. lua_pushstring (L, "type");
  2369. lua_gettable (L, -2);
  2370. if (lua_type (L, -1) == LUA_TSTRING) {
  2371. type_str = lua_tostring (L, -1);
  2372. type = lua_parse_symbol_type (type_str);
  2373. }
  2374. lua_pop (L, 1);
  2375. lua_pushstring (L, "flags");
  2376. lua_gettable (L, -2);
  2377. if (lua_type (L, -1) == LUA_TSTRING) {
  2378. type_str = lua_tostring (L, -1);
  2379. type |= lua_parse_symbol_flags (type_str);
  2380. }
  2381. lua_pop (L, 1);
  2382. lua_pushstring (L, "allowed_ids");
  2383. lua_gettable (L, -2);
  2384. if (lua_type (L, -1) == LUA_TSTRING) {
  2385. allowed_ids = lua_tostring (L, -1);
  2386. }
  2387. lua_pop (L, 1);
  2388. lua_pushstring (L, "forbidden_ids");
  2389. lua_gettable (L, -2);
  2390. if (lua_type (L, -1) == LUA_TSTRING) {
  2391. forbidden_ids = lua_tostring (L, -1);
  2392. }
  2393. lua_pop (L, 1);
  2394. id = rspamd_register_symbol_fromlua (L,
  2395. cfg,
  2396. name,
  2397. idx,
  2398. weight,
  2399. priority,
  2400. type,
  2401. -1,
  2402. allowed_ids, forbidden_ids,
  2403. optional);
  2404. if (id != -1) {
  2405. /* Check for condition */
  2406. lua_pushstring (L, "condition");
  2407. lua_gettable (L, -2);
  2408. if (lua_type (L, -1) == LUA_TFUNCTION) {
  2409. gint condref;
  2410. /* Here we pop function from the stack, so no lua_pop is required */
  2411. condref = luaL_ref (L, LUA_REGISTRYINDEX);
  2412. g_assert (name != NULL);
  2413. rspamd_symcache_add_condition_delayed (cfg->cache,
  2414. name, L, condref);
  2415. }
  2416. else {
  2417. lua_pop (L, 1);
  2418. }
  2419. }
  2420. /*
  2421. * Now check if a symbol has not been registered in any metric and
  2422. * insert default value if applicable
  2423. */
  2424. struct rspamd_symbol *sym = g_hash_table_lookup (cfg->symbols, name);
  2425. if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
  2426. nshots = cfg->default_max_shots;
  2427. lua_pushstring (L, "score");
  2428. lua_gettable (L, -2);
  2429. if (lua_type (L, -1) == LUA_TNUMBER) {
  2430. score = lua_tonumber (L, -1);
  2431. if (sym) {
  2432. /* Reset unscored flag */
  2433. sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
  2434. }
  2435. }
  2436. lua_pop (L, 1);
  2437. lua_pushstring (L, "group");
  2438. lua_gettable (L, -2);
  2439. if (lua_type (L, -1) == LUA_TSTRING) {
  2440. group = lua_tostring (L, -1);
  2441. }
  2442. lua_pop (L, 1);
  2443. if (!isnan (score) || group != NULL) {
  2444. lua_pushstring (L, "description");
  2445. lua_gettable (L, -2);
  2446. if (lua_type (L, -1) == LUA_TSTRING) {
  2447. description = lua_tostring (L, -1);
  2448. }
  2449. lua_pop (L, 1);
  2450. lua_pushstring (L, "one_shot");
  2451. lua_gettable (L, -2);
  2452. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2453. if (lua_toboolean (L, -1)) {
  2454. nshots = 1;
  2455. }
  2456. }
  2457. lua_pop (L, 1);
  2458. lua_pushstring (L, "one_param");
  2459. lua_gettable (L, -2);
  2460. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2461. if (lua_toboolean (L, -1)) {
  2462. flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
  2463. }
  2464. }
  2465. lua_pop (L, 1);
  2466. /*
  2467. * Do not override the existing symbols (using zero priority),
  2468. * since we are defining default values here
  2469. */
  2470. if (!isnan (score)) {
  2471. rspamd_config_add_symbol (cfg, name, score,
  2472. description, group, flags, 0, nshots);
  2473. }
  2474. else if (group) {
  2475. /* Add with zero score */
  2476. rspamd_config_add_symbol (cfg, name, NAN,
  2477. description, group, flags, 0, nshots);
  2478. }
  2479. lua_pushstring (L, "groups");
  2480. lua_gettable (L, -2);
  2481. if (lua_istable (L, -1)) {
  2482. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  2483. if (lua_isstring (L, -1)) {
  2484. rspamd_config_add_symbol_group (cfg, name,
  2485. lua_tostring (L, -1));
  2486. }
  2487. else {
  2488. return luaL_error (L, "invalid groups element");
  2489. }
  2490. }
  2491. }
  2492. lua_pop (L, 1);
  2493. }
  2494. }
  2495. /* Remove table from stack */
  2496. lua_pop (L, 1);
  2497. }
  2498. }
  2499. else {
  2500. return luaL_error (L, "invalid arguments");
  2501. }
  2502. return 0;
  2503. }
  2504. static gint
  2505. lua_config_add_condition (lua_State *L)
  2506. {
  2507. LUA_TRACE_POINT;
  2508. struct rspamd_config *cfg = lua_check_config (L, 1);
  2509. const gchar *sym = luaL_checkstring (L, 2);
  2510. gboolean ret = FALSE;
  2511. gint condref;
  2512. if (cfg && sym && lua_type (L, 3) == LUA_TFUNCTION) {
  2513. lua_pushvalue (L, 3);
  2514. condref = luaL_ref (L, LUA_REGISTRYINDEX);
  2515. ret = rspamd_symcache_add_condition_delayed (cfg->cache, sym, L,
  2516. condref);
  2517. if (!ret) {
  2518. luaL_unref (L, LUA_REGISTRYINDEX, condref);
  2519. }
  2520. }
  2521. lua_pushboolean (L, ret);
  2522. return 1;
  2523. }
  2524. static gint
  2525. lua_config_set_peak_cb (lua_State *L)
  2526. {
  2527. LUA_TRACE_POINT;
  2528. struct rspamd_config *cfg = lua_check_config (L, 1);
  2529. gint condref;
  2530. if (cfg && lua_type (L, 2) == LUA_TFUNCTION) {
  2531. lua_pushvalue (L, 2);
  2532. condref = luaL_ref (L, LUA_REGISTRYINDEX);
  2533. rspamd_symcache_set_peak_callback (cfg->cache,
  2534. condref);
  2535. }
  2536. return 0;
  2537. }
  2538. static gint
  2539. lua_config_enable_symbol (lua_State *L)
  2540. {
  2541. LUA_TRACE_POINT;
  2542. struct rspamd_config *cfg = lua_check_config (L, 1);
  2543. const gchar *sym = luaL_checkstring (L, 2);
  2544. if (cfg && sym) {
  2545. rspamd_symcache_enable_symbol_perm (cfg->cache, sym);
  2546. }
  2547. else {
  2548. return luaL_error (L, "invalid arguments");
  2549. }
  2550. return 0;
  2551. }
  2552. static gint
  2553. lua_config_disable_symbol (lua_State *L)
  2554. {
  2555. LUA_TRACE_POINT;
  2556. struct rspamd_config *cfg = lua_check_config (L, 1);
  2557. const gchar *sym = luaL_checkstring (L, 2);
  2558. gboolean disable_parent = TRUE;
  2559. if (cfg && sym) {
  2560. if (lua_isboolean (L, 3)) {
  2561. disable_parent = lua_toboolean (L, 3);
  2562. }
  2563. rspamd_symcache_disable_symbol_perm (cfg->cache, sym, disable_parent);
  2564. }
  2565. else {
  2566. return luaL_error (L, "invalid arguments");
  2567. }
  2568. return 0;
  2569. }
  2570. static gint
  2571. lua_config_register_regexp (lua_State *L)
  2572. {
  2573. LUA_TRACE_POINT;
  2574. struct rspamd_config *cfg = lua_check_config (L, 1);
  2575. struct rspamd_lua_regexp *re = NULL;
  2576. rspamd_regexp_t *cache_re;
  2577. const gchar *type_str = NULL, *header_str = NULL;
  2578. gsize header_len = 0;
  2579. GError *err = NULL;
  2580. enum rspamd_re_type type = RSPAMD_RE_BODY;
  2581. gboolean pcre_only = FALSE;
  2582. /*
  2583. * - `re`* : regular expression object
  2584. * - `type`*: type of regular expression:
  2585. * + `mime`: mime regexp
  2586. * + `rawmime`: raw mime regexp
  2587. * + `header`: header regexp
  2588. * + `rawheader`: raw header expression
  2589. * + `body`: raw body regexp
  2590. * + `url`: url regexp
  2591. * - `header`: for header and rawheader regexp means the name of header
  2592. * - `pcre_only`: allow merely pcre for this regexp
  2593. */
  2594. if (cfg != NULL) {
  2595. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  2596. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  2597. "*re=U{regexp};*type=S;header=S;pcre_only=B",
  2598. &re, &type_str, &header_str, &pcre_only)) {
  2599. msg_err_config ("cannot get parameters list: %e", err);
  2600. if (err) {
  2601. g_error_free (err);
  2602. }
  2603. }
  2604. else {
  2605. type = rspamd_re_cache_type_from_string (type_str);
  2606. if ((type == RSPAMD_RE_HEADER ||
  2607. type == RSPAMD_RE_RAWHEADER ||
  2608. type == RSPAMD_RE_MIMEHEADER) &&
  2609. header_str == NULL) {
  2610. msg_err_config (
  2611. "header argument is mandatory for header/rawheader regexps");
  2612. }
  2613. else {
  2614. if (pcre_only) {
  2615. rspamd_regexp_set_flags (re->re,
  2616. rspamd_regexp_get_flags (re->re) | RSPAMD_REGEXP_FLAG_PCRE_ONLY);
  2617. }
  2618. if (header_str != NULL) {
  2619. /* Include the last \0 */
  2620. header_len = strlen (header_str) + 1;
  2621. }
  2622. cache_re = rspamd_re_cache_add (cfg->re_cache, re->re, type,
  2623. (gpointer) header_str, header_len, -1);
  2624. /*
  2625. * XXX: here are dragons!
  2626. * Actually, lua regexp contains internal rspamd_regexp_t
  2627. * and it owns it.
  2628. * However, after this operation we have some OTHER regexp,
  2629. * which we really would like to use.
  2630. * So we do the following:
  2631. * 1) Remove old re and unref it
  2632. * 2) Replace the internal re with cached one
  2633. * 3) Increase its refcount to share ownership between cache and
  2634. * lua object
  2635. */
  2636. if (cache_re != re->re) {
  2637. rspamd_regexp_unref (re->re);
  2638. re->re = rspamd_regexp_ref (cache_re);
  2639. if (pcre_only) {
  2640. rspamd_regexp_set_flags (re->re,
  2641. rspamd_regexp_get_flags (re->re) | RSPAMD_REGEXP_FLAG_PCRE_ONLY);
  2642. }
  2643. }
  2644. }
  2645. }
  2646. }
  2647. return 0;
  2648. }
  2649. static gint
  2650. lua_config_replace_regexp (lua_State *L)
  2651. {
  2652. LUA_TRACE_POINT;
  2653. struct rspamd_config *cfg = lua_check_config (L, 1);
  2654. struct rspamd_lua_regexp *old_re = NULL, *new_re = NULL;
  2655. gboolean pcre_only = FALSE;
  2656. GError *err = NULL;
  2657. if (cfg != NULL) {
  2658. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  2659. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  2660. "*old_re=U{regexp};*new_re=U{regexp};pcre_only=B",
  2661. &old_re, &new_re, &pcre_only)) {
  2662. gint ret = luaL_error (L, "cannot get parameters list: %s",
  2663. err ? err->message : "invalid arguments");
  2664. if (err) {
  2665. g_error_free (err);
  2666. }
  2667. return ret;
  2668. }
  2669. else {
  2670. if (pcre_only) {
  2671. rspamd_regexp_set_flags (new_re->re,
  2672. rspamd_regexp_get_flags (new_re->re) | RSPAMD_REGEXP_FLAG_PCRE_ONLY);
  2673. }
  2674. rspamd_re_cache_replace (cfg->re_cache, old_re->re, new_re->re);
  2675. }
  2676. }
  2677. return 0;
  2678. }
  2679. static gint
  2680. lua_config_register_worker_script (lua_State *L)
  2681. {
  2682. LUA_TRACE_POINT;
  2683. struct rspamd_config *cfg = lua_check_config (L, 1);
  2684. const gchar *worker_type = luaL_checkstring (L, 2), *wtype;
  2685. struct rspamd_worker_conf *cf;
  2686. GList *cur;
  2687. struct rspamd_worker_lua_script *sc;
  2688. gboolean found = FALSE;
  2689. if (cfg == NULL || worker_type == NULL || lua_type (L, 3) != LUA_TFUNCTION) {
  2690. return luaL_error (L, "invalid arguments");
  2691. }
  2692. for (cur = g_list_first (cfg->workers); cur != NULL; cur = g_list_next (cur)) {
  2693. cf = cur->data;
  2694. wtype = g_quark_to_string (cf->type);
  2695. if (g_ascii_strcasecmp (wtype, worker_type) == 0) {
  2696. sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
  2697. lua_pushvalue (L, 3);
  2698. sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  2699. DL_APPEND (cf->scripts, sc);
  2700. found = TRUE;
  2701. }
  2702. }
  2703. lua_pushboolean (L, found);
  2704. return 1;
  2705. }
  2706. static gint
  2707. lua_config_add_on_load (lua_State *L)
  2708. {
  2709. LUA_TRACE_POINT;
  2710. struct rspamd_config *cfg = lua_check_config (L, 1);
  2711. struct rspamd_config_cfg_lua_script *sc;
  2712. if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
  2713. return luaL_error (L, "invalid arguments");
  2714. }
  2715. sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
  2716. lua_pushvalue (L, 2);
  2717. sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  2718. DL_APPEND (cfg->on_load_scripts, sc);
  2719. return 0;
  2720. }
  2721. static inline int
  2722. rspamd_post_init_sc_sort (const struct rspamd_config_cfg_lua_script *pra,
  2723. const struct rspamd_config_cfg_lua_script *prb)
  2724. {
  2725. /* Inverse sort */
  2726. return prb->priority - pra->priority;
  2727. }
  2728. static gint
  2729. lua_config_add_post_init (lua_State *L)
  2730. {
  2731. LUA_TRACE_POINT;
  2732. struct rspamd_config *cfg = lua_check_config (L, 1);
  2733. struct rspamd_config_cfg_lua_script *sc;
  2734. guint priority = 0;
  2735. lua_Debug d;
  2736. gchar tmp[256], *p;
  2737. if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
  2738. return luaL_error (L, "invalid arguments");
  2739. }
  2740. if (lua_type (L, 3) == LUA_TNUMBER) {
  2741. priority = lua_tointeger (L , 3);
  2742. }
  2743. if (lua_getstack (L, 1, &d) == 1) {
  2744. (void) lua_getinfo (L, "Sl", &d);
  2745. if ((p = strrchr (d.short_src, '/')) == NULL) {
  2746. p = d.short_src;
  2747. }
  2748. else {
  2749. p++;
  2750. }
  2751. if (strlen (p) > 200) {
  2752. rspamd_snprintf (tmp, sizeof (tmp), "%10s...]:%d", p,
  2753. d.currentline);
  2754. }
  2755. else {
  2756. rspamd_snprintf (tmp, sizeof (tmp), "%s:%d", p,
  2757. d.currentline);
  2758. }
  2759. }
  2760. sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
  2761. lua_pushvalue (L, 2);
  2762. sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  2763. sc->priority = priority;
  2764. sc->lua_src_pos = rspamd_mempool_strdup (cfg->cfg_pool, tmp);
  2765. DL_APPEND (cfg->post_init_scripts, sc);
  2766. DL_SORT (cfg->post_init_scripts, rspamd_post_init_sc_sort);
  2767. return 0;
  2768. }
  2769. static gint
  2770. lua_config_add_config_unload (lua_State *L)
  2771. {
  2772. LUA_TRACE_POINT;
  2773. struct rspamd_config *cfg = lua_check_config (L, 1);
  2774. struct rspamd_config_cfg_lua_script *sc;
  2775. lua_Debug d;
  2776. gchar tmp[256], *p;
  2777. if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
  2778. return luaL_error (L, "invalid arguments");
  2779. }
  2780. if (lua_getstack (L, 1, &d) == 1) {
  2781. (void) lua_getinfo (L, "Sl", &d);
  2782. if ((p = strrchr (d.short_src, '/')) == NULL) {
  2783. p = d.short_src;
  2784. }
  2785. else {
  2786. p++;
  2787. }
  2788. if (strlen (p) > 20) {
  2789. rspamd_snprintf (tmp, sizeof (tmp), "%10s...]:%d", p,
  2790. d.currentline);
  2791. }
  2792. else {
  2793. rspamd_snprintf (tmp, sizeof (tmp), "%s:%d", p,
  2794. d.currentline);
  2795. }
  2796. }
  2797. sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
  2798. lua_pushvalue (L, 2);
  2799. sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  2800. sc->lua_src_pos = rspamd_mempool_strdup (cfg->cfg_pool, tmp);
  2801. DL_APPEND (cfg->config_unload_scripts, sc);
  2802. return 0;
  2803. }
  2804. static void lua_periodic_callback_finish (struct thread_entry *thread, int ret);
  2805. static void lua_periodic_callback_error (struct thread_entry *thread, int ret, const char *msg);
  2806. struct rspamd_lua_periodic {
  2807. struct ev_loop *event_loop;
  2808. struct rspamd_config *cfg;
  2809. gchar *lua_src_pos;
  2810. lua_State *L;
  2811. gdouble timeout;
  2812. ev_timer ev;
  2813. gint cbref;
  2814. gboolean need_jitter;
  2815. ref_entry_t ref;
  2816. };
  2817. static void
  2818. lua_periodic_dtor (struct rspamd_lua_periodic *periodic)
  2819. {
  2820. luaL_unref (periodic->L, LUA_REGISTRYINDEX, periodic->cbref);
  2821. ev_timer_stop (periodic->event_loop, &periodic->ev);
  2822. }
  2823. static void
  2824. lua_periodic_fin (gpointer p)
  2825. {
  2826. struct rspamd_lua_periodic *periodic = (struct rspamd_lua_periodic *)p;
  2827. REF_RELEASE (periodic);
  2828. }
  2829. static void
  2830. lua_periodic_callback (struct ev_loop *loop, ev_timer *w, int revents)
  2831. {
  2832. struct rspamd_lua_periodic *periodic = (struct rspamd_lua_periodic *)w->data;
  2833. struct rspamd_config **pcfg, *cfg;
  2834. struct ev_loop **pev_base;
  2835. struct thread_entry *thread;
  2836. lua_State *L;
  2837. REF_RETAIN (periodic);
  2838. thread = lua_thread_pool_get_for_config (periodic->cfg);
  2839. thread->cd = periodic;
  2840. thread->finish_callback = lua_periodic_callback_finish;
  2841. thread->error_callback = lua_periodic_callback_error;
  2842. L = thread->lua_state;
  2843. lua_rawgeti (L, LUA_REGISTRYINDEX, periodic->cbref);
  2844. pcfg = lua_newuserdata (L, sizeof (*pcfg));
  2845. rspamd_lua_setclass (L, "rspamd{config}", -1);
  2846. cfg = periodic->cfg;
  2847. *pcfg = cfg;
  2848. pev_base = lua_newuserdata (L, sizeof (*pev_base));
  2849. rspamd_lua_setclass (L, "rspamd{ev_base}", -1);
  2850. *pev_base = periodic->event_loop;
  2851. lua_pushnumber (L, ev_now (periodic->event_loop));
  2852. lua_thread_call (thread, 3);
  2853. }
  2854. static void
  2855. lua_periodic_callback_finish (struct thread_entry *thread, int ret)
  2856. {
  2857. lua_State *L;
  2858. struct rspamd_lua_periodic *periodic = thread->cd;
  2859. gboolean plan_more = FALSE;
  2860. gdouble timeout = 0.0;
  2861. L = thread->lua_state;
  2862. ev_now_update (periodic->event_loop);
  2863. if (ret == 0) {
  2864. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2865. plan_more = lua_toboolean (L, -1);
  2866. timeout = periodic->timeout;
  2867. }
  2868. else if (lua_type (L, -1) == LUA_TNUMBER) {
  2869. timeout = lua_tonumber (L, -1);
  2870. plan_more = timeout > 0 ? TRUE : FALSE;
  2871. }
  2872. lua_pop (L, 1); /* Return value */
  2873. }
  2874. if (periodic->cfg->cur_worker) {
  2875. if (periodic->cfg->cur_worker->state != rspamd_worker_state_running) {
  2876. /* We are terminating, no more periodics */
  2877. plan_more = FALSE;
  2878. }
  2879. }
  2880. if (plan_more) {
  2881. if (periodic->need_jitter) {
  2882. timeout = rspamd_time_jitter (timeout, 0.0);
  2883. }
  2884. periodic->ev.repeat = timeout;
  2885. ev_timer_again (periodic->event_loop, &periodic->ev);
  2886. }
  2887. else {
  2888. ev_timer_stop (periodic->event_loop, &periodic->ev);
  2889. }
  2890. REF_RELEASE (periodic);
  2891. }
  2892. static void
  2893. lua_periodic_callback_error (struct thread_entry *thread, int ret, const char *msg)
  2894. {
  2895. struct rspamd_config *cfg;
  2896. struct rspamd_lua_periodic *periodic = thread->cd;
  2897. cfg = periodic->cfg;
  2898. msg_err_config ("call to periodic script (registered at %s) failed: %s",
  2899. periodic->lua_src_pos, msg);
  2900. lua_periodic_callback_finish (thread, ret);
  2901. }
  2902. static gint
  2903. lua_config_add_periodic (lua_State *L)
  2904. {
  2905. LUA_TRACE_POINT;
  2906. struct rspamd_config *cfg = lua_check_config (L, 1);
  2907. struct ev_loop *ev_base = lua_check_ev_base (L, 2);
  2908. gdouble timeout = lua_tonumber (L, 3);
  2909. struct rspamd_lua_periodic *periodic;
  2910. gboolean need_jitter = FALSE;
  2911. lua_Debug d;
  2912. gchar tmp[256], *p;
  2913. if (cfg == NULL || timeout < 0 || lua_type (L, 4) != LUA_TFUNCTION) {
  2914. return luaL_error (L, "invalid arguments");
  2915. }
  2916. if (lua_type (L, 5) == LUA_TBOOLEAN) {
  2917. need_jitter = lua_toboolean (L, 5);
  2918. }
  2919. if (lua_getstack (L, 1, &d) == 1) {
  2920. (void) lua_getinfo (L, "Sl", &d);
  2921. if ((p = strrchr (d.short_src, '/')) == NULL) {
  2922. p = d.short_src;
  2923. }
  2924. else {
  2925. p++;
  2926. }
  2927. if (strlen (p) > 20) {
  2928. rspamd_snprintf (tmp, sizeof (tmp), "%10s...]:%d", p,
  2929. d.currentline);
  2930. }
  2931. else {
  2932. rspamd_snprintf (tmp, sizeof (tmp), "%s:%d", p,
  2933. d.currentline);
  2934. }
  2935. }
  2936. periodic = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*periodic));
  2937. periodic->timeout = timeout;
  2938. periodic->L = L;
  2939. periodic->cfg = cfg;
  2940. periodic->event_loop = ev_base;
  2941. periodic->need_jitter = need_jitter;
  2942. periodic->lua_src_pos = rspamd_mempool_strdup (cfg->cfg_pool, tmp);
  2943. lua_pushvalue (L, 4);
  2944. periodic->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  2945. if (need_jitter) {
  2946. timeout = rspamd_time_jitter (timeout, 0.0);
  2947. }
  2948. ev_timer_init (&periodic->ev, lua_periodic_callback, timeout, 0.0);
  2949. periodic->ev.data = periodic;
  2950. ev_timer_start (ev_base, &periodic->ev);
  2951. REF_INIT_RETAIN (periodic, lua_periodic_dtor);
  2952. rspamd_mempool_add_destructor (cfg->cfg_pool, lua_periodic_fin,
  2953. periodic);
  2954. return 0;
  2955. }
  2956. static gint
  2957. lua_config_get_symbols_count (lua_State *L)
  2958. {
  2959. LUA_TRACE_POINT;
  2960. struct rspamd_config *cfg = lua_check_config (L, 1);
  2961. guint res = 0;
  2962. if (cfg != NULL) {
  2963. res = rspamd_symcache_stats_symbols_count (cfg->cache);
  2964. }
  2965. else {
  2966. return luaL_error (L, "invalid arguments");
  2967. }
  2968. lua_pushinteger (L, res);
  2969. return 1;
  2970. }
  2971. static gint
  2972. lua_config_get_symbols_cksum (lua_State *L)
  2973. {
  2974. LUA_TRACE_POINT;
  2975. struct rspamd_config *cfg = lua_check_config (L, 1);
  2976. guint64 res = 0, *pres;
  2977. if (cfg != NULL) {
  2978. res = rspamd_symcache_get_cksum (cfg->cache);
  2979. }
  2980. else {
  2981. return luaL_error (L, "invalid arguments");
  2982. }
  2983. pres = lua_newuserdata (L, sizeof (res));
  2984. *pres = res;
  2985. rspamd_lua_setclass (L, "rspamd{int64}", -1);
  2986. return 1;
  2987. }
  2988. static gint
  2989. lua_config_get_symbols_counters (lua_State *L)
  2990. {
  2991. LUA_TRACE_POINT;
  2992. struct rspamd_config *cfg = lua_check_config (L, 1);
  2993. ucl_object_t *counters;
  2994. if (cfg != NULL) {
  2995. counters = rspamd_symcache_counters (cfg->cache);
  2996. ucl_object_push_lua (L, counters, true);
  2997. ucl_object_unref (counters);
  2998. }
  2999. else {
  3000. return luaL_error (L, "invalid arguments");
  3001. }
  3002. return 1;
  3003. }
  3004. struct lua_metric_symbols_cbdata {
  3005. lua_State *L;
  3006. struct rspamd_config *cfg;
  3007. };
  3008. static void
  3009. lua_metric_symbol_inserter (gpointer k, gpointer v, gpointer ud)
  3010. {
  3011. struct lua_metric_symbols_cbdata *cbd = (struct lua_metric_symbols_cbdata *)ud;
  3012. lua_State *L;
  3013. const gchar *sym = k;
  3014. struct rspamd_symbol *s = (struct rspamd_symbol *) v;
  3015. struct rspamd_symbols_group *gr;
  3016. gint i;
  3017. L = cbd->L;
  3018. lua_pushstring (L, sym); /* Symbol name */
  3019. lua_createtable (L, 0, 6);
  3020. lua_pushstring (L, "score");
  3021. lua_pushnumber (L, s->score);
  3022. lua_settable (L, -3);
  3023. lua_pushstring (L, "description");
  3024. lua_pushstring (L, s->description);
  3025. lua_settable (L, -3);
  3026. lua_pushstring (L, "flags");
  3027. lua_createtable (L, 0, 3);
  3028. if (s->flags & RSPAMD_SYMBOL_FLAG_IGNORE_METRIC) {
  3029. lua_pushstring (L, "ignore");
  3030. lua_pushboolean (L, true);
  3031. lua_settable (L, -3);
  3032. }
  3033. if (s->flags & RSPAMD_SYMBOL_FLAG_ONEPARAM) {
  3034. lua_pushstring (L, "oneparam");
  3035. lua_pushboolean (L, true);
  3036. lua_settable (L, -3);
  3037. }
  3038. if (s->flags & RSPAMD_SYMBOL_FLAG_UNGROUPPED) {
  3039. lua_pushstring (L, "ungroupped");
  3040. lua_pushboolean (L, true);
  3041. lua_settable (L, -3);
  3042. }
  3043. if (s->flags & RSPAMD_SYMBOL_FLAG_DISABLED) {
  3044. lua_pushstring (L, "disabled");
  3045. lua_pushboolean (L, true);
  3046. lua_settable (L, -3);
  3047. }
  3048. if (s->cache_item) {
  3049. guint sflags = rspamd_symcache_get_symbol_flags (cbd->cfg->cache, sym);
  3050. lua_push_symbol_flags (L, sflags, LUA_SYMOPT_FLAG_USE_MAP);
  3051. guint nids;
  3052. const guint *allowed_ids = rspamd_symcache_get_allowed_settings_ids (cbd->cfg->cache,
  3053. sym, &nids);
  3054. if (allowed_ids && nids > 0) {
  3055. lua_createtable (L, nids, 0);
  3056. for (i = 0; i < nids; i ++) {
  3057. lua_pushinteger (L, allowed_ids[i]);
  3058. lua_rawseti (L, -2, i + 1);
  3059. }
  3060. lua_setfield (L, -2, "allowed_ids");
  3061. }
  3062. const guint *forbidden_ids = rspamd_symcache_get_forbidden_settings_ids (
  3063. cbd->cfg->cache,
  3064. sym, &nids);
  3065. if (forbidden_ids && nids > 0) {
  3066. lua_createtable (L, nids, 0);
  3067. for (i = 0; i < nids; i ++) {
  3068. lua_pushinteger (L, forbidden_ids[i]);
  3069. lua_rawseti (L, -2, i + 1);
  3070. }
  3071. lua_setfield (L, -2, "forbidden_ids");
  3072. }
  3073. }
  3074. lua_settable (L, -3); /* Flags -> flags_table */
  3075. lua_pushstring (L, "nshots");
  3076. lua_pushinteger (L, s->nshots);
  3077. lua_settable (L, -3);
  3078. if (s->gr) {
  3079. lua_pushstring (L, "group");
  3080. lua_pushstring (L, s->gr->name);
  3081. lua_settable (L, -3);
  3082. }
  3083. if (s->groups && s->groups->len > 0) {
  3084. lua_pushstring (L, "groups");
  3085. lua_createtable (L, s->groups->len, 0);
  3086. PTR_ARRAY_FOREACH (s->groups, i, gr) {
  3087. lua_pushstring (L, gr->name);
  3088. lua_rawseti (L, -2, i + 1); /* Groups[i + 1] = group_name */
  3089. }
  3090. lua_settable (L, -3); /* Groups -> groups_table */
  3091. }
  3092. else {
  3093. lua_createtable (L, 0, 0);
  3094. lua_setfield (L, -2, "groups");
  3095. }
  3096. lua_settable (L, -3); /* Symname -> table */
  3097. }
  3098. static gint
  3099. lua_config_get_symbols (lua_State *L)
  3100. {
  3101. LUA_TRACE_POINT;
  3102. struct rspamd_config *cfg = lua_check_config (L, 1);
  3103. if (cfg != NULL) {
  3104. struct lua_metric_symbols_cbdata cbd;
  3105. cbd.L = L;
  3106. cbd.cfg = cfg;
  3107. lua_createtable (L, 0, g_hash_table_size (cfg->symbols));
  3108. g_hash_table_foreach (cfg->symbols,
  3109. lua_metric_symbol_inserter,
  3110. &cbd);
  3111. }
  3112. else {
  3113. return luaL_error (L, "invalid arguments");
  3114. }
  3115. return 1;
  3116. }
  3117. static gint
  3118. lua_config_get_symbol_callback (lua_State *L)
  3119. {
  3120. LUA_TRACE_POINT;
  3121. struct rspamd_config *cfg = lua_check_config (L, 1);
  3122. const gchar *sym = luaL_checkstring (L, 2);
  3123. struct rspamd_abstract_callback_data *abs_cbdata;
  3124. struct lua_callback_data *cbd;
  3125. if (cfg != NULL && sym != NULL) {
  3126. abs_cbdata = rspamd_symcache_get_cbdata (cfg->cache, sym);
  3127. if (abs_cbdata == NULL || abs_cbdata->magic != rspamd_lua_callback_magic) {
  3128. lua_pushnil (L);
  3129. }
  3130. else {
  3131. cbd = (struct lua_callback_data *)abs_cbdata;
  3132. if (cbd->cb_is_ref) {
  3133. lua_rawgeti (L, LUA_REGISTRYINDEX, cbd->callback.ref);
  3134. }
  3135. else {
  3136. lua_getglobal (L, cbd->callback.name);
  3137. }
  3138. }
  3139. }
  3140. else {
  3141. return luaL_error (L, "invalid arguments");
  3142. }
  3143. return 1;
  3144. }
  3145. static gint
  3146. lua_config_set_symbol_callback (lua_State *L)
  3147. {
  3148. LUA_TRACE_POINT;
  3149. struct rspamd_config *cfg = lua_check_config (L, 1);
  3150. const gchar *sym = luaL_checkstring (L, 2);
  3151. struct rspamd_abstract_callback_data *abs_cbdata;
  3152. struct lua_callback_data *cbd;
  3153. if (cfg != NULL && sym != NULL && lua_type (L, 3) == LUA_TFUNCTION) {
  3154. abs_cbdata = rspamd_symcache_get_cbdata (cfg->cache, sym);
  3155. if (abs_cbdata == NULL || abs_cbdata->magic != rspamd_lua_callback_magic) {
  3156. lua_pushboolean (L, FALSE);
  3157. }
  3158. else {
  3159. cbd = (struct lua_callback_data *)abs_cbdata;
  3160. if (cbd->cb_is_ref) {
  3161. luaL_unref (L, LUA_REGISTRYINDEX, cbd->callback.ref);
  3162. }
  3163. else {
  3164. cbd->cb_is_ref = TRUE;
  3165. }
  3166. lua_pushvalue (L, 3);
  3167. cbd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX);
  3168. lua_pushboolean (L, TRUE);
  3169. }
  3170. }
  3171. else {
  3172. return luaL_error (L, "invalid arguments");
  3173. }
  3174. return 1;
  3175. }
  3176. static gint
  3177. lua_config_get_symbol_stat (lua_State *L)
  3178. {
  3179. LUA_TRACE_POINT;
  3180. struct rspamd_config *cfg = lua_check_config (L, 1);
  3181. const gchar *sym = luaL_checkstring (L, 2);
  3182. gdouble freq, stddev, tm;
  3183. guint hits;
  3184. if (cfg != NULL && sym != NULL) {
  3185. if (!rspamd_symcache_stat_symbol (cfg->cache, sym, &freq,
  3186. &stddev, &tm, &hits)) {
  3187. lua_pushnil (L);
  3188. }
  3189. else {
  3190. lua_createtable (L, 0, 4);
  3191. lua_pushstring (L, "frequency");
  3192. lua_pushnumber (L, freq);
  3193. lua_settable (L, -3);
  3194. lua_pushstring (L, "sttdev");
  3195. lua_pushnumber (L, stddev);
  3196. lua_settable (L, -3);
  3197. lua_pushstring (L, "time");
  3198. lua_pushnumber (L, tm);
  3199. lua_settable (L, -3);
  3200. lua_pushstring (L, "hits");
  3201. lua_pushinteger (L, hits);
  3202. lua_settable (L, -3);
  3203. }
  3204. }
  3205. else {
  3206. return luaL_error (L, "invalid arguments");
  3207. }
  3208. return 1;
  3209. }
  3210. static gint
  3211. lua_config_get_symbol_parent (lua_State *L)
  3212. {
  3213. LUA_TRACE_POINT;
  3214. struct rspamd_config *cfg = lua_check_config (L, 1);
  3215. const gchar *sym = luaL_checkstring (L, 2), *parent;
  3216. if (cfg != NULL && sym != NULL) {
  3217. parent = rspamd_symcache_get_parent (cfg->cache, sym);
  3218. if (parent) {
  3219. lua_pushstring (L, parent);
  3220. }
  3221. else {
  3222. lua_pushnil (L);
  3223. }
  3224. }
  3225. else {
  3226. return luaL_error (L, "invalid arguments");
  3227. }
  3228. return 1;
  3229. }
  3230. static gint
  3231. lua_config_get_group_symbols (lua_State *L)
  3232. {
  3233. LUA_TRACE_POINT;
  3234. struct rspamd_config *cfg = lua_check_config (L, 1);
  3235. const gchar *gr_name = luaL_checkstring (L, 2);
  3236. if (cfg != NULL && gr_name != NULL) {
  3237. struct rspamd_symbols_group *group;
  3238. group = g_hash_table_lookup (cfg->groups, gr_name);
  3239. if (group == NULL) {
  3240. lua_pushnil (L);
  3241. }
  3242. else {
  3243. guint i = 1;
  3244. gpointer k, v;
  3245. GHashTableIter it;
  3246. lua_createtable (L, g_hash_table_size (group->symbols), 0);
  3247. g_hash_table_iter_init (&it, group->symbols);
  3248. while (g_hash_table_iter_next (&it, &k, &v)) {
  3249. lua_pushstring (L, k);
  3250. lua_rawseti (L, -2, i);
  3251. i ++;
  3252. }
  3253. }
  3254. }
  3255. else {
  3256. return luaL_error (L, "invalid arguments");
  3257. }
  3258. return 1;
  3259. }
  3260. static gint
  3261. lua_config_get_groups (lua_State *L)
  3262. {
  3263. LUA_TRACE_POINT;
  3264. struct rspamd_config *cfg = lua_check_config (L, 1);
  3265. gboolean need_private;
  3266. struct rspamd_symbols_group *gr;
  3267. GHashTableIter it;
  3268. gpointer k, v;
  3269. if (cfg) {
  3270. if (lua_isboolean (L, 2)) {
  3271. need_private = lua_toboolean (L, 2);
  3272. }
  3273. else {
  3274. need_private = !(cfg->public_groups_only);
  3275. }
  3276. lua_createtable (L, 0, g_hash_table_size (cfg->groups));
  3277. g_hash_table_iter_init (&it, cfg->groups);
  3278. while (g_hash_table_iter_next (&it, &k, &v)) {
  3279. gr = (struct rspamd_symbols_group *)v;
  3280. if (need_private || (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC)) {
  3281. lua_createtable (L, 0, 4);
  3282. lua_pushstring (L, gr->description);
  3283. lua_setfield (L, -2, "description");
  3284. lua_pushnumber (L, gr->max_score);
  3285. lua_setfield (L, -2, "max_score");
  3286. lua_pushboolean (L, (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC) != 0);
  3287. lua_setfield (L, -2, "is_public");
  3288. /* TODO: maybe push symbols as well */
  3289. /* Parent table indexed by group name */
  3290. lua_setfield (L, -2, gr->name);
  3291. }
  3292. }
  3293. }
  3294. else {
  3295. return luaL_error (L, "invalid arguments");
  3296. }
  3297. return 1;
  3298. }
  3299. static gint
  3300. lua_config_register_finish_script (lua_State *L)
  3301. {
  3302. LUA_TRACE_POINT;
  3303. struct rspamd_config *cfg = lua_check_config (L, 1);
  3304. struct rspamd_config_cfg_lua_script *sc;
  3305. if (cfg != NULL && lua_type (L, 2) == LUA_TFUNCTION) {
  3306. sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
  3307. lua_pushvalue (L, 2);
  3308. sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  3309. DL_APPEND (cfg->on_term_scripts, sc);
  3310. }
  3311. else {
  3312. return luaL_error (L, "invalid arguments");
  3313. }
  3314. return 0;
  3315. }
  3316. static inline bool
  3317. rspamd_lua_config_check_settings_symbols_object (const ucl_object_t *obj)
  3318. {
  3319. if (obj == NULL) {
  3320. /* Semantically valid */
  3321. return true;
  3322. }
  3323. if (ucl_object_type (obj) == UCL_OBJECT) {
  3324. /* Key-value mapping - should be okay */
  3325. return true;
  3326. }
  3327. if (ucl_object_type (obj) == UCL_ARRAY) {
  3328. /* Okay if empty */
  3329. if (obj->len == 0) {
  3330. return true;
  3331. }
  3332. }
  3333. /* Everything else not okay */
  3334. return false;
  3335. }
  3336. static gint
  3337. lua_config_register_settings_id (lua_State *L)
  3338. {
  3339. LUA_TRACE_POINT;
  3340. struct rspamd_config *cfg = lua_check_config (L, 1);
  3341. const gchar *settings_name = luaL_checkstring (L, 2);
  3342. if (cfg != NULL && settings_name) {
  3343. ucl_object_t *sym_enabled, *sym_disabled;
  3344. enum rspamd_config_settings_policy policy = RSPAMD_SETTINGS_POLICY_DEFAULT;
  3345. sym_enabled = ucl_object_lua_import (L, 3);
  3346. if (!rspamd_lua_config_check_settings_symbols_object (sym_enabled)) {
  3347. ucl_object_unref (sym_enabled);
  3348. return luaL_error (L, "invalid symbols enabled");
  3349. }
  3350. sym_disabled = ucl_object_lua_import (L, 4);
  3351. if (!rspamd_lua_config_check_settings_symbols_object (sym_disabled)) {
  3352. ucl_object_unref (sym_enabled);
  3353. ucl_object_unref (sym_disabled);
  3354. return luaL_error (L, "invalid symbols enabled");
  3355. }
  3356. /* Check policy */
  3357. if (lua_isstring (L, 5)) {
  3358. const gchar *policy_str = lua_tostring (L, 5);
  3359. if (strcmp (policy_str, "default") == 0) {
  3360. policy = RSPAMD_SETTINGS_POLICY_DEFAULT;
  3361. }
  3362. else if (strcmp (policy_str, "implicit_allow") == 0) {
  3363. policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_ALLOW;
  3364. }
  3365. else if (strcmp (policy_str, "implicit_deny") == 0) {
  3366. policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_DENY;
  3367. }
  3368. else {
  3369. return luaL_error (L, "invalid settings policy: %s", policy_str);
  3370. }
  3371. }
  3372. else {
  3373. /* Apply heuristic */
  3374. if (!sym_enabled) {
  3375. policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_ALLOW;
  3376. }
  3377. }
  3378. rspamd_config_register_settings_id (cfg, settings_name, sym_enabled,
  3379. sym_disabled, policy);
  3380. if (sym_enabled) {
  3381. ucl_object_unref (sym_enabled);
  3382. }
  3383. if (sym_disabled) {
  3384. ucl_object_unref (sym_disabled);
  3385. }
  3386. }
  3387. else {
  3388. return luaL_error (L, "invalid arguments");
  3389. }
  3390. return 0;
  3391. }
  3392. static gint
  3393. lua_config_register_monitored (lua_State *L)
  3394. {
  3395. LUA_TRACE_POINT;
  3396. struct rspamd_config *cfg = lua_check_config (L, 1);
  3397. struct rspamd_monitored *m, **pm;
  3398. const gchar *url, *type;
  3399. ucl_object_t *params = NULL;
  3400. url = lua_tostring (L, 2);
  3401. type = lua_tostring (L, 3);
  3402. if (cfg != NULL && url != NULL && type != NULL) {
  3403. if (g_ascii_strcasecmp (type, "dns") == 0) {
  3404. lua_Debug ar;
  3405. if (lua_type (L, 4) == LUA_TTABLE) {
  3406. params = ucl_object_lua_import (L, 4);
  3407. }
  3408. /* Get lua line and source */
  3409. lua_getstack (L, 1, &ar);
  3410. lua_getinfo (L, "nSl", &ar);
  3411. m = rspamd_monitored_create_ (cfg->monitored_ctx, url,
  3412. RSPAMD_MONITORED_DNS, RSPAMD_MONITORED_DEFAULT,
  3413. params, ar.short_src);
  3414. if (m) {
  3415. pm = lua_newuserdata (L, sizeof (*pm));
  3416. *pm = m;
  3417. rspamd_lua_setclass (L, "rspamd{monitored}", -1);
  3418. }
  3419. else {
  3420. lua_pushnil (L);
  3421. }
  3422. if (params) {
  3423. ucl_object_unref (params);
  3424. }
  3425. }
  3426. else {
  3427. return luaL_error (L, "invalid monitored type: %s", type);
  3428. }
  3429. }
  3430. else {
  3431. return luaL_error (L, "invalid arguments");
  3432. }
  3433. return 1;
  3434. }
  3435. static gint
  3436. lua_config_add_doc (lua_State *L)
  3437. {
  3438. LUA_TRACE_POINT;
  3439. struct rspamd_config *cfg;
  3440. const gchar *path = NULL, *option, *doc_string;
  3441. const gchar *type_str = NULL, *default_value = NULL;
  3442. ucl_type_t type = UCL_NULL;
  3443. gboolean required = FALSE;
  3444. GError *err = NULL;
  3445. cfg = lua_check_config (L, 1);
  3446. if (lua_type (L, 2 ) == LUA_TSTRING) {
  3447. path = luaL_checkstring (L, 2);
  3448. }
  3449. option = luaL_checkstring (L, 3);
  3450. doc_string = luaL_checkstring (L, 4);
  3451. if (cfg && option && doc_string) {
  3452. if (lua_type (L, 5) == LUA_TTABLE) {
  3453. if (!rspamd_lua_parse_table_arguments (L, 5, &err,
  3454. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  3455. "type=S;default=S;required=B",
  3456. &type_str, &default_value, &required)) {
  3457. msg_err_config ("cannot get parameters list: %e", err);
  3458. if (err) {
  3459. g_error_free (err);
  3460. }
  3461. if (type_str) {
  3462. if (!ucl_object_string_to_type (type_str, &type)) {
  3463. msg_err_config ("invalid type: %s", type_str);
  3464. }
  3465. }
  3466. }
  3467. }
  3468. rspamd_rcl_add_doc_by_path (cfg, path, doc_string, option,
  3469. type, NULL, 0, default_value, required);
  3470. }
  3471. else {
  3472. return luaL_error (L, "invalid arguments");
  3473. }
  3474. return 0;
  3475. }
  3476. static gint
  3477. lua_config_add_example (lua_State *L)
  3478. {
  3479. LUA_TRACE_POINT;
  3480. struct rspamd_config *cfg;
  3481. const gchar *path = NULL, *option, *doc_string, *example;
  3482. gsize example_len;
  3483. cfg = lua_check_config (L, 1);
  3484. if (lua_type (L, 2 ) == LUA_TSTRING) {
  3485. path = luaL_checkstring (L, 2);
  3486. }
  3487. option = luaL_checkstring (L, 3);
  3488. doc_string = luaL_checkstring (L, 4);
  3489. example = luaL_checklstring (L, 5, &example_len);
  3490. if (cfg && option && doc_string && example) {
  3491. rspamd_rcl_add_doc_by_example (cfg, path, doc_string, option,
  3492. example, example_len);
  3493. }
  3494. else {
  3495. return luaL_error (L, "invalid arguments");
  3496. }
  3497. return 0;
  3498. }
  3499. static gint
  3500. lua_config_get_cpu_flags (lua_State *L)
  3501. {
  3502. LUA_TRACE_POINT;
  3503. struct rspamd_config *cfg = lua_check_config (L, 1);
  3504. struct rspamd_cryptobox_library_ctx *crypto_ctx;
  3505. if (cfg != NULL) {
  3506. crypto_ctx = cfg->libs_ctx->crypto_ctx;
  3507. lua_newtable (L);
  3508. if (crypto_ctx->cpu_config & CPUID_SSSE3) {
  3509. lua_pushstring (L, "ssse3");
  3510. lua_pushboolean (L, true);
  3511. lua_settable (L, -3);
  3512. }
  3513. if (crypto_ctx->cpu_config & CPUID_SSE41) {
  3514. lua_pushstring (L, "sse41");
  3515. lua_pushboolean (L, true);
  3516. lua_settable (L, -3);
  3517. }
  3518. if (crypto_ctx->cpu_config & CPUID_SSE42) {
  3519. lua_pushstring (L, "sse42");
  3520. lua_pushboolean (L, true);
  3521. lua_settable (L, -3);
  3522. }
  3523. if (crypto_ctx->cpu_config & CPUID_SSE2) {
  3524. lua_pushstring (L, "sse2");
  3525. lua_pushboolean (L, true);
  3526. lua_settable (L, -3);
  3527. }
  3528. if (crypto_ctx->cpu_config & CPUID_SSE3) {
  3529. lua_pushstring (L, "sse3");
  3530. lua_pushboolean (L, true);
  3531. lua_settable (L, -3);
  3532. }
  3533. if (crypto_ctx->cpu_config & CPUID_AVX) {
  3534. lua_pushstring (L, "avx");
  3535. lua_pushboolean (L, true);
  3536. lua_settable (L, -3);
  3537. }
  3538. if (crypto_ctx->cpu_config & CPUID_AVX2) {
  3539. lua_pushstring (L, "avx2");
  3540. lua_pushboolean (L, true);
  3541. lua_settable (L, -3);
  3542. }
  3543. }
  3544. else {
  3545. return luaL_error (L, "invalid arguments");
  3546. }
  3547. return 1;
  3548. }
  3549. static gint
  3550. lua_config_has_torch (lua_State *L)
  3551. {
  3552. msg_warn ("use of the obsoleted `has_torch` function");
  3553. lua_pushboolean (L, false);
  3554. return 1;
  3555. }
  3556. static gint
  3557. lua_config_experimental_enabled (lua_State *L)
  3558. {
  3559. LUA_TRACE_POINT;
  3560. struct rspamd_config *cfg = lua_check_config (L, 1);
  3561. if (cfg != NULL) {
  3562. lua_pushboolean (L, cfg->enable_experimental);
  3563. }
  3564. else {
  3565. return luaL_error (L, "invalid arguments");
  3566. }
  3567. return 1;
  3568. }
  3569. struct rspamd_lua_include_trace_cbdata {
  3570. lua_State *L;
  3571. gint cbref;
  3572. };
  3573. static void
  3574. lua_include_trace_cb (struct ucl_parser *parser,
  3575. const ucl_object_t *parent,
  3576. const ucl_object_t *args,
  3577. const char *path,
  3578. size_t pathlen,
  3579. void *user_data)
  3580. {
  3581. struct rspamd_lua_include_trace_cbdata *cbdata =
  3582. (struct rspamd_lua_include_trace_cbdata *)user_data;
  3583. gint err_idx;
  3584. lua_State *L;
  3585. L = cbdata->L;
  3586. lua_pushcfunction (L, &rspamd_lua_traceback);
  3587. err_idx = lua_gettop (L);
  3588. lua_rawgeti (L, LUA_REGISTRYINDEX, cbdata->cbref);
  3589. /* Current filename */
  3590. lua_pushstring (L, ucl_parser_get_cur_file (parser));
  3591. /* Included filename */
  3592. lua_pushlstring (L, path, pathlen);
  3593. /* Params */
  3594. if (args) {
  3595. ucl_object_push_lua (L, args, true);
  3596. }
  3597. else {
  3598. lua_newtable (L);
  3599. }
  3600. /* Parent */
  3601. if (parent) {
  3602. lua_pushstring (L, ucl_object_key (parent));
  3603. }
  3604. else {
  3605. lua_pushnil (L);
  3606. }
  3607. if (lua_pcall (L, 4, 0, err_idx) != 0) {
  3608. msg_err ("lua call to local include trace failed: %s", lua_tostring (L, -1));
  3609. }
  3610. lua_settop (L, err_idx - 1);
  3611. }
  3612. #define LUA_TABLE_TO_HASH(htb, idx) do { \
  3613. lua_pushstring (L, (idx)); \
  3614. lua_gettable (L, -2); \
  3615. if (lua_isstring (L, -1)) { \
  3616. g_hash_table_insert ((htb), (idx), g_strdup (lua_tostring (L, -1))); \
  3617. } \
  3618. lua_pop (L, 1); \
  3619. } while(0)
  3620. static gint
  3621. lua_config_load_ucl (lua_State *L)
  3622. {
  3623. struct rspamd_config *cfg = lua_check_config (L, 1);
  3624. const gchar *filename;
  3625. GHashTable *paths = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal,
  3626. NULL, g_free);
  3627. GError *err = NULL;
  3628. if (cfg) {
  3629. if (lua_isstring (L, 2)) {
  3630. filename = lua_tostring (L, 2);
  3631. }
  3632. else {
  3633. filename = RSPAMD_CONFDIR "/rspamd.conf";
  3634. }
  3635. /* Convert rspamd_paths */
  3636. lua_getglobal (L, "rspamd_paths");
  3637. if (lua_istable (L, -1)) {
  3638. LUA_TABLE_TO_HASH(paths, RSPAMD_CONFDIR_INDEX);
  3639. LUA_TABLE_TO_HASH(paths, RSPAMD_LOCAL_CONFDIR_INDEX);
  3640. LUA_TABLE_TO_HASH(paths, RSPAMD_RUNDIR_INDEX);
  3641. LUA_TABLE_TO_HASH(paths, RSPAMD_DBDIR_INDEX);
  3642. LUA_TABLE_TO_HASH(paths, RSPAMD_LOGDIR_INDEX);
  3643. LUA_TABLE_TO_HASH(paths, RSPAMD_WWWDIR_INDEX);
  3644. LUA_TABLE_TO_HASH(paths, RSPAMD_PLUGINSDIR_INDEX);
  3645. LUA_TABLE_TO_HASH(paths, RSPAMD_RULESDIR_INDEX);
  3646. LUA_TABLE_TO_HASH(paths, RSPAMD_LUALIBDIR_INDEX);
  3647. LUA_TABLE_TO_HASH(paths, RSPAMD_PREFIX_INDEX);
  3648. }
  3649. lua_pop (L, 1);
  3650. if (lua_isfunction (L, 3)) {
  3651. struct rspamd_lua_include_trace_cbdata cbd;
  3652. lua_pushvalue (L, 3);
  3653. cbd.cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  3654. cbd.L = L;
  3655. if (!rspamd_config_parse_ucl (cfg, filename, paths,
  3656. lua_include_trace_cb, &cbd, lua_toboolean (L, 4), &err)) {
  3657. luaL_unref (L, LUA_REGISTRYINDEX, cbd.cbref);
  3658. lua_pushboolean (L, false);
  3659. lua_pushfstring (L, "failed to load config: %s", err->message);
  3660. g_error_free (err);
  3661. g_hash_table_unref (paths);
  3662. return 2;
  3663. }
  3664. luaL_unref (L, LUA_REGISTRYINDEX, cbd.cbref);
  3665. }
  3666. else {
  3667. if (!rspamd_config_parse_ucl (cfg, filename, paths, NULL, NULL,
  3668. lua_toboolean (L, 3), &err)) {
  3669. lua_pushboolean (L, false);
  3670. lua_pushfstring (L, "failed to load config: %s", err->message);
  3671. g_error_free (err);
  3672. g_hash_table_unref (paths);
  3673. return 2;
  3674. }
  3675. }
  3676. rspamd_rcl_maybe_apply_lua_transform (cfg);
  3677. rspamd_config_calculate_cksum (cfg);
  3678. }
  3679. else {
  3680. return luaL_error (L, "invalid arguments");
  3681. }
  3682. g_hash_table_unref (paths);
  3683. lua_pushboolean (L, true);
  3684. return 1;
  3685. }
  3686. #undef IDX_TO_HASH
  3687. static gint
  3688. lua_config_parse_rcl (lua_State *L)
  3689. {
  3690. LUA_TRACE_POINT;
  3691. struct rspamd_config *cfg = lua_check_config (L, 1);
  3692. GHashTable *excluded = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal,
  3693. g_free, NULL);
  3694. GError *err = NULL;
  3695. struct rspamd_rcl_section *top;
  3696. if (cfg) {
  3697. if (lua_istable (L, 2)) {
  3698. lua_pushvalue (L, 2);
  3699. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  3700. g_hash_table_insert (excluded, g_strdup (lua_tostring (L, -1)),
  3701. GINT_TO_POINTER (-1));
  3702. }
  3703. lua_pop (L, 1);
  3704. }
  3705. top = rspamd_rcl_config_init (cfg, excluded);
  3706. if (!rspamd_rcl_parse (top, cfg, cfg, cfg->cfg_pool, cfg->rcl_obj, &err)) {
  3707. lua_pushboolean (L, false);
  3708. lua_pushfstring (L, "failed to load config: %s", err->message);
  3709. g_error_free (err);
  3710. g_hash_table_unref (excluded);
  3711. rspamd_rcl_section_free (top);
  3712. return 2;
  3713. }
  3714. }
  3715. else {
  3716. return luaL_error (L, "invalid arguments");
  3717. }
  3718. g_hash_table_unref (excluded);
  3719. rspamd_rcl_section_free (top);
  3720. lua_pushboolean (L, true);
  3721. return 1;
  3722. }
  3723. static gint
  3724. lua_config_init_modules (lua_State *L)
  3725. {
  3726. LUA_TRACE_POINT;
  3727. struct rspamd_config *cfg = lua_check_config (L, 1);
  3728. if (cfg != NULL) {
  3729. rspamd_lua_post_load_config (cfg);
  3730. lua_pushboolean (L, rspamd_init_filters (cfg, false, false));
  3731. }
  3732. else {
  3733. return luaL_error (L, "invalid arguments");
  3734. }
  3735. return 1;
  3736. }
  3737. static gint
  3738. lua_config_init_subsystem (lua_State *L)
  3739. {
  3740. LUA_TRACE_POINT;
  3741. struct rspamd_config *cfg = lua_check_config (L, 1);
  3742. const gchar *subsystem = luaL_checkstring (L, 2);
  3743. gchar **parts;
  3744. guint nparts, i;
  3745. if (cfg != NULL && subsystem != NULL) {
  3746. parts = g_strsplit_set (subsystem, ";,", -1);
  3747. nparts = g_strv_length (parts);
  3748. for (i = 0; i < nparts; i ++) {
  3749. if (strcmp (parts[i], "filters") == 0) {
  3750. rspamd_lua_post_load_config (cfg);
  3751. rspamd_init_filters (cfg, false, false);
  3752. }
  3753. else if (strcmp (parts[i], "langdet") == 0) {
  3754. if (!cfg->lang_det) {
  3755. cfg->lang_det = rspamd_language_detector_init (cfg);
  3756. rspamd_mempool_add_destructor (cfg->cfg_pool,
  3757. (rspamd_mempool_destruct_t) rspamd_language_detector_unref,
  3758. cfg->lang_det);
  3759. }
  3760. }
  3761. else if (strcmp (parts[i], "stat") == 0) {
  3762. rspamd_stat_init (cfg, NULL);
  3763. }
  3764. else if (strcmp (parts[i], "dns") == 0) {
  3765. struct ev_loop *ev_base = lua_check_ev_base (L, 3);
  3766. if (ev_base) {
  3767. cfg->dns_resolver = rspamd_dns_resolver_init (rspamd_log_default_logger (),
  3768. ev_base,
  3769. cfg);
  3770. }
  3771. else {
  3772. g_strfreev (parts);
  3773. return luaL_error (L, "no event base specified");
  3774. }
  3775. }
  3776. else if (strcmp (parts[i], "symcache") == 0) {
  3777. rspamd_symcache_init (cfg->cache);
  3778. }
  3779. else {
  3780. int ret = luaL_error (L, "invalid param: %s", parts[i]);
  3781. g_strfreev (parts);
  3782. return ret;
  3783. }
  3784. }
  3785. g_strfreev (parts);
  3786. }
  3787. else {
  3788. return luaL_error (L, "invalid arguments");
  3789. }
  3790. return 0;
  3791. }
  3792. static gint
  3793. lua_config_register_re_selector (lua_State *L)
  3794. {
  3795. LUA_TRACE_POINT;
  3796. struct rspamd_config *cfg = lua_check_config (L, 1);
  3797. const gchar *name = luaL_checkstring (L, 2);
  3798. const gchar *selector_str = luaL_checkstring (L, 3);
  3799. const gchar *delimiter = "";
  3800. bool flatten = false;
  3801. gint top = lua_gettop (L);
  3802. bool res = false;
  3803. if (cfg && name && selector_str) {
  3804. if (lua_gettop (L) >= 4) {
  3805. delimiter = luaL_checkstring (L, 4);
  3806. if (lua_isboolean (L, 5)) {
  3807. flatten = lua_toboolean (L, 5);
  3808. }
  3809. }
  3810. if (luaL_dostring (L, "return require \"lua_selectors\"") != 0) {
  3811. msg_warn_config ("cannot require lua_selectors: %s",
  3812. lua_tostring (L, -1));
  3813. }
  3814. else {
  3815. if (lua_type (L, -1) != LUA_TTABLE) {
  3816. msg_warn_config ("lua selectors must return "
  3817. "table and not %s",
  3818. lua_typename (L, lua_type (L, -1)));
  3819. }
  3820. else {
  3821. lua_pushstring (L, "create_selector_closure");
  3822. lua_gettable (L, -2);
  3823. if (lua_type (L, -1) != LUA_TFUNCTION) {
  3824. msg_warn_config ("create_selector_closure must return "
  3825. "function and not %s",
  3826. lua_typename (L, lua_type (L, -1)));
  3827. }
  3828. else {
  3829. gint err_idx, ret;
  3830. struct rspamd_config **pcfg;
  3831. lua_pushcfunction (L, &rspamd_lua_traceback);
  3832. err_idx = lua_gettop (L);
  3833. /* Push function */
  3834. lua_pushvalue (L, -2);
  3835. pcfg = lua_newuserdata (L, sizeof (*pcfg));
  3836. rspamd_lua_setclass (L, "rspamd{config}", -1);
  3837. *pcfg = cfg;
  3838. lua_pushstring (L, selector_str);
  3839. lua_pushstring (L, delimiter);
  3840. lua_pushboolean (L, flatten);
  3841. if ((ret = lua_pcall (L, 4, 1, err_idx)) != 0) {
  3842. msg_err_config ("call to create_selector_closure lua "
  3843. "script failed (%d): %s", ret,
  3844. lua_tostring (L, -1));
  3845. }
  3846. else {
  3847. if (lua_type (L, -1) != LUA_TFUNCTION) {
  3848. msg_warn_config ("create_selector_closure "
  3849. "invocation must return "
  3850. "function and not %s",
  3851. lua_typename (L, lua_type (L, -1)));
  3852. }
  3853. else {
  3854. ret = luaL_ref (L, LUA_REGISTRYINDEX);
  3855. rspamd_re_cache_add_selector (cfg->re_cache,
  3856. name, ret);
  3857. res = true;
  3858. }
  3859. }
  3860. }
  3861. }
  3862. }
  3863. }
  3864. else {
  3865. return luaL_error (L, "invalid arguments");
  3866. }
  3867. lua_settop (L, top);
  3868. lua_pushboolean (L, res);
  3869. if (res) {
  3870. msg_info_config ("registered regexp selector %s", name);
  3871. }
  3872. return 1;
  3873. }
  3874. static gint
  3875. lua_config_get_tld_path (lua_State *L)
  3876. {
  3877. LUA_TRACE_POINT;
  3878. struct rspamd_config *cfg = lua_check_config (L, 1);
  3879. if (cfg != NULL) {
  3880. lua_pushstring (L, cfg->tld_file);
  3881. }
  3882. else {
  3883. return luaL_error (L, "invalid arguments");
  3884. }
  3885. return 1;
  3886. }
  3887. static gint
  3888. lua_config_get_dns_max_requests (lua_State *L)
  3889. {
  3890. LUA_TRACE_POINT;
  3891. struct rspamd_config *cfg = lua_check_config (L, 1);
  3892. if (cfg != NULL) {
  3893. lua_pushinteger (L, cfg->dns_max_requests);
  3894. }
  3895. else {
  3896. return luaL_error (L, "invalid arguments");
  3897. }
  3898. return 1;
  3899. }
  3900. static gint
  3901. lua_monitored_alive (lua_State *L)
  3902. {
  3903. LUA_TRACE_POINT;
  3904. struct rspamd_monitored *m = lua_check_monitored (L, 1);
  3905. if (m) {
  3906. lua_pushboolean (L, rspamd_monitored_alive (m));
  3907. }
  3908. else {
  3909. return luaL_error (L, "invalid arguments");
  3910. }
  3911. return 1;
  3912. }
  3913. static gint
  3914. lua_monitored_offline (lua_State *L)
  3915. {
  3916. LUA_TRACE_POINT;
  3917. struct rspamd_monitored *m = lua_check_monitored (L, 1);
  3918. if (m) {
  3919. lua_pushnumber (L, rspamd_monitored_offline_time (m));
  3920. }
  3921. else {
  3922. return luaL_error (L, "invalid arguments");
  3923. }
  3924. return 1;
  3925. }
  3926. static gint
  3927. lua_monitored_total_offline (lua_State *L)
  3928. {
  3929. LUA_TRACE_POINT;
  3930. struct rspamd_monitored *m = lua_check_monitored (L, 1);
  3931. if (m) {
  3932. lua_pushnumber (L, rspamd_monitored_total_offline_time (m));
  3933. }
  3934. else {
  3935. return luaL_error (L, "invalid arguments");
  3936. }
  3937. return 1;
  3938. }
  3939. static gint
  3940. lua_monitored_latency (lua_State *L)
  3941. {
  3942. LUA_TRACE_POINT;
  3943. struct rspamd_monitored *m = lua_check_monitored (L, 1);
  3944. if (m) {
  3945. lua_pushnumber (L, rspamd_monitored_latency (m));
  3946. }
  3947. else {
  3948. return luaL_error (L, "invalid arguments");
  3949. }
  3950. return 1;
  3951. }
  3952. void
  3953. luaopen_config (lua_State * L)
  3954. {
  3955. rspamd_lua_new_class (L, "rspamd{config}", configlib_m);
  3956. lua_pop (L, 1);
  3957. rspamd_lua_new_class (L, "rspamd{monitored}", monitoredlib_m);
  3958. lua_pop (L, 1);
  3959. }
  3960. void
  3961. lua_call_finish_script (struct rspamd_config_cfg_lua_script *sc,
  3962. struct rspamd_task *task) {
  3963. struct rspamd_task **ptask;
  3964. struct thread_entry *thread;
  3965. thread = lua_thread_pool_get_for_task (task);
  3966. thread->task = task;
  3967. lua_State *L = thread->lua_state;
  3968. lua_rawgeti (L, LUA_REGISTRYINDEX, sc->cbref);
  3969. ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
  3970. rspamd_lua_setclass (L, "rspamd{task}", - 1);
  3971. *ptask = task;
  3972. lua_thread_call (thread, 1);
  3973. }