Contactar i els formularis web anònims

Blog
3/12/21
Lluís Turró Cutiller
29
0

En la majoria d'ocasions, els usuaris demanen un formulari de contacte a la seva web. En la majoria d'ocasions, també, s'acaben queixant de la quantitat d'spam que reben.

La primera pregunta que se'm passa pel cap és, i per què no donar un correu electrònic? I la resposta més habitual és, per evitar l'spam. És això cert? Evitem així l'spam? No i no.

Formulari web per usuaris no autenticats

Aquest seria un formulari de lliure accés per a visitants. Es compon d'un cert nombre de camps, el valor dels quals s'envia per correu a l'adreça internament configurada. Els principals punts en contra d'aquests formularis són:

  • El servidor de correus que envia els valors és allotjat dins la mateixa web o en un servei relacionat. Això fa que el contingut sempre sigui considerat com a fiable.
  • Marcar el servidor o servei com a spam via configuració, el fa innecessari. Perquè voldríem un servidor d'spam?
  • Encara que el formulari tingui un camp pel correu, aquest no es pot usar com adreça d'enviament. Si ho féssim, tots el missatges serien spam.

I usar un filtre intern d'spam?

Sí, es pot fer. De fet, molts servidors ja el tenen instal·lat pel correu entrant. El que estaríem fent és el mateix que faria el nostre servidor de correu quan rep aquest: decidir si passar-ho a la carpeta de brossa. En curt, repetiríem la feina dues vegades per cap motiu raonable.

I els Captcha?

Els Captcha no són realment filtres d'spam. El que fan és controlar que qui omple el formulari és un humà o un robot (un programa que repetitivament omple i envia). És un pedaç, no una solució.

La recomanació

Posar una adreça de correu electrònic a la web. Amb l'hiperenllaç que permeti fer clic i enviar, si es vol. Així de simple. I amb una llista de motius:

  • Les grans empreses gasten milers de recursos per detectar l'spam. Si estem usant serveis de correus en línia, tots aquests recursos van al nostre favor.
  • L'usuari que envia necessita tenir una adreça real, sinó ja no passarà el primer pas de detecció d'spam: el registre SPF.
  • Si així i tot ens arribés correu spam, podem marcar-lo com a tal i un servidor ben configurat ho recordarà.

N'hi ha més, però serien tecnicismes al voltant del que ja hem dit.

Algunes de les coses que han passat i no he dit

Blog
10/25/20
Lluís Turró Cutiller
167
0

En aquest repàs no ho tinc en compte tot, ni poso especial interès en l'ordre cronològic. Tampoc afecta en res el que veuràs.

Totes aquestes novetats, com tota la resta, incloses en l'estàndard. Sota codi font obert i completament gratuïtes.

Tot i no haver publicat massa cosa, ja veieu que aquí no es para. Els temps demanen això i més.

Tomcat virtual hosting with SSL

Blog
5/7/18
Lluís Turró Cutiller
5,842
2

This 2018 I needed to install an SSL Certificate for a web application. Since Tomcat 9 features virtual hosted web application with differentiated SSL hosts, the next step were easy to guess: move to Java 10 plus Tomcat 9 and make use of these new features. This article goes about the process to its final ending, this web site.

First issues when migrating

Java 9 and above no longer include JAXB. Simply add the JAXB library to Tomcat 9.

Tomcat 9 no longer put the final slash to the URL (does not redirect). Modify conf/context.xml to include mapper attributes:

<Context ... 
	 mapperContextRootRedirectEnabled="true" 
	 mapperDirectoryRedirectEnabled="true"/>

Requirements

  • Tomcat 9, although I've been told 8.5 also supported SSL host virtualization.
  • Java 8 or higher. This example has been tested with Java 10.

Elements used for this article

  • This web site, an open source web application.
  • A Comodo Essential Certificate.
  • A full weekend

Asking for the certificate

If you already have a certificate you may want to skip this part. Otherwise, buy a certificate and continue.

First thing the provider ask for is a Certificate Signing Request. Lets generate one:

openssl req -new -newkey rsa:2048 -nodes -out [yourdomain].csr -keyout [yourdomain].key -subj "/C=[country]/ST=[state]/L=[city]/O=[organization]/OU=[department]/CN=[domain]"

Field

Description

yourdomain

This will be the file name. For example www_domain_whatever, in my case www_turro_org.

country

Two uppercase letters of your country, see ISO 3166-1.

state

Your state or province, as is.

city

Your city.

organization

Your organization name.

department

Department managing de certificate.

domain

As for Comodo Essential, the domain will apply to www.[domain] and [domain] as longer as you use www..

Recomendation: use www.domain, in my case www.turro.org.

Once executed, this command generated two files, yourdomain.csr and yourdomain.key. The CSR file is the Certificate Signing Request, and is the first thing you will need to provide when asking your certificate. The second is the Private Key. Keep them both in a secure place.

Installing the certificate into a keystore

If everything has gone well, you now have a response from the Certification Provider and some certificates in you hard disk. Copy them where you saved previous generated files, CSR and private key. If you followed the instructions, you private key is stored in [yourdomain].key file.

Now, one of the certificates you received is your certificate. The rest are called root certificate and chain certificates.

Change to convenient format

First thing we'll do is convert your private key and your certificate to PKCS12 format. Don't bother now as to why we use this format, I want a single keystore to include the whole bunch of certificates to simplify Tomcat configuration, and it turns out that Tomcat NIO likes this format. So, have it.

openssl pkcs12 -export -in [yourcertificate] -inkey [yourdomain].key -name [yourdomain] -out [yourdomain].p12

Field

Description

yourcertificate

Your certificate is one of those the certification provider sent you. As for Comodo, my certificate was www_turro_org.crt, so it was easy to point out which one was mine.

yourdomain

This will be the file name. For example www_domain_whatever, in my case www_turro_org.

Import private key and certificates into the keystore

This step creates a new keystore file.

keytool -importkeystore -destkeypass [password] -destkeystore [yourdomain].keystore -srckeystore [yourdomain].p12 -srcstoretype PKCS12 -srcstorepass [password]

Now, add the root and chain certificates. Bellow the example with Comodo certificates. You may follow instructions provided for your own certificate provider. Notice that the only pattern used is alias equal to certificate file minus extension.

keytool -import -trustcacerts -alias AddTrustExternalCARoot -file AddTrustExternalCARoot.crt -keystore [yourdomain].keystore
keytool -import -trustcacerts -alias COMODORSAAddTrustCA -file COMODORSAAddTrustCA.crt -keystore [yourdomain].keystore
keytool -import -trustcacerts -alias COMODORSADomainValidationSecureServerCA -file COMODORSADomainValidationSecureServerCA.crt -keystore [yourdomain].keystore

If you followed the instructions, you have a keystore named [yourdomain].keystore with everything required by Tomcat.

Installing the keystore

Let's explain something about Tomcat. Tomcat has a single Connector for SSL configuration. Once you configure your keystore, it will be available by all the web application installed, but will only certificate your domain. So, where SSL hosting virtualization is?

Don't panic, there is SSL hosting virtualization. You achieve the goal by creating SSLHostConfig elements with hostName attribute set to match one of the Host elements its name attribute. One of them will need to be the defaultSSLHostConfigName attribute in the Connector element. Messy? See the server.xml example with the values we used:

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" 
           SSLEnabled="true"
           scheme="https"
           secure="true"
           defaultSSLHostConfigName="[domain]"
           
           ...

           >
    <SSLHostConfig hostName="[domain]">
        <Certificate certificateKeystoreFile="[yourdomain].keystore"
                     certificateKeystorePassword="[password]"/>
    </SSLHostConfig>

    ....

</Connector>

...

<Engine name="Catalina" defaultHost="[domain]">

  <Host name="[domain]"  appBase="/anyfolder" 
        unpackWARs="false" autoDeploy="false">
  </Host>

  ...

</Engine>

Let's suppose we followed the steps with [domain2] values. The server.xml will look like:

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" 
           SSLEnabled="true"
           scheme="https"
           secure="true"
           defaultSSLHostConfigName="[domain]"
           
           ...

           >
    <SSLHostConfig hostName="[domain]">
        <Certificate certificateKeystoreFile="[yourdomain].keystore"
                     certificateKeystorePassword="[password]"/>
    </SSLHostConfig>

    <SSLHostConfig hostName="[domain2]">
        <Certificate certificateKeystoreFile="[yourdomain2].keystore"
                     certificateKeystorePassword="[password2]"/>
    </SSLHostConfig>

    ....

</Connector>

...

<Engine name="Catalina" defaultHost="[domain]">

  <Host name="[domain]"  appBase="/anyfolder" 
        unpackWARs="false" autoDeploy="false">
  </Host>

  <Host name="[domain2]"  appBase="/anyfolder2" 
        unpackWARs="false" autoDeploy="false">
  </Host>

  ...

</Engine>

Now everything is more clear. [domain] is the default SSL configuration, but when somebody visits [domain2] there is a match between SSLHostConfig its hostName attribute and Host its name attribute. Thus, [yourdomain2].keystore will be used.

Restart your Tomcat and... That's all!

Detect the charset in Java strings

Blog
12/13/17
Lluís Turró Cutiller
30,313
0

Before start, I would like to mention Apache Tika and juniversalchardet. Tika is a full-featured file type detection library and, because so much features, takes a big amount of dependencies. I haven't tried juniversalchardet for does not detect ISO-8859-1, which is the reason I needed charset detection.

