miércoles, 17 de agosto de 2011

IIS se cae al habilitar extensión de PHP para Postgres

Intentando configurar un servidor web con PHP para que pudiera conectarse a Postgres me sucedía que al habilitar la extensión de postgres (quitando el ";" a la línea extension = php_pgsql.dll del php.ini) el servidor IIS se caía.

Al parecer este archivo en las versiones posteriores a la 5.2.5 hacen que el IIS falle. La solución fue sencilla: conseguir el archivo dll de alguna versión anterior de PHP, 5.2.5 o menos, y sustituirla en el directorio ext. Funciona sin problemas y ya puede conectarse a la base de datos PostgreSQL

miércoles, 20 de julio de 2011

Utilizando SSLSockets en un ambiente de prueba

He estado desarrollando una aplicación en Java que utiliza Sockets para la comunicación entre el cliente y el servidor. Inicialmente lo hice con Sockets normales, pero a la hora de pasarlo a SSLSockets me encontré con varios problemitas que complicaron la implementación, después de invesitgar un poco y hacer cambios a prueba y error logré hacerlo funcionar.

Siguiendo esta lista de pasos, podrás hacer funcionar tu aplicación con SSLSockets en un ambiente de pruebas donde quizás no tengas instalado un certificado SSL válido (Este post asume que conoces, al menos de manera general, qué es SSL y cómo funciona):


Servidor

Lo primero que se necesita hacer es crear un certificado SSL para el servidor, el cual será utilizado para establecer la comunicación con el cliente. Para la creación de este certificado se puede utilizar la herramienta keytool que viene en el JDK y en el JRE de Sun Microsystems.

Para crear este certificado corremos la siguiente instrucción:
keytool -genkey -keystore miKeyStore -alias unAlias -keypass clave -storepass claveDeKeyStore
-keystore genera un archivo que es el almacén de claves (KeyStore), en él se guardará el certificado autofirmado y el par de claves pública/privada. Si no especificamos este comando se creará un archivo en el directorio raíz del usuario con el nombre ".keystore".

-alias es el nombre con el que haremos referencia al par de claves creado.

-keypass es el password para acceder a la clave privada

-storepass es la clave para acceder al KeyStore


Para saber que escribir en cada una de los inputs que el programa esperará, o para conocer que otras características puedes utilizar con keytool puedes consultar alguno de estos links: http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=securitySSLKeytool o http://download.oracle.com/javase/1.3/docs/tooldocs/win32/keytool.html. Una vez creado el archivo deberá ser copiado en el directorio de trabajo donde correrá nuestro Servidor.

Ahora estamos listos para programar nuestro servidor en Java, el cual debiera ser algo similar a esto:

public class Servidor {
    public static void main(String args[]) {
      System.setProperty("javax.net.ssl.keyStore", "miKeyStore");
      System.setProperty("javax.net.ssl.keyStorePassword", "claveDeKeyStore");
      try {
        SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
        SSLServerSocket sss = (SSLServerSocket)ssf.createServerSocket(9999);

        SSLSocket s = (SSLSocket)sss.accept();
        LineNumberReader in = new LineNumberReader(new InputStreamReader(s.getInputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream());

        String linea = in.readLine();
        System.out.println(linea);
        out.println("respuesta");
        out.flush();
      } catch (Exception e) {e.printStackTrace();}
    }
}


No es estrictamente necesario incluir los setProperty en el código, pueden agregarse en la línea de comando al momento de correr el programa, de la siguiente manera:

java -Djavax.net.ssl.keyStore=miKeystore -Djavax.net.ssl.keyStorePassword=claveDeKeyStore Server

Aquí puede ser que tengas tu primer problema, y que al momento de correr el servidor obtengas el siguiente error:

java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)

Este error se debe a que no pudo obtenerse la clave del certificado y puede ser por varias razones, la más común es que no estés enviando la clave correcta o que no se encuentre el archivo especificado; pero si se tiene seguridad que no es debido a estos problemas, el error puede deberse a que indicaste una clave distinta en el keypass y el storepass. Como estamos en un ambiente de prueba podemos establecer ambos passwords con el mismo valor y de esta manera el error desaparecerá. Para implementarlo en un ambiente de producción, deberás programas un KeyManager ya que JSSE no provee una manera adecuada de especificar estos passwords a través de System Properties.


