La sentencia prohibida

Últimamente se han descubierto un par de errores bastante serios relacionados con la comprobación de certificados digitales. El primero de los casos saltó a la palestra cuando Apple trató de parchear de forma silenciosa parte del código nativo en los sistemas de Apple que valida los certificados digitales. En este caso a Apple se le “escapó” un goto fail; que prácticamente invalidaba la función de validación. Este sólo parece que afectaba a Safari dentro los navegadores más conocidos, ya que Firefox y Chrome usan sus propias rutinas de comprobación y no la nativa del sistema. Ya nuestros compañeros de Seguridad Apple se hicieron eco de la noticia en su día y si quieres saber un poco más dales una visita.

El otro error que ha aparecido más reciente, coincidentemente también tiene que ver con la verificación de certificados digitales, pero esta vez en sistemas Linux. La librería en cuestión es GnuTLS en el modulo (x509/verify.c) que verifica si el creador de un certificado digital es una autoridad certificadora. El error en este caso también usa sentencias goto. Aquí el problema es más bien de implementación y convención de código en lenguaje C. static int check_if_ca (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer, unsigned int flags) { int result; result = _gnutls_x509_get_signed_data (issuer->cert, “tbsCertificate”, &issuer_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signed_data (cert->cert, “tbsCertificate”, &cert_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; }

// snip

result = 0;

cleanup: // cleanup type stuff return result; }

El listado de arriba muestra el código con el error. En la primera comprobación, si el resultado es negativo, se produce un salto (goto cleanup;) a cleanup y se devuelve el contenido de la variable result. El problema es que en C el valor 0 (cero) se traduce a falso y cualquier otro valor distinto de 0 se interpreta como verdadero, ya sea el valor positivo o negativo, como es el caso que nos ocupa.

El código parcheado es el siguiente: int result; result = _gnutls_x509_get_signed_data (issuer->cert, “tbsCertificate”, &issuer_signed_data); if (result < 0) { gnutls_assert (); goto fail; // CHANGED }

// snip

fail: // ADDED result = 0;

cleanup: // cleanup type stuff return result; }

Ahora como vemos, cuando se produce un fail, se le asigna a la variable el valor 0.

Aunque en ninguno de los dos casos la utilización de instrucciones goto es la causante del drama, he visto en muchos blogs y foros clamando al cielo por el uso de dicha instrucción. Tienes más información en esta entrada.

[spam] Si quieres saber más sobre el origen del movimiento anti-goto, quién y el por qué, así como algunas anécdotas sobre esta polémica instrucción, no dudes en echar un vistazo al libro de Microhistorias: anécdotas y curiosidades de la Informática, dónde tienes una historia llamada La sentencia prohibida, que como puedes ver es el título que he usado para esta entrada.[/spam]