Since none well suited my problem, I decided to detect charsets myself and, once results were in production, share it with anyone else. Hope you like it

Why charset detection?

Anyone developing web applications with data inputs and third-party frameworks, with a different charset than UTF-8, might have encountered the need to auto-detect charset. Guessing the source of the input on utility classes, or passing the charset along among methods, doesn't seem to be the right way and isn't always possible.

Changing the string charset

We'll need a convert method, in order to change the string charset. The most simple way would be using String supplied methods. Something like:

public String convert(String value, String fromEncoding, String toEncoding) {
  return new String(value.getBytes(fromEncoding), toEncoding);
}

The problem remains, though. The variable fromEncoding isn't always known.

Charset guessing

Guessing? Well, let's be clear, we are guessing. Also taking some premises that might be not true. For instance, we probe using UTF-8 against a set of expected charsets. The good thing about it is that we know the elements at play and can change them at will.

The approach is very simple: if I do change the string from the expected charset to UTF-8 and then back from UTF-8 to the expected charset, shouldn't be the resulting string exactly the same than the original one?

Let's put this at work:

public static String charset(String value, String charsets[]) {
  String probe = StandardCharsets.UTF_8.name();
  for(String c : charsets) {
    Charset charset = Charset.forName(c);
    if(charset != null) {
      if(value.equals(convert(convert(value, charset.name(), probe), probe, charset.name()))) {
        return c;
      }
    }
  }
  return StandardCharsets.UTF_8.name();
}

A possible call to the charset() method would be:

String detectedCharset = charset(value, new String[] { "ISO-8859-1", "UTF-8" });

As I said, the approach uses the premise that UTF-8 will behave well on all transformations and that there is a reduced set of expected charsets. I haven't tried probing the whole Charset.availableCharsets(). In case you do and find a better way, please let me know.

Missatgeria i seguretat

Blog
10/12/17
Lluís Turró Cutiller
8,004
0

Aquests dies han estat tan elèctrics a Catalunya, que moltes persones s'han mostrat preocupades per la seguretat del seu sistema de missatgeria. Anem a donar una mirada ràpida als dos més utilitzats: WhatsApp i Telegram.

Mireu la data del text. Aquestes apps solen canviar sovint i el text no valdria per res.

Els missatges

WhatsApp entrega els missatges directament al receptor, sense que existeixin a cap servidor. Els servidors s'utilitzen exclusivament per resoldre el recipient del missatge (a qui s'envia).

Telegram, en canvi, utilitza els servidors per a fer l'enviament. El missatge, doncs, existeix al servidor.

Xats (persona a persona)

WhatsApp encripta per defecte els xats normals, persona a persona. El missatge s'encripta al enviar i es desencripta al rebre.

Telegram envia el text com a text pla, sense encriptar.

Xats de grup (grups de persones)

WhatsApp encripta per defecte els xats de grup.

Telegram utilitza text pla.

Xats privats (persona a persona)

WhatsApp no té xats privats com opció. Tots ho són.

Telegram encripta els xats privats, igualant-se així a WhatsApp, però amés ofereix configurar la durada del missatge. Els missatges s'esborren un cop passat el temps configurat.

Les còpies de seguretat

Les còpies de seguretat són un dels problemes més complexes de resoldre. Es fan no encriptades i contenen tots els missatges rebuts. Els xats privats de Telegram no permeten fer còpies.

La porta del darrera

Com ja suposareu, tota conversa passa per un servidor que resol on s'envia el text. Es podria "capturar" el text, llegir-lo, i després enviar-lo com si res.

La porta del darrera és possible en els xats i xats de grup de Telegram. Impossible en el cas de xats privats de Telegram.

Pel que fa a WhatsApp, caldria que s'introduís una clau pública diferent i només serviria per a nous missatges. Els canvis de clau pública a WhatsApp són transparents, excepte que s'activi Settings -> Account -> Security -> Show Security Notifications. Un cop activada aquesta opció, si hi hagués un canvi de clau, es notificaria amb un missatge. Aturaríem llavors la conversa, fins que la clau tornés a ser la mateixa.

Estic fet un embolic i no sé què fer

Ho entenc. Aquí quatre indicacions per anar ràpid:

Xats de grup i xats normals de persona a persona

Feu servir WhatsApp. És més segur. Per evitar que en un futur es puguin veure les converses, esborreu i demaneu que esborrin el contingut del xat.

Xats de persona a persona i contingut altament sensible

Feu servir el xat privat de Telegram i esborreu un cop acabat.

Conclusió

Recordeu que les converses normals queden al dispositiu. Si li agafen el dispositiu a un dels usuaris, l'altre o els altres quedaran al descobert. Esborreu els continguts.

No sé si us heu fixat, però no hi ha possibilitat de fer un xat de grup amb contingut altament sensible. Com a la vida real.