Cliente

El código para el cliente podría ser de la siguiente forma:

public class Cliente {

    public static void main(String args[]) {
      try {
        SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 9999);

        LineNumberReader in;
        PrintWriter out;
        in = new LineNumberReader(new InputStreamReader(s.getInputStream()));
        out = new PrintWriter(s.getOutputStream());

        out.println("hola");
        out.flush();
        System.out.println(in.readLine());

      } catch (Exception exception) { exception.printStackTrace(); }
    }
}

Pero muy probablemente obtendremos el siguiente error:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

Este error se debe a que el certificado que estamos utilizando no es un certificado SSL válido. El esquema utilizado por SSL es conocido como X.509 y Java utiliza un TrustManager para este esquema, llamado x509TrustManager. Para poder evitar este error tenemos que crear un TrustManager diferente que acepte todos los certificados y no nos genere un error y utilizar este para la creación del Socket. Nuestro código quedaría algo así:

public class Cliente {

    public static void main(String args[]) {
      try {
        X509TrustManager tm = new X509TrustManager() {  
          public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
          public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
          public X509Certificate[] getAcceptedIssuers() { return null; }
        };            

      SSLContext ctx = SSLContext.getInstance("TLS");
      ctx.init(null, new TrustManager[]{tm}, null);

      SSLSocketFactory sslsocketfactory = ctx.getSocketFactory();
      SSLSocket s = (SSLSocket) sslsocketfactory.createSocket("192.168.0.32", 9999);

      LineNumberReader in;
      PrintWriter out;
      in = new LineNumberReader(new InputStreamReader(s.getInputStream()));
      out = new PrintWriter(s.getOutputStream());

      out.println("hola");
      out.flush();
      System.out.println(in.readLine());

      } catch (Exception exception) {
      exception.printStackTrace();
      }
    }
}

Una vez hecho esto, nuestros dos procesos se comunicarán utilizando SSL sin problemas :).

lunes, 18 de julio de 2011

No se puede iniciar sesión localmente en un Windows SBS 2003

