Al menos en mi Ubuntu, los mensajes "demasiado similares" aparecen cuando: "... más de la mitad de los personajes son diferentes ..." (ver más abajo para más detalles). gracias al soporte de PAM, como se explica claramente en la respuesta @slhck.
Para otra plataforma, donde no se utiliza PAM, los mensajes "demasiado similares" aparecen cuando: "... más de la mitad de los caracteres son diferentes ..." (ver más abajo para más detalles)
Para verificar esta declaración por su cuenta, es posible verificar el código fuente. Aquí es cómo.
El programa "passwd" está incluido en el paquete passwd:
verzulli@iMac:~$ which passwd
/usr/bin/passwd
verzulli@iMac:~$ dpkg -S /usr/bin/passwd
passwd: /usr/bin/passwd
Como estamos tratando con tecnologías de código abierto, tenemos acceso ilimitado al código fuente. Conseguirlo es tan simple como:
verzulli@iMac:/usr/local/src/passwd$ apt-get source passwd
Después es fácil encontrar el fragmento de código relevante:
verzulli@iMac:/usr/local/src/passwd$ grep -i -r 'too similar' .
[...]
./shadow-4.1.5.1/NEWS:- new password is not "too similar" if it is long enough
./shadow-4.1.5.1/libmisc/obscure.c: msg = _("too similar");
Una comprobación rápida de "obscure.c" muestra esto (estoy cortando y pegando solo el fragmento de código relevante):
static const char *password_check (
const char *old,
const char *new,
const struct passwd *pwdp)
{
const char *msg = NULL;
char *oldmono, *newmono, *wrapped;
if (strcmp (new, old) == 0) {
return _("no change");
}
[...]
if (palindrome (oldmono, newmono)) {
msg = _("a palindrome");
} else if (strcmp (oldmono, newmono) == 0) {
msg = _("case changes only");
} else if (similar (oldmono, newmono)) {
msg = _("too similar");
} else if (simple (old, new)) {
msg = _("too simple");
} else if (strstr (wrapped, newmono) != NULL) {
msg = _("rotated");
} else {
}
[...]
return msg;
}
Entonces, ahora, sabemos que hay una función "similar" que se basa en el antiguo y el nuevo para verificar si ambos son similares. Aquí está el fragmento:
/*
* more than half of the characters are different ones.
*/
static bool similar (const char *old, const char *new)
{
int i, j;
/*
* XXX - sometimes this fails when changing from a simple password
* to a really long one (MD5). For now, I just return success if
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
if (strlen (new) >= 8) {
return false;
}
for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
if (strchr (new, old[i]) != NULL) {
j++;
}
}
if (i >= j * 2) {
return false;
}
return true;
}
No he revisado el código C. Me limité a confiar en el comentario justo antes de la definición de la función :-)
La diferenciación entre las plataformas con reconocimiento PAM y NO PAM se define en el archivo "obscure.c" que está estructurado de la siguiente manera:
#include <config.h>
#ifndef USE_PAM
[...lots of things, including all the above...]
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */