phone

    • chevron_right

      Ignite Realtime Blog: New: Openfire MUC Real-Time Block List plugin!

      news.movim.eu / PlanetJabber · Thursday, 23 February, 2023 - 20:30 · 1 minute

    A new plugin has been made available for Openfire, our cross-platform real-time collaboration server based on the XMPP protocol. We have named this new plugin the MUC Real-Time Block List plugin.

    This plugin can help you moderate your chat rooms, especially when your service is part of a larger network of federated XMPP domains. From experience, the XMPP community has learned that bad actors tend to spam a wide range of public chat rooms on an equally wide range of different domains. Prior to the functionality provided by this plugin, the administrator of each MUC service had to manually adjust permissions, to keep unwanted entities out. With this new plugin, that process is automated.

    This plugin can be used to subscribe to a Publish/Subscribe node (as defined in XEP-0060 ), that can live on a remote XMPP domain, but curated by a trusted (group of) administrators). It is expected that this node contains a list of banned entities. When Openfire, through the plugin, is notified that the list has received a new banned entity, it will prevent that entity from joining a chat room in Openfire (if they’re already in, they will be kicked out automatically). Using this mechanism, moderation efforts centralized in one federated Pub/Sub service can be used by any server that uses this plugin.

    This plugin is heavily inspired, and aspires to be compatible with, Prosody’s mod_muc_rtbl and the pub/sub services that it uses.

    The first version of this plugin is now available on our website and should become available in the list of installable plugins in your instance of Openfire in the next few hours. Please give it a test! We are interested in hearing back from you!

    For other release announcements and news follow us on Twitter

    1 post - 1 participant

    Read full topic

    • chevron_right

      Erlang Solutions: Can’t Live `with` It, Can’t Live `with`out It

      news.movim.eu / PlanetJabber · Thursday, 23 February, 2023 - 12:29 · 8 minutes

    I’d like to share some thoughts about Elixir’s with keyword. with is a wonderful tool, but in my experience it is a bit overused.  To use it best, we must understand how it behaves in all cases.  So, let’s briefly cover the basics, starting with pipes in Elixir.

    Pipes are a wonderful abstraction

    But like all tools, you should think about when it is best used…

    Pipes are at their best when you expect your functions to accept and return basic values. But often we don’t have only simple values because we need to deal with error cases . For example:

    region 
    
    |> Module.fetch_companies() 
    
    |> Module.fetch_departments() 
    
    |> Enum.map(& &1.employee_count) 
    
    |> calculate_average()

    If our fetch_* methods return list values there isn’t a problem. But often we fetch data from an external source, which means we introduce the possibility of an error . Generally in Elixir this means {:ok, _} tuples for success and {:error, _} tuples for failure. Using pipes that might become:

    region
    
    |> Module.fetch_companies()
    
    |> case do
    
      {:ok, companies} -> Module.fetch_departments(companies)
    
      {:error, _} = error -> error
    
    end
    
    |> case do
    
      {:ok, departments} ->
    
        departments
    
        |> Enum.map(& &1.employee_count)
    
        |> calculate_average()
    
      {:error, _} = error -> error
    
    end

    Not horrible, but certainly not beautiful. Fortunately, Elixir has with !

    `with` is a wonderful abstraction

    But like all tools, you should think about when it’s best used…

    with is at it’s best when dealing with the happy paths of a set of calls which all return similar things . What do I mean by that? Let’s look at what this code might look like using with ?

    with {:ok, companies} <- Module.fetch_companies(region),
    
         {:ok, departments} <- Module.fetch_departments(companies) do
    
      departments
    
      |> Enum.map(& &1.employee_count)
    
      |> calculate_average()
    
    end

    That’s definitely better!

    • We separated out the parts of our code which might fail (remember that failure is a sign of a side-effect and in functional programming we want to isolate side-effects).
    • The body is only the things that we don’t expect to fail.
    • We don’t need to explicitly deal with the {:error, _} cases (in this case with will return any clause values which don’t match the pattern before <-) .

    But this is a great example of a happy path where the set of calls all return similar things . But where are some examples of where we might go wrong with with ?

    Non-standard failure

    What if Module.fetch_companies returns {:error, _} but `Module.fetch_departments` returns just :error ? That means your with is going to return two different error results. If your with is the end of your function call then that complexity is now the caller’s responsibility. You might not think that’s a big deal because we can do this:

    else
    
      :error -> {:error, "Error fetching departments"}

    But this breaks to more-or-less important degrees because:

    • … once you add an else clause, you need to take care of every non-happy path case (e.g. above we should match the {:error, _} returned by Module.fetch_companies which we didn’t need to explicitly match before) 😤
    • … if either function is later refactored to return another pattern (e.g. {:error, _, _} ) – there will be a WithClauseError exception (again, because once you add an else the fallback behavior of non-matching <- patterns doesn’t work) 🤷‍♂️
    • … if Module.fetch_departments is later refactored to return {:error, _} – we’ll then have an unused handler 🤷‍♂️
    • … if another clause is added which also returns :error the message Error fetching departments probably won’t be the right error 🙈
    • … if you want to refactor this code later, you need to understand *everything* that the called functions might potentially return, leading to code which is hard to refactor.  If there are just two clauses and we’re just calling simple functions, that’s not as big of a deal.  But with many with clauses which call complex functions, it can become a nightmare 🙀

    So the first major thing to know when using with is what happens when a clause doesn’t match it’s pattern :

    • If else is not specified then the non-matching clause is returned.
    • If else is specified then the code for the first matching else pattern is evaluated. If no else pattern matches , a WithClauseError is raised.

    As Stratus3D excellently put it: “ with blocks are the only Elixir construct that implicitly uses the same else clauses to handle return values from different expressions. The lack of a one-to-one correspondence between an expression in the head of the with block and the clauses that handle its return values makes it impossible to know when each else clause will be used”. There are a couple of well known solutions to address this.  One is using “tagged tuples”:

    with {:fetch_companies, {:ok, companies} <- {:fetch_companies, Module.fetch_companies(region)},
    
         {:fetch_departments, {:ok, departments} <- {:fetch_departments, Module.fetch_departments(companies)},
    
      departments
    
      |> Enum.map(& &1.employee_count)
    
      |> calculate_average()
    
    else
    
      {:fetch_companies, {:error, reason}} -> ...
    
      {:fetch_departments, :error} -> ...
    
    end

    Though tagged tuples should be avoided for various reasons:

    • They make the code a lot more verbose
    • else is now being used, so we need to match all patterns that might occur
    • We need to keep the clauses and else in sync when adding/removing/modifying clauses, leaving room for bugs.
    • Most importantly: the value in an abstraction like {:ok, _} / {:error, _} tuples is that you can handle things generically without needing to worry about the source

    A generally better solution is to create functions which normalize the values matched in the patterns.  This is covered well in a note in the docs for with and I recommend checking it out.  One addition I would make: in the above case you could leave the Module.fetch_companies alone and just surround the Module.fetch_departments with a local fetch_departments to turn the :error into an {:error, reason} .

    Non-standard success

    We can even get unexpected results when with succeeds! To start let’s look at the parse/1 function from the excellent decimal library. It’s typespec tells us that it can return {Decimal.t(), binary()} or :error . If we want to match a decimal value without extra characters, we could have a with clause like this:

    with {:ok, value} <- fetch_value(),
    
         {decimal, ""} <- Decimal.parse(value) do
    
      {:ok, decimal}

    But if value is given as "1.23 " (with a space at the end), then Decimal.parse/1 will return {#Decimal<1.23>, " "} . Since that doesn’t match our pattern (string with a space vs. an empty string), the body of the with will be skipped. If we don’t have an else then instead of returning a {:ok, _} value, we return {#Decimal<1.23>, " "} .

    The solution may seem simple: match on {decimal, _} ! But then we match strings like “1.23a” which is what we were trying to avoid. Again, we’re likely better off defining a local parse_decimal function which returns {:ok, _} or {:error, _} .

    There are other, similar, situations:

    • {:ok, %{"key" => value}} <- fetch_data(...) – the value inside of the {:ok, _} tuple may not have a "key" key.
    • [%{id: value}] <- fetch_data(...) – the list returned may have more or less than one item, or if it does only have one item it may not have the :id key
    • value when length(value) > 2 <- fetch_data(...) – the when might not match. There are two cases where this might surprise you:
      • If value is a list, the length of the list being 2 or below will return the list.
      • If value is a string, length isn’t a valid function (you’d probably want byte_size ). Instead of an exception, the guard simply fails and the pattern doesn’t match.

    The problem in all of these cases is that the intermediate value from fetch_data will be returned, not what the body of the with would return. This means that our with returns “uneven” results. We can handle these cases in the else , but again, once we introduce else we need to take care of all potential cases.

    I might even go to the extent of recommending that you don’t define with clause patterns which are at all deep in their pattern matching unless you are very sure the success case will be able to match the whole pattern .  One example where you might take a risk is when matching %MyStruct{key: value} <- … where you know that a MyStruct value is going to be returned and you know that key is one of the keys defined for the struct. No matter the case, dialyzer is one tool to gain confidence that you will be able to match on the pattern (at least for your own code or libraries which also use dialyzer).

    One of the simplest and most standard ways to avoid these issues is to make sure the functions that you are calling return {:ok, variable} or {:error, reason} tuples. Then with can fall through cleanly ( definitely check out Chris Keathley’s discussion of “Avoid else in with blocks” in his post “Good and Bad Elixir” ).

    With all that said, I recommend using with statements whenever you can! Just make sure that you think about fallback cases that might happen. Even better: write tests to cover all of your potential cases! If you can strike a balance and use with carefully, your code can be both cleaner and more reliable.

    Need help with Elixir?

    We’ve helped 100’s of the world’s biggest companies achieve success with Elixir. From digital transformation, developing fit-for-purposes software for your business logic, to proof-of-concepts, right through to staff augmentation development and support. We’re here to make sure your system makes the most of Elixir to be scalable, reliable and easy to maintain. Talk to us to learn more.

    Training

    Want to improve your Elixir skills? Our world-leading experts are here to help. Learn from the same team who architect, manage and develop some of the biggest in-production systems available. Head to our training page to learn more about our courses and tutorials.

    The post Can’t Live `with` It, Can’t Live `with`out It appeared first on Erlang Solutions .

    • chevron_right

      JMP: SMS Account Verification

      news.movim.eu / PlanetJabber · Sunday, 19 February, 2023 - 03:49 · 4 minutes

    Some apps and services (but not JMP!) require an SMS verification code in order to create a new account.  (Note that this is different from using SMS for authentication; which is a bad idea since SMS can be easily intercepted , are not encrypted in transit , and are vulnerable to simple swap scams , etc.; but has different incentives and issues.)  Why do they do this, and how can it affect you as a user?

    Tarpit

    In the fight against service abuse and SPAM, there are no sure-fire one-size-fits-all solutions.  Often preventing abusive accounts and spammers entirely is not possible, so targets turn to other strategies, such as tarpits .  This is anything that slows down the abusive activity, thus resulting in less of it.  This is the best way to think about most account-creation verification measures.  Receiving an SMS to a unique phone number is something that is not hard for most customers creating an account.  Even a customer who does not wish to give out their phone number or does not have a phone number can (in many countries, with enough money) get a new cell phone and cell phone number fairly quickly and use that to create the account.

    If a customer is expected to be able to pass this check easily, and an abuser is indistiguishable from a customer, then how can any SMS verification possibly help prevent abuse?  Well, if the abuser needs to create only one account, it cannot.  However, in many cases an abuser is trying to create tens of thousands of accounts.  Now imagine trying to buy ten thousand new cell phones at your local store every day.  It is not going to be easy.

    “VoIP Numbers”

    Now, JMP can easily get ten thousand new SMS-enabled numbers in a day.  So can almost any other carrier or reseller.  If there is no physical device that needs to be handed over (such as with VoIP , eSIM , and similar services), the natural tarpit is gone and all that is left is the prices and policies of the provider.  JMP has many times received requests to help with getting “10,000 numbers, only need them for one day”.  Of course, we do not serve such customers.  JMP is not here to facilitate abuse, but to help create a gateway to the phone network for human beings whose contacts are still only found there.  That doesn’t mean there are no resellers who will work with such a customer, however.

    So now the targets are in a pickle if they want to keep using this strategy.  If the abuser can get ten thousand SMS-enabled numbers a day, and if it doesn’t cost too much, then it won’t work as a tarpit at all!  So many of them have chosen a sort of scorched-earth policy.  They buy and create heuristics to guess if a phone number was “too easy” to get, blocking entire resellers, entire carriers, entire countries.  These rules change daily, are different for every target, and can be quite unpredictable.  This may help when it comes to foiling the abusers, but is bad if you are a customer who just wants to create an account.  Some targets, especially “big” ones, have made the decision to lose some customers (or make their lives much more difficult) in order to slow the abusers down.

    De-anonymization

    Many apps and services also make money by selling your viewing time to advertisers (e.g. ads interspersed in a social media feed, as pre-/mid-roll in a video, etc.) based on your demographics and behaviour.  To do this, they need to know who you are and what your habits are so they can target the ads you see for the advertisers’ benefit.  As a result, they have an incentive to associate your activity with just one identity, and to make it difficult for you to separate your behaviour in ways that reduce their ability to get a complete picture of who you are.  Some companies might choose to use SMS verification as one of the ways they try to ensure a given person can’t get more than one account, or for associating the account (via the provided phone number) with information they can acquire from other sources, such as where you are at any given time .

    Can I make a new account with JMP numbers?

    The honest answer is, we cannot say.  While JMP would never work with abusers, and has pricing and incentives set up to cater to long-term users rather than those looking for something “disposable”, communicating that to every app and service out there is a big job.  Many of our customers try to help us with this job by contacting the services they are also customers of; after all, a company is more likely to listen to their own customers than a cold-call from some other company. The Soprani.ca project has a wiki page where users keep track of what has worked for them, and what hasn’t, so everyone can remain informed of the current state (since a service may work today, but not tomorrow, then work again next week, it is important to track success over time).

    Many customers use JMP as their only phone number, often ported in from their previous carrier and already associated with many online accounts.  This often works very well, but everyone’s needs are different.  Especially those creating new personas which start with a JMP number find that creating new accounts at some services for the persona can be frustrating to impossible.  It is an active area of work for us and all other small, easy-access phone network resellers.

    • wifi_tethering open_in_new

      This post is public

      blog.jmp.chat /b/2022-sms-account-verification

    • chevron_right

      Isode: Cobalt 1.3 Release Features

      news.movim.eu / PlanetJabber · Thursday, 9 February, 2023 - 13:42 · 2 minutes

    Cobalt 1.3 depends on M-Vault 19.0 or subsequent versions

    M-Vault Management Supporties

    • M-Vault Bootstrap.   Enables operation in conjunction with M-Vault 19.0 to support headless bootstrap.
    • Managing users in M-Vault groups, such as Directory Server Administrators  and Messaging Configuration Read/Write.  This enables Cobalt to control user and operator rights to access M-Vault.
    • AD/LDAP passthrough support
      • Allow users (per domain) to support mandatory or partial passthrough
      • Set and validate passthrough entry for user
      • Identify users in passthrough server that might be added to domain

    Messaging Management

    • Profile Editor for supporting and managing M-Switch Profiler.
      • SIC Coverage UI. Provide full list of SICS, showing which addresses each one goes to.   This enables operator to ensure that all SICs are sensibly handled.
    • File Transfer By Email capability is now managed by Cobalt, replacing capability previously in MConsole.
    • For Organizations and Military DLs enable control manage capability functions:
      • Max Message Size
      • Max Line Length (for ACP 127 destinations)
      • Charset Restrictions (for ACP 127 destinations)
      • Allows/block attachments
    • Option to show for a user which DLs the user is in, and give easy addition to other DLs.  This facilitates managing DL membership.

    New Views

    • Non-Human Users (Special Users).  Need to support accounts with passwords that are not humans.   For XMPP, Email or both.
    • View for end users, rather than administrators.  User can:
      • Change password.
      • See all of own entry and modify  attributes.   The list of modifiable attributes can be configured.
      • See references to entry and email list membership.
    • User Groups, to enable management of directory groups (Distinguished Names).

    Cobalt Access Control

    • New Cobalt roles, that can enable selective control of which users can access directory admin controls, and which users can set OAUTH rights and can add OAUTH Clients.
    • Restrict Password set/change rights, so that only selected Cobalt administrators can do this.

    Security Enhancements

    • When deleting a user, remove the password.   This will make it safe for applications searching whole DIT as you can’t authenticate with a deleted user’s account.
    • Security Clearance can be selected for any role or user, based on a configured catalogue.  This supports key M-Switch and Harrier feature to check clearances.

    Miscellaneous

    • When assigning a new email, search entire DIT for conflicts, not just Cobalt area.   This  helps SASL resilience
    • Can add Photos to Routed UAs and Organizations.
    • Check References on Delete. Cobalt has a “References” button on user/role form that displays all references of a user/role.  On deleting, references are deleted as well.
    • Tool to check references to users in AD, so that when users in AD are deleted, dangling references can be picked up.
    • Remove default domain concept
    • On deletion of domain in Cobalt, give option to delete all the domain data
    • Option to end all  cobalt logged in sessions of an operator, to allow an operator to logout from all browsers with a single action
    • There is also an option for an operator with appropriate rights  to end sessions of another Cobalt operator.
    • wifi_tethering open_in_new

      This post is public

      www.isode.com /company/wordpress/cobalt-1-3-release-features/

    • chevron_right

      Erlang Solutions: Elixir, 7 steps to start your journey

      news.movim.eu / PlanetJabber · Thursday, 9 February, 2023 - 10:44 · 3 minutes

    Read this post in Spanish .

    Let’s talk about Elixir!

    Elixir is a functional programming language created by José Valim to build concurrent and scalable systems. It is defined as:

    “a dynamic, functional language for building scalable and maintainable applications”.

    https://elixir-lang.org/

    Its first version was released in 2012. Since then, new features and improvements have been added until its current version . It is a relatively young programming language that has established itself quickly due to its nice syntax and short learning curve. Also, it is supported by a technology that has been working since the eighties in production systems, the BEAM.

    Elixir runs on the BEAM, Erlang’s virtual machine.

    In a later blog post, we’ll go into more detail about the virtual machine. For now, I want to mention a few features that make the BEAM a solid technology and a fantastic choice for system development. For example:

    • It simultaneously supports millions of users and transactions.
    • It has a mechanism to detect failures and define strategies that allow a system to recover from them.
    • It has all the necessary elements to develop a system capable of operating without interruptions or, failing that, with the minimum of them.
    • It allows system updates in real-time without stopping and in an “invisible” way for end users.

    Elixir inherits all these properties from BEAM. Adding to it that-the language has a very nice syntax, it is easy to learn, there are many resources (blogs, podcasts, etc), and the community is very friendly. So creating a project from scratch to start practicing requires very little time and effort.

    I was introduced to Elixir by chance in 2018. The project I learned it with made me suffer a bit because it was a different experience than what I was used to until then. But once I got into the rhythm, it became pretty enjoyable. Sometime last year, I wondered what would have happened if I hadn’t discovered it by coincidence.

    Would Elixir have caught my attention on its own? Is it a recommended option for someone learning to program? Do you require previous experience?

    So I posted a tweet asking other developers:

    Here are some answers :

    It is not easy to reach a definitive conclusion since choosing this language, as the first option will depend on the tastes and experiences of the individual. Some of its advantages are mentioned in the tweet replies, which motivated me to write this series.

    Without further ado, I welcome you to the series Elixir, 7 steps to start your journey.

    Throughout seven chapters, we’ll talk a bit about history, relevant technical aspects and delve into why Elixir has quickly gained popularity. I will also tell you a little about my experience in the projects in which I have participated.

    What topics will it cover?

    1. Erlang’s virtual machine, the BEAM
    2. Understanding processes and concurrency
    3. Libraries and frameworks
    4. Testing and debugging
    5. The Elixir Community
    6. Functional Programming vs. Object-Oriented Programming
    7. My first project with Elixir!

    Who is this series for?

    • People with no experience in any programming language looking for an option to explore.
    • People with previous experience in other programming languages who want to experiment with Elixir.

    Difficulty level: Beginner

    Elixir official documentation:

    In each chapter, I’ll share resources to dig deeper into the topics. You can find me on Twitter as @loreniuxmr to clarify questions or continue the conversation. You can also use the hashtags #MyElixirStatus and #Elixirlang  to find other Elixir developers.

    The next post will be about Erlang’s virtual machine, the BEAM, and why it is so relevant when it comes to Elixir. See you!

    The post Elixir, 7 steps to start your journey appeared first on Erlang Solutions .

    • chevron_right

      Erlang Solutions: Elixir, 7 pasos para iniciar tu viaje

      news.movim.eu / PlanetJabber · Thursday, 9 February, 2023 - 10:44 · 3 minutes

    ¡Hablemos de Elixir!

    Elixir es un lenguaje de programación funcional creado por José Valim para construi sistemas concurrentes y escalables.

    “a dynamic, functional language for building scalable and maintainable applications”.

    https://elixir-lang.org/

    Su primera versión fue liberada en 2012. Desde entonces, se le han agregado nuevas funcionalidades y mejoras hasta llegar a su versión actual . Se trata de un lenguaje de programación relativamente joven, pero bien establecido y que ha ganado aceptación rápidamente gracias su sintaxis agradable y una curva de aprendizaje corta. Elixir está respaldado por una tecnología que ha estado en funcionamiento en sistemas reales desde los años ochenta, la BEAM.

    Elixir corre sobre la máquina virtual de Erlang, la BEAM.

    Más adelante entraremos en más detalles y hablaremos de la máquina virtual. Por ahora me gustaría mencionar algunas características que hacen de la BEAM una tecnología sólida y una gran opción para el desarrollo de sistemas. Por ejemplo:

    • Soporta simultáneamente millones de usuarios y transacciones .
    • Tiene un mecanismo para detectar fallos y te permite definir estrategias para recuperarse de ellos.
    • Te brinda todos los elementos necesarios para desarrollar sistemas capaces de operar sin interrupciones o, en su defecto, con el mínimo de ellas.
    • Permite hacer actualizaciones de un sistema en tiempo real sin detenerlo, y de manera “invisible” para los usuarios finales.

    Elixir hereda todas estas propiedades de la BEAM. Y a eso le sumamos que el lenguaje tiene una sintaxis bastante agradable, es fácil de aprender, existen muchos recursos (blogs, podcasts, etc) y la comunidad es increíble. Así que crear un proyecto desde cero para practicar y aprender require de muy poco tiempo y esfuerzo.

    Conocí Elixir por casualidad en 2018. El proyecto con el que lo aprendí me hizo sufrir un poco, porque se trataba de un lenguaje totalmente diferente a los que había conocido hasta ese entonces (orientados a objetos) pero mi experiencia una vez que descubrí todo lo que había se volvió muy disfrutable. En algún momento del año pasado me pregunté qué hubiera pasado de no haberlo descubierto por coincidencia.

    ¿Me hubiera llamado la atención en algún momento? ¿Es una opción recomendada para alguien que está aprendiendo programación? ¿Requiere experiencia previa?

    Así que le pregunté en Twitter a otros desarrolladores :

    A continuación algunas respuestas:

    Es difícil llegar a una conclusión definitiva, pues escoger este lenguaje como primera opción o no dependerá de los gustos y la experiencia de cada quien. Algunas de las respuestas hablan acerca de las ventajas de este lenguaje de programación y fueron la razón que me motivo a escribir esta serie.

    Así que sin más que decir, bienvenido a Elixir, 7 pasos para iniciar tu viaje.

    A lo largo de siete capítulos hablaremos un poco acerca de su historia, aspectos técnicos relevantes y por qué ha ganado popularidad rápidamente. También te contaré cómo ha sido mi experiencia en los proyectos en los que he participado.

    ¿Qué temas cubrirá?

    1. La máquina virtual de Erlang, la BEAM
    2. Entendiendo procesos y concurrencia
    3. Bibliotecas y frameworks
    4. Pruebas y debugging
    5. La comunidad de Elixir
    6. Programación funcional vs Programación orientada a objetos
    7. ¡Mi primer proyecto con Elixir!

    ¿A quién está dirigida esta serie?

    • Personas sin experiencia en ningún lenguaje de programación que están en busca de su primera opción para explorar.
    • Personas con experiencia previa en otros lenguajes de programación que quieran experimentar con Elixir.

    Nivel de dificultad: Principantes.

    Documentación oficial de Elixir:

    En cada capítulo te compartiré recursos para profundizar los temas. Puedes encontrarme en Twitter como @loreniuxmr para aclarar cualquier duda o seguir con la conversación. Y también puedes utilizar los siguientes hashtags para conectar con otros desarrolladores: #MyElixirStatus y #Elixirlang

    En la próxima nota hablaremos de la máquina virtual de Erlang, la BEAM y por qué es tan relevante cuando hablamos de Elixir. ¡Nos vemos!

    The post Elixir, 7 pasos para iniciar tu viaje appeared first on Erlang Solutions .

    • chevron_right

      Ignite Realtime Blog: Denial of Service Vulnerability in Smack 4.4 if XMPPTCPConnection is used with StAX

      news.movim.eu / PlanetJabber · Saturday, 3 December, 2022 - 14:42 · 2 minutes

    The fantastic folks behind Jitsi have discovered a Denial of Service (DoS) vulnerability in Smack ( JSA-2022-0002 , JSA-2022-0003 ), which is possible if a combination of Smack components is used. The root of the vulnerability is interesting because it is due to a countermeasure against DoS attacks, namely FEATURE_SECURE_PROCESSING of the Java API for XML Processing (JAXP).

    The DoS is possible because the older XMPPTCPConnection implementation of Smack parses the XMPP stream as one large XML document. Suppose the connection instance uses a parser where FEATURE_SECURE_PROCESSING is enabled. In that case, it is easy for an attacker to craft a stanza that triggers one of the various limits imposed by FEATURE_SECURE_PROCESSING, causing an exception, leaving the parser in an unrecoverable state, and closing the connection.

    This vulnerability was relatively recently introduced in Smack with the addition of the support for JAXP’s Streaming API for XML (StaX) parser. Historically, Smack only used XPP3 as XML pull parser. The default implementation of XPP3 is a fast, lightweight, and, to the best of our knowledge, secure parser. XPP3 is used, for example, by Android. However, with version 4.4.0 ( SMACK-591 ), Smack gained support for using Java’s Streaming API for XML (StAX) in addition to XPP3, to facilitate code-reuse on Java SE platforms and avoiding the XPP3 dependency.

    So this DoS is possible if the XMPP connection is of type XMPPTCPConnection and if the Smack connection instance uses a StAX parser for XMPP parsing.

    On a related note, Smack’s newer modular connection architecture is not affected by this, because it splits the individual top-level XMPP stream elements and parses them as standalone document. The splitting is done very early in the input processing step by XmlSplitter (of jxmpp ), which also enforces size limits for the XML elements. Therefore, the DoS is not possible over connections that are established via Smack’s modern ModularXmppClientToServerConnection .

    If you are affected, then the following countermeasures are possible:

    1. Relax the FEATURE_SECURE_PROCESSING_LIMITS
    2. Switch to XPP3 (smack-xmlparser-xpp3)
    3. Use ModularXmppClientToServerConnection

    Option A has the drawback that it is only possible to relax the limits globally. That is, it will affect XML processing regardless if Smack or some other component performs it. If you still want to go down that route, then

    System.setProperty("jdk.xml.entityExpansionLimit", "0")
    System.setProperty("jdk.xml.maxOccurLimit", "0")
    System.setProperty("jdk.xml.elementAttributeLimit", "0")
    System.setProperty("jdk.xml.totalEntitySizeLimit", "0")
    System.setProperty("jdk.xml.maxXMLNameLimit", "524288")
    System.setProperty("jdk.xml.entityReplacementLimit", "0")
    

    1 post - 1 participant

    Read full topic

    • wifi_tethering open_in_new

      This post is public

      discourse.igniterealtime.org /t/denial-of-service-vulnerability-in-smack-4-4-if-xmpptcpconnection-is-used-with-stax/92314

    • chevron_right

      Gajim: Gajim 1.5.4

      news.movim.eu / PlanetJabber · Saturday, 3 December, 2022 - 00:00 · 1 minute

    Gajim 1.5.4 comes with a reworked file transfer interface, better URL detection, message selection improvements, and many fixes under the hood. Thank you for all your contributions!

    What’s New

    Gajim’s interface for sending files has been reworked, and should be much easier to use now. For each file you’re about to send, Gajim will generate a preview. This way, you can avoid sending the wrong file to somebody. Regardless of how you start a file transfer, be it drag and drop, pasting a screen shot, or simply clicking the share button, you’ll always be able to check what you’re about to send.

    Gajim’s new file transfer interface

    Gajim’s new file transfer interface

    More Changes

    • Performance: Chat history is now displayed quicker
    • Support for Jingle XTLS has been dropped, since it hasn’t been standardized
    • geo:-URIs are now prettier (thanks, @mjk )
    • Dependencies: pyOpenSSL has been replaced by python-cryptography

    Fixes

    • Fixes for message selection
    • Improvements for recognizing URLs ( @mjk )
    • Many fixes to improve Gajim’s usability

    Over 20 issues have been fixed in this release. Have a look at the changelog for a complete list.

    Gajim

    As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab .

    • wifi_tethering open_in_new

      This post is public

      gajim.org /post/2022-12-03-gajim-1.5.4-released/

    • chevron_right

      Erlang Solutions: Advent of Code 2022 – Every Puzzle Solved in Erlang

      news.movim.eu / PlanetJabber · Thursday, 1 December, 2022 - 10:33 · 9 minutes

    Day 1

    Christmas is getting closer and with that, the annual Advent of Code begins. For those who do not know, Advent of Code is a fun and inclusive event which provides a new programming puzzle every day. The fun is that these puzzles can be solved in any programming language and are accessible for varying levels of coding experience and skills. The real test is in your problem-solving. This year, we’ll be solving each of the problems in Erlang and publishing the results. We hope you enjoy it – if you’ve come up with a different solution and want to discuss it with us, we encourage you to comment on Twitter.

    The code will be added to the repo here: https://github.com/aleklisi/AdventOfCode2022 as I manage to solve each next puzzle.

    Day 1

    Full problem description: https://adventofcode.com/2022/day/1

    The example input file:

    1000
    2000
    3000
    
    4000
    
    5000
    6000
    
    7000
    8000
    9000
    
    10000
    

    Puzzle 1

    We are given a file with a list of values for calories in snacks carried by elves. The Elves take turns writing down the number of Calories contained in the various snacks that they’ve brought with them, one item per line . Each Elf separates its own inventory from the previous Elf’s inventory (if any) by a blank line. So the first task is to read and parse the data and decide how to represent it.

    I decided to represent the input as a list of two-element tuples, where each tuple stores the elf’s number and a list of snacks. Here is an example data representation for the example file:

    [
      {1,[1000,2000,3000]},
      {2,[4000]},
      {3,[5000,6000]},
      {4,[7000,8000,9000]},
      {5,[10000]}
    ]
    

    Now we just need to define a max function, which compares elements based on the sum of elements in a list of the calories in the snacks. I assumed that the list of elves is not empty, so I start with its first element as the current max and then started comparisons with other elves. Every time I find an elf with a bigger calorie sum I replace my current elf with the new one so that I will end up with the elf with the highest calorie total. Once the elf with the most calories is found, we can return the sum of calories.
    See the code: https://github.com/aleklisi/AdventOfCode2022/blob/main/day1_puzzle1/src/day1_puzzle1.erl#L48-L56 .

    Puzzle 2

    The only difference in puzzle 2 compared to puzzle 1 is that now we need to find 3 elves with the most calories total instead of just 1 elf and sum their calories altogether.

    We can heavily rely on solutions from puzzle 1.

    To find the top 3 elves I will just:

    1. Find the elf with the highest calories and save this elf as the first one.
    2. Remove the first elf from the list of elves.
    3. Find the next top elf with the highest calories from the list of elves (without the first elf) and save this elf as the second one.
    4. Remove the second elf from the list of elves.
    5. Find the next top elf with the highest calories from the list of elves (without the first and second elf) and save this elf as the third one.
    6. Return the sum of calories of the first, second and third elf.

    Voila!

    Day 2

    Day 2 of Advent of Code sees us helping the Elves to score a game of Rock, Paper, Scissors. The Elves have provided us with a strategy guide and it’s our job to help them score their game.

    Puzzle 1

    To complete the task we need to calculate the results of the above games. Since the games are unrelated (the result of previous games does not impact the next games, the best way to approach the problem is to start by implementing a single game’s score count function and then map a list of games with this function, to get the scores for each of the games. To get the final score (which is a sum of the games’ scores) we then sum all of the elements of the list.

    The data structure I decided to use to represent a single game is a two element tuple, where the first element is the opponent’s move and the second element is my move.

    The list of games is parsed into something like this:

    [{rock, rock},
                  {scissors, rock},
                  {scissors, rock},
                  {scissors, rock},
                  {paper, paper},
    	…
    ]
    

    Looking back (after solving the problem) I could have used maps with a structure like the one below:

    	#{my_move = > rock, opponent_move => paper}
    

    It might have helped me debug and avoid errors, which I did when first approaching the problem. That error was to confuse my move with my opponent’s move. In other words, I decoded A, B and C to be my moves and  X, Y, and Z to be my opponent’s moves. It is an obvious mistake when you spot it, but easy oversight when reading the puzzle’s description fast. I obviously had to read the description carefully 2 more times to spot my mistake, so as we say in Polish: “the cunning one loses twice”.

    Both parsing and solving today’s puzzle heavily rely on pattern matching, so let’s see that in action.

    Firstly, let’s take a look at how the data is decoded using pattern matching:

    % "The first column is what your opponent is going to play:
    % A for Rock,
    % B for Paper,
    % C for Scissors.
    translate_opponent_move("A") -> rock;
    translate_opponent_move("B") -> paper;
    translate_opponent_move("C") -> scissors.
    
    % The second column, you reason, must be what you should play in response:
    % X for Rock,
    % Y for Paper,
    % Z for Scissors.
    translate_my_move("X") -> rock;
    translate_my_move("Y") -> paper;
    translate_my_move("Z") -> scissors.
    

    A smart observer might notice that I could have used a single function to handle that translation, but I find dividing the decoding into two separate functions much more readable.

    Now let’s take a look at how scoring can be conveniently calculated:

    count_games_score({OpponentMove, MyMove}) ->
        count_shape_score(MyMove) + count_result_score(OpponentMove, MyMove).
    
    % The score for a single round is the score for the shape you selected (
    % 1 for Rock,
    % 2 for Paper,
    % 3 for Scissors
    count_shape_score(rock) -> 1;
    count_shape_score(paper) -> 2;
    count_shape_score(scissors) -> 3.
    
    % ) plus the score for the outcome of the round (
    % 0 if you lost,
    % 3 if the round was a draw, 
    % 6 if you won
    % ).
    count_result_score(rock, scissors) -> 0;
    count_result_score(paper, rock) -> 0;
    count_result_score(scissors, paper) -> 0;
    count_result_score(OpponentMove, MyMove) when MyMove == OpponentMove -> 3;
    count_result_score(scissors, rock) -> 6;
    count_result_score(rock, paper) -> 6;
    count_result_score(paper, scissors) -> 6.
    

    Again a keen observer might notice that it could be done in a single function, but I think most people will agree that translating the specifications one-to-one is way more convenient and much easier to understand and possibly debug if the need arises.

    The solution can be found here: https://github.com/aleklisi/AdventOfCode2022/tree/main/day2_puzzle1

    Puzzle 2

    Puzzle two introduces a plot twist. It turns out that the second part of the input for each of the games is not what we are supposed to play, but the expected game result. We need to figure out what to play, based on what our opponent’s move is and the expected result. Notice that the game score count does not change, so if we determine what we have played based on the new understanding of input and provide parsing output to follow the same rules as we did in today’s puzzle 1 when doing the parsing, the rest of the code should work correctly without any change.

    Let’s now see how to achieve that in practice.

    In the `read_and_parse_data/1` function I modified the anonymous function inside a map function to translate the predicted result into my move:

            fun(RawGame) ->
                [OpponentMoveRaw, GameResultRaw] = string:split(RawGame, " "),
                OpponentMove = translate_opponent_move(OpponentMoveRaw),
                GameResult = translate_result(GameResultRaw),
                MyMove = find_my_move(OpponentMove, GameResult),
                {OpponentMove, MyMove}
            end

    And this is the implementation of the translating functions:

    % "The first column is what your opponent is going to play:
    % A for Rock,
    % B for Paper,
    % C for Scissors.
    translate_opponent_move("A") -> rock;
    translate_opponent_move("B") -> paper;
    translate_opponent_move("C") -> scissors.
    
    % The second column says how the round needs to end:
    % X means you need to lose,
    % Y means you need to end the round in a draw,
    % Z means you need to win.
    translate_result("X") -> lose;
    translate_result("Y") -> draw;
    translate_result("Z") -> win.
    
    find_my_move(OpponentMove, draw) -> OpponentMove;
    find_my_move(rock, lose) -> scissors;
    find_my_move(paper, lose) -> rock;
    find_my_move(scissors, lose) -> paper;
    find_my_move(rock, win) -> paper;
    find_my_move(paper, win) -> scissors;
    find_my_move(scissors, win) -> rock.
    

    Again they heavily rely on pattern matching.

    The solution can be found here: https://github.com/aleklisi/AdventOfCode2022/tree/main/day2_puzzle2

    Conclusions after completing day 2

    Firstly, ALWAYS carefully read the requirements, and do not skip any part, because you find it “obvious”.

    Secondly, pattern matching is a great tool to have, it allows us to easily implement readable code.

    And last but not least, if you struggle or get stuck with something, it helps to add readable printing/logging to your code. When my implementation of `find_my_move/2` function (when solving puzzle 2) did not work. I added the following printing debug to the parsing data function:

    
    …
    MyMove = find_my_move(OpponentMove, GameResult),
                io:format("OpponentMoveRaw: ~p\t", [OpponentMoveRaw]),
                io:format("OpponentMove: ~p\t", [OpponentMove]),
                io:format("GameResultRaw: ~p\t", [GameResultRaw]),
                io:format("MyMove: ~p\t", [MyMove]),
                io:format("GameResult: ~p\t", [GameResult]),
                io:format("Result Score: ~p\n", [count_games_score({OpponentMove, MyMove})]),
                {OpponentMove, MyMove}
    …
    

    Which for the test file:

    A X
    A Y
    A Z
    B X
    B Y
    B Z
    C X
    C Y
    C Z
    

    Results with the following output:

    OpponentMoveRaw: "A"	OpponentMove: rock	GameResultRaw: "X"	MyMove: scissors		GameResult: lose	Result Score: 3
    OpponentMoveRaw: "A"	OpponentMove: rock	GameResultRaw: "Y"	MyMove: rock		GameResult: draw	Result Score: 4
    OpponentMoveRaw: "A"	OpponentMove: rock	GameResultRaw: "Z"	MyMove: paper		GameResult: win	Result Score: 8
    OpponentMoveRaw: "B"	OpponentMove: paper	GameResultRaw: "X"	MyMove: rock		GameResult: lose	Result Score: 1
    OpponentMoveRaw: "B"	OpponentMove: paper	GameResultRaw: "Y"	MyMove: paper		GameResult: draw	Result Score: 5
    OpponentMoveRaw: "B"	OpponentMove: paper	GameResultRaw: "Z"	MyMove: scissors		GameResult: win	Result Score: 9
    OpponentMoveRaw: "C"	OpponentMove: scissors	GameResultRaw: "X"	MyMove: paper		GameResult: lose	Result Score: 2
    OpponentMoveRaw: "C"	OpponentMove: scissors	GameResultRaw: "Y"	MyMove: scissors		GameResult: draw	Result Score: 6
    OpponentMoveRaw: "C"	OpponentMove: scissors	GameResultRaw: "Z"	MyMove: rock		GameResult: win	Result Score: 7
    

    Which I found extremely helpful when finding the mistake. It turned out that instead of:

    % …
    find_my_move(rock, lose) -> scissors;
    find_my_move(paper, lose) -> rock;
    find_my_move(scissors, lose) -> paper;
    % …
    

    I had:

    % …
    find_my_move(rock, lose) -> paper;
    find_my_move(paper, lose) -> rock;
    find_my_move(scissors, lose) -> paper;
    % …
    

    In the event that I was unable to locate my mistake, I would recommend implementing unit tests, hoping not to duplicate the mistake there.

    That’s it for day 2. Come back on Monday for the solutions to the weekend’s puzzles as well as Monday’s solution.

    The post Advent of Code 2022 – Every Puzzle Solved in Erlang appeared first on Erlang Solutions .