Al intentar entrar a un servidor Windows SBS 2003 de manera local con el usuario administrador me aparecía el mensaje "Las directivas locales de este sistema no le permiten iniciar una sesión interactiva", pero si podía ingresar al sistema desde una conexión remota. Después de revisar la ayuda en el sitio de Microsoft (http://support.microsoft.com/kb/841188/es) encontré que si el administrador pertenece al grupo Operadores Remotos (Remote Operators) no podrá ingresar de manera local, ya que por default en Windows SBS 2003 este grupo tiene denegado el acceso local al sistema.

Noté que este era mi caso y procedí a eliminar el usuario administrador del grupo Operadores Remotos. Excelente, ya podía ingresar al servidor de manera local, pero ya no podía hacerlo de manera remota.

¿Cómo hacer que el administrador pueda ingresar de manera remota y local al servidor? Esto no debería ser un problema, pero no sé por qué razón el administrador estaba en Operadores Remotos ni porque no me le daba acceso normal al quitarlo de ahi, pero la solución es sencilla:
  • Abrir el editor de objetos de directivas de grupo escribiendo en la línea de comandos gpedit.msc
  • Irse a Configuración del equipo -> Configuración de Windows -> Configuración de seguridad -> Directivas locales -> Asignación de derechos de usuario.
  • Encontrarás ahi la directiva "Permitir el inicio de sesión a través de Servicios de Terminal Server", darle doble click
  • Presionar el botón Agregar un usuario o grupo
  • Escribir el usuario o grupo que deseas agregar, asegúrate de incluir el nombre de dominio, por ejemplo: MiDominio\administrador

Con esto el administrador ya podrá ingresar de manera local y remota.

martes, 8 de marzo de 2011

Conexión ODBC en Windows 7

Deseaba configurar una máquina con Windows 7 para que pudiera conectarse a través de ODBC con un servidor SQL Server 2000, y a pesar que la configuración terminaba exitosamente, la aplicación no podía conectarse.

Me parecía raro también que al momento de configurar el ODBC no miraba la larga lista de drivers que normalmente miro sino que solamente me aparecía uno.

El problema era que mi versión del Windows es de 64 bits y existen dos aplicaciones administradoras de ODBC, una de 32-bits y otra de 64-bits. La versión de 32 bits se encuentra en la carpeta %systemdrive%\Windows\SysWow64 y la de 64bits se encuentra en %systemdrive%\Windows\System32.

La versión de 32 bits muestra el DSN de sistema de 32 bits, DSN de usuario de 32 bits y DSN de usuario de 64 bits. La versión de 64 bits muestra el DSN de sistema de 64 bits, DSN de usuario de 32 bits y DSN de usuario de 64 bits.

Así que corriendo la versión correcta del administrador, se puede solucionar el problema.

Más información en http://support.microsoft.com/kb/942976

Unir Windows 7 de 64 bits a un dominio Windows SBS 2003

Intenté unir una PC con Windows 7 a un dominio Windows SBS 2003 y no encontré mayor problema que instalar algunas actualizaciones en el Servidor administrador del dominio. Pero cierta computadora en particular me dió bastante guerra. Se lograba unir al dominio aunque al momento de hacerlo tiraba un mensaje de error mencionando algo del DNS.

Una vez que la computadora reiniciaba no había forma de que entrara con alguno de los usuarios del dominio, ni siquiera con el administrador. Después de mucho pelear con la computadora, se me ocurrió averiguar la diferencia que había entre esta computadora y las otras con Windows 7 que habían logrado unirse al dominio sin problemas (esto, porque asumí que el problema estaba relacionado con el Sistema Operativo, ya que nunca me dió ese tipo de problemas con XP).

La diferencia era (además de la marca de la computadora) que el sistema operativo era Windows 7 de 64 bits. No estoy totalmente seguro que está haya sido la causa del problema, pero independientemente de eso, lo importante era averiguar cómo resolverlo. Así que si te ha pasado algo similar y tu computadora, aunque se una al dominio, no te permite ingresar a ella con usuarios del dominio, esta fue la solución que yo encontré y me sirvió muy bien:

  • Instalar Support Tools que vienen en los CDs de tu Windows Server 2003
  • Ejecutar la aplicación ADSIEDIT.MSC que se encuentra en el directorio Support Tools
  • En el menú de la derecha seleccionar Domain -> DC = -> CN=Computers
  • Buscar la computadora afectada, presionar el botón derecho sobre ella y elegir Propiedades
  • Dar dobleclick en el campo ServicePrincipalName de la lista
  • Agregar el siguiente valor: HOST/nombrehost.dominio.xyz

Listo, al hacer esto, podrás ingresar en la computadora con cualquiera de los usuarios del dominio sin ningún problema.

viernes, 7 de enero de 2011

DNS cache en ISA Server

Cambié la dirección de uno de mis servidores y cuando intentaba accesar el sitio hospedado en él desde cualquier navegador nunca cargaba. Supuse que era problema de resolución de la dirección IP, así que me aseguré que la dirección se hubiera cambiado en el DNS.

Luego realicé un nslookup para chequear si el DNS devolvía la dirección correcta y si lo hacía. Al parecer solo los navegadores tenian este problema y seguían resolviendo la dirección anterior.

Después de revisar durante un rato, noté que el problema se daba solamente si estaba levantado el Cliente Firewall de ISA, así que supuse que el ISA Server manejaba algún tipo de caché para DNS y que me seguía devolviendo la dirección anterior.

En efecto, este era el problema, y la solución es sencilla: reiniciar el servidor ISA o limpiar el caché. Para limpiar el caché (o borrar solamente la entrada que está dando problemas) descargué el DNSTools para ISA Server, lo corrí, borré la entrada para la dirección antigua y listo, los clientes de mi red accesaron bien a la nueva dirección.