Consejos de seguridad para usar Facebook de forma responsable.

Si en su momento ya hice una entrada de consejos de seguridad generales en la red para proteger la privacidad de tus cuentas, ahora toca uno específico para Facebook.

  • No añadas a lo loco a gente que no conoces, hay muchas cuentas que pretenden hacerse pasar por una persona que quiere amistad o sexo para luego estafarnos o extorsionarnos.
  • Si tienes que aceptar a alguien por «compromiso» puedes dejar a esa persona con acceso limitado para que solo vea lo que pones como público. Y recuerda que el que compartas algo solo para tus contactos no garantiza al 100% que esto no pueda acabar siendo visto por alguien que no querías que lo viera, así que si dudas mejor no compartas.
  • Usa siempre una contraseña fuerte. Lo mejor es que uses un gestor de contraseñas. Si no quieres usarlo entonces recuerda: nunca menos de 11 dígitos y con mayúsculas, minísculas, números y símbolos. Aunque no hayas detectado ningún ataque, cámbiala al menos cada cuatro meses. Y si sospechas que se ha visto comprometida, no pierdas ni un minuto en hacerlo. No la compartas con otras personas y no utilices para FB la misma que para el correo electrónico que tengas asociado.
  • Si usas un equipo en una ubicación pública (cibercafé, centro social, instituto, universidad, biblioteca), o en el ordenador de otra persona, cierra siempre la sesión. No basta con cerrar el navegador, la sesión persiste, y aunque confiéis en la buena fe de la otra persona, ello no implica que la seguridad de su equipo no esté expuesta. Por eso, antes de cerrar el navegador, id a Salir de vuestra cuenta (en el menú de vuestra cuenta).
  • Ojito con el phishing. Comprobad en la barra de direcciones que la dirección es correcta, y que no sea http://www.facbook.com o http://www.bacefook.com o similar. Hay páginas con direcciones que suenan parecidas a la de Facebook creadas expresamente para robar tus datos, fíjate bien en la dirección.
  • Cuidado con los permisos que te piden la aplicaciones. Todo el caso de Cambridge Analítica vino de ahí, de aplicaciones que accedian a datos de terceros por culpa de usuarios que no tenían cuidado a la hora de unirse a estos juegos o tests.
  • Usa la navegación segura. Cuando la utilizas toda la transmisión de información se cifra, haciendo más complejos ciertos ataques. Para activarla debes hacerlo desde el apartado de Seguridad de la Configuración de Cuenta, donde basta marcar la casilla de Usar Facebook a través de una conexión segura siempre que sea posible y luego guardar los cambios. Si está activada verás como en la dirección el procolo cambia de http a https.
  • Si monitorizas la actividad de tu cuenta puedes saber si se ha accedido desde un dispositivo que no es el tuyo. En la sección de Seguridad de tu cuenta podéis ir a Notificaciones de inicio de sesión para que, si se accede desde un dispositivo que no haya sido usado antes para entrar a tu FB, te lo notifique al correo electrónico. También puedes comprobar ahí qué sesiones están activas, y saber si alguien más está conectado a tu cuenta.
  • Y otro punto que repito del anterior: Cuidado con la geolocalización, se pueden cruzar tus datos con los de otras redes y aplicaciones para saber dónde vives, por dónde te mueves…

Y recuerda que Facebook genera millones pero para el usuario es gratis. Piensa ¿De dónde sale la pasta? La minería de datos es uno de los grandes negocios de esta década, así que supón que lo más probable es que comercien con ellos, y ya los tenga alguna empresa china o estadounidense.

Tres herramientas libres para el cifrado de archivos

Como llevo unos días estudiando temas de seguridad (firma electrónica, VPN, algoritmos de encriptación, funciones de resumen…) es un buen momento para una corta entrada sobre herramientas para cifrar tus archivos. Voy a recomendar las que creo que son las tres mejores herramientas para encriptar tus archivos.

  • GPG o GNU Privacy Guard: Es la versión libre de PGP, y podéis descargarla desde este enlace. No sólo es ideal para el cifrado de archivos locales, e incluso de sistemas de discos enteros, sino también para el encriptado de comunicaciones. Permite el uso de pares de claves, firmas con tiempo limitado y esquemas de cifrado varios. Aunque en principio funciona en línea de comandos, existen varios plugins y entornos gráficos para el mismo, tanto en Linux como en Windows o MacOS.
  • True Crypt: Una de las más poderosas herramientas del mercado, se trata de una herramienta on-the-fly, que descrifa los archivos cuando los abres y los vuelve a cifrar cuando no están en uso. True Crypt es libre, gratis y está disponible para Linux, MacOS y Windows desde su web oficial. Está fuertemente optimizado para que la diferencia entre trabajar con un volumen cifrado y uno sin cifrar sea la menor posible. Permite cifrar tanto archivos como unidades enteras de disco, crear discos de seguridad virtuales y hasta crear volúmenes ocultos para mayor seguridad.
  • AxCrypt: En el caso de AxCrypt la utilidad es mayormente la de cifrar archivos sueltos o carpetas. Está disponible aquí para Windows y se integra en la shell del SO para que, con sólo hacer click derecho sobre un archivo, ya tengas la opción de Encriptar/Desencriptar. Permite además crear archivos autoextraíbles para transportarlos y transferirlos de forma segura, sin tener que tener instalado AxCrypt en el otro equipo.

Conste que si la idea es simplemente encriptar un archivo, el compresor 7zip te da la posibilidad de utilizar AES-256 para codificar el paquete ZIP, con lo que tus archivos estarán totalmente seguros.

En fin, con estas tres aplicaciones, no hay excusa para tener tus datos más confidenciales expuestos.

Dust – Hard Attack

Quería escribir sobre criptografía, pero estoy vago, así que creo que es un buen día para añadir un nuevo disco a la sección Joyas Musicales, que poco a poco crece.

Mi historia con este Hard Attack de los Dust es curiosa. Un día lo vi en una estantería de una tienda de discos, y la portada de Frank Frazzetta, que muestra a Conan peleando contra dos guerreros vanires me llamó la atención. Era épica, impactaba, muy chula pero ¿qué tal estaba el grupo?

Con esa portada uno podría esperarse a una especie de Manowar/Virgin Steele, una banda de heavy metal épico, pero si alguien se acerca a esta banda esperando a una suerte de Cirith Ungol va a llevarse una decepción o, en el mejor de los casos, una sorpresa. Porque estos Dust beben del rollito hippie sesentero, salpicado con gotas de Jethro Tull y los The Who más rockeros, recordándome por momentos a Wishbone Ash. La combinación de guitarra acústica con eléctrica es una constante en todo el trabajo, un discazo de 1972 que ejerció gran magisterio en el nacimiento del posterior heavy metal americano, junto a otras bandas como Steppenwolf o Grand Funk Railroad.

Este disco fue el segundo, y a la postre el último de esta banda, que a pesar de haber logrado dos trabajos excelentes siendo un grupo formado por miembros muy jóvenes, no lograron el éxito comercial. Eran un «power trio» (lo cual debía hacer complejo llevar los temas al directo con la gran cantidad de arreglos a dos guitarras que tienen) que se movía entre el rock más duro de la época con otras sonoridades más suaves. La base rítmica de la banda fueron los que mayor éxito cosecharon en su carrera posterior: Puede que el nombre del batería, Marc Bell, no te diga mucho, pero si te digo que en el ’78 se lo cambió por Marky Ramone ya sabes por dónde van los tiros. Por su parte, el excelente bajista Kenny Aaronson, que firma un espectacular trabajo a pesar de su corta edad (18 años en el primer disco y 20 en este) se ganó la vida como músico de gira y sesión, siendo votado en 1988 «Bajista del año» por la revista Rolling Stone, y trabajando para Bob Dylan, Billy Idol, Lita Ford, Foghat, Joan Jett, Sammy Haggar, Brian Setzer, Tony Iommy… en fin, un curriculum de esos de varias páginas.

Pasando ya al disco en si, se abre con la fantástica Pull Away, como ya he dicho cargada de reminiscencias a Jethro Tull, con una gran combinación de acústica con eléctrica. La sigue Walk in the Soft Rain donde de nuevo el sonido acústico vuelve a estar presente recordando un poco en su inicio al Bowie de la época. La balada Thusly Spoken, cargada de arreglos de cuerda y piano me parece el punto más flojo del disco, un tema al uso para intentar hacer caja, y que en su línea vocal me trae a la cabeza a Simon & Garfunkel. Pero tras la calma llega la tormenta con Learning to Die, un ataque de hard rock desenfrenado, casi rozando el rollo garajero, que evoluciona en un tema épico de casi 7 minutos con varias partes, un tema que podría estar perfectamente el cualquier disco de los primeros Led Zeppelin. All in All por su parte me recuerda a lo más agresivo de The Who con una pizca de la mala hostia de Cream. I been Thinkin nos ofrece un descanso tras la descarga más cañera, con suaves líneas sureñas sobre la base acústica. Pero tras este tema llega una selvática descarga digna de todo un Ted Nugent como es Ivory, un desenfrenado tema instrumental, que dará paso a una relajada How Many Horses, de nueva con toques de folk rock y rock sureño, incluso algo de soul, y un tremendo solo de por medias. Y finalmente el tema Suicide devuelve al primer plano la distorsión y el rock más duro, en la onda de Grand Funk Railroad, para terminar con el corto outro de menos de 30 segundos que es Entrances, una sucesión de acordes de influencia mediterránea.

Duraron poco estos Dust, pero no sería bueno olvidar el legado de una banda que en su corta existencia (1969-1972) nos regaló dos discos de tanta calidad. Este Hard Attack es un disco disfrutable por todo fan del rock setentero, de la época en la que las bandas podían hacer temas variados en sus discos y en la que no sonaban todos a copia de la copia. Tal vez no sean indispensables como Rainbow, Purple, Sabbath, Kiss o Zeppelin, pero cuando menos deberías darle una oportunidad a este disco.

Lubuntu 12.04 (faster than a bullet)

Faster than a bullet… así empieza el Painkiller de los Judas, y así se puede definir la versión de Ubuntu con escritorio LXDE. ¿Tienes un equipo viejo por casa que no es capaz de tirar con Windows Vista, 7 o con un Ubuntu normal? Dejarle un XP desactualizado, con todos sus agujerazos de seguridad por falta de actualizaciones, puede no ser una buena opción si pretendes navegar por internet con él. Cualquier experto en seguridad te lo dirá, el SO siempre actualizado a la última. ¿Quiere eso decir que hay que dejar el equipo morirse? No, Lubuntu te ofrece una alternativa ligera.

El sistema requiere como mínimo un Pentium II con 128 megas de RAM para arrancar. Con esta configuración debería ir un pelín justo, pero para lo básico ya furrula. Una curiosidad es que no incluye Firefox como navegador predeterminado, sino Chromium, por cuestiones de rendimiento (Firefox es más pesado). De hecho tampoco incluye Libre Office ni Open Office, sino una pequeña serie de programas ofimáticos más limitados pero con menor consumo. En todo caso, basta un apt-get install para hacerse con todo lo que queramos o, siendo más comodones, desde el gestor de aplicaciones.

Testeado sobre un máquina virtual de 1.5 GB de RAM primero, con instalación básica, y luego sobre una máquina física (1GB de RAM DDR2, Intel Centrino T2500 2GHZ) separando en 5 particiones (SWAP, /boot, /, /tmp y /home) el resultado es soprendentemente rápido.

A nivel de software dispondrás de todo el habido y por haber para Ubuntu, si bien ten en cuenta que si estás usando este sistema para tirar de máquina con pocos recursos, es posible que para cierto software andes justo en extremo (modificar una foto con GIMP 2.8 con 128 megas de RAM no se si es imposible pero harto complejo, seguro). En todo caso, si tu equipo tiene los mínimos para mover Ubuntu (que iría pelín lento y pesado en él), con Lubuntu lograrás que vaya como un tiro. Desde su gestor de aplicaciones, además, podrás instalar cómodamente todo el software libre que quieras. Y sobre seguridad, no te comes mucho la cabeza, todas las derivaciones de Ubuntu 12.04 son LTS (es decir, 5 años de actualizaciones de seguridad, tienes SO hasta abril de 2017 actualizado).

 

Lubuntu es una forma de revivir un viejo ordenador teniéndolo totalmente actualizado, o de mejorar tu rendimiento en un equipo que vaya justito. Realmente lo único es que tiene un entorno más feo que un Ubuntu normal, pero a nivel funcional igual hasta un usuario que venga de Windows se adapta mejor a LXDE que a Unity. En este vídeo puedes ver lo bien que furrula, y en este enlace descargarlo.

¿Qué tamaño doy a la partición boot?

Si ayer os hablaba de qué tamaño dar a la partición SWAP durante la instalación de Linux, hoy vamos con otra partición: La boot. En el caso de /boot no es obligatorio definirla, pero si la ubicas en una partición primaria al principio (después de la partición SWAP, que se recomienda que sea la primera) y le pones como sistema de archivos ext2 (más ligero que ext3 o ext4, que son los que habitualmente utilizaremos para el resto) lograrás una mayor velocidad de arranque. Que es posible que con ordenador muy potente no notes ninguna diferencia. En /boot se almacena el núcleo del sistema operativo y el sistema de arranque, así que no requiere mucho espacio.

Esto en caso de sistemas domésticos, porque cuando se trata de servidores con múltiples discos intercambiables o sistemas raid sí que puede volverse totalmente obligatorio tener el boot separado.

En todo caso ¿Qué tamaño le damos a /boot? Pues va dependiendo de la distribución de Linux y de si tenemos pensado tener varios kernels (ya sabéis que hay gente con el vicio de recompilarlo), pero en principio vamos a suponer un uso normal de usuario doméstico.

Todo esto lo comento basándome en lo leído en documentación y foros varios, y en alguna prueba doméstica con máquinas virtuales: para Ubuntu desde 10.10 hasta 11.10 dicen que 150 megas van sobrados, pero que para 12.04 mejor 250 . Para Debian 6 leo que se recomiendan 200. Para Fedora dicen que hasta  350, para ArchLinux leo que entre 100 y 150… Si tenéis un disco duro amplio lo mejor es no racanear y con 350 te aseguras no tener ningún problema de falta de espacio. La clave, como comentaba antes, está más en el sistema de archivos (ext2) y en ubicarla justo tras la SWAP.

¿Qué tamaño le asigno a la partición SWAP en Linux?

Si decides realizar una instalación manual en Linux ya sabes que necesitas al menos dos particiones: una para / y otra para el espacio de intercambio (SWAP). Aunque yo suelo hacer 4 particiones (/, swap, /boot y /home) para máquinas virtuales, y hasta 5 si el equipo va a usarse para editar vídeo, audio o trabajar con bases de datos muy grandes (ahí meto además separada /tmp); y tengo colegas que rara vez bajan de 7… (yo eso ya diría que es vicio). En todo caso suele surgir una duda ¿Qué espacio le asigno a SWAP durante la instalación?

Tradicionalmenet se decía «el doble de SWAP que lo que tengas de RAM«, pero es una teoría de los primeros tiempos de Linux, cuando los equipos andaban faltos de memoria. A día de hoy, tener 12 gigas de SWAP es una verdadera animalada, además de un desperdicio de recursos. Lo que sí se recomienda en varias páginas es que SWAP sea la primera partición del disco, por motivos de rendimiento.

Por lo que recomienda el señor Russell Coker la regla a seguir es la siguiente:

  • Si tienes hasta 1GB de RAM: El clásico «doble de SWAP que de RAM«
  • Si tienes entre 2GB y 4GB de RAM: Nueva teoría «La mitad de SWAP que de RAM«
  • Si tienes más de 4GB: Con 2 GB de SWAP vas que chutas.

Es más, si te fijas, todas las cuentas dan un máximo de 2GB de RAM. En fin, espero que esta minientrada te sea útil.

Cinco voces infravaloradas del rock

El éxito comercial y la repercusión no siempre son justos retribuyendo el talento de los músicos. Hoy he decidido hablar de cinco vocalistas que jamás han logrado que sus nombres suenen tanto como los de Halford, Dio, Paul Rodgers, Freddie Mercury o Ian Gillan. Esta es la lista de esas cinco voces olvidadas del rock:

Terry Reid: Ya hablé de él en la sección Joyas Musicales, reseñando su disco Seed of Memory. Vocalista y guitarrista inglés nacido en 1949, sus inicios apuntaban bien. Su primera banda profesional, The Jaywalkers, logró telonear a los Rolling Stones en Reino Unido. Tras esto llegó su primer disco en solitario, que aunque no tuvo mucho éxito comercial sí logró colocar un single en la radio bastante tiempo y hacer una gira con Cream en los EEUU. Rechazó el puesto de vocalista en Led Zeppelin para centrarse en su carrera, pero entonces la cosa empezó a tornarse en carrera maldita. No logró éxito comercial con ninguno de sus discos durante los 70, a pesar de haber tocado en festivales como el de la Isla de Wight en 1970, y se pasó la década dando tumbos y buscando siempre un camino. Tenía una voz cojonuda, pero parecía que los productores nunca le asesoraban bien, nunca sabían elegir sus singles, nunca le encauzaban a grabar las versiones correctas… Parecía que siempre estaba un paso por detrás del mercado musical. En 1981 dejó su carrera en solitario para convertirse en músico de sesión, no volviendo a retormala hasta una década después, donde de nuevo se queda a las puertas del éxito con una versión de Gimme Some Lovin’ de Steve Winwood que apareció en la BSO de Días de trueno, y con el tema The Whole of the Moon, haciendo un dúo con Enya. Tras eso se ha mantenido girando por USA, Reino Unido y Asia sin demasiada repercusión. En los 60 Aretha Franklin dijo de él que era «lo mejor de Reino Unido«, junto a los Beatles y los Stones, y la señora algo sabía de cantar. La voz de Reid puede recordar un poco a la de Robert Plant, pero con un timbre más grave, con una influencia soul similar a la de Glenn Hughes o Paul Rodgers.

Steve Grimmett: Este obeso vocalista, con pinta de ser el primo heavy de Meat Loaf, tal vez pagó el llegar tarde a la NWOBHM con sus Grim Reaper. Tras ganar una batalla de bandas grabaron su primer disco, See you in Hell,girando por USA y Reino Unido con bastante éxito para una banda debutante, llegando a actuar para más de 20.000 personas en el festival Texxas Jam!. Fear No Evil, con una producción mucho mejor, ya logró un cierto éxito comercial, en Alemania, UK y EEUU en 1985. Pero problemas legales con su sello discográfico provocó que Rock you to Hell se retrasara casi dos años y saliera a la venta a finales de 1987, cuando el heavy melódico que practicaban había caido en desgracia frente al thrash metal y al hard rock americano de pelos cardados. Aunque tenían ya material para un cuarto album que comenzó a grabarse, las peleas con el sello discográfico siguieron, llevándoles a separarse en 1988. Tras esto Grimmett se unió a los thrashers Onslaught, para grabar su disco más melódico In search of Sanity, y posteriormente sacaría adelante proyectos como Lionsheart (más hard rock) o Grimmstine (con un sonido muy en la onda de Grim Reaper) si demasiada repercusión, para acabar reuniendo a Grim Reaper de nuevo, logrando una cierta repercusión en festivales underground y de revival de la NWOBHM, pero con poca más chicha. Tiene un tono medio rasgado muy potente y es capaz de atacar partes muy agudas, la voz ideal para el heavy metal clásico.

Paul Shortino: También hablé de él en su día en este blog. Nacido en Las Vegas en 1953 nos sorprendió a todos en el vídeo de Stars del proyecto de Dio Hear ‘n Aid, mostrando una voz impresionante, y destacando en un vídeo donde cantaba junto a otros titanes del metal. En aquellos tiempos militaba en Rough Cutt, con los que grabó dos discos y un directo donde había poco que picar aparte de su voz. Tras Rough Cutt entró como mercenario en Quiet Riot, sustituyendo a un DuBrown ya inutilizado por las drogas y en una etapa de total hundimiento para la banda. En el 93 se metió en Bad Boyz, pero ya se había puesto de moda irse de poeta deprimido y no logró demasiada repercusión. Tras eso vinieron varios discos en solitario, duetos con otros artistas, colaboraciones mercenarias, una gira con Great White, otra con Carmine Appice y Javier Vargas y su entrada en los reformados King Kobra como vocalista. Su tono rasgado y multitud de registros hacen de él un vocalista capaz de moverse entre el blues clásico, el hard rock y el heavy metal con una gran versatilidad. Es cierto que su registro más agudo se ha visto afectado por los años, pero con todo sigue siendo un vocalista excelente.

Fin Muir: Nombre artístico del vocalista Ian More, y seguramente el menos conocido de los vocalistas aquí listados. Poco puedo aportar sobre este rockero escocés, porque poco más que su paso por los geniales y olvidados Waysted conozco. Esta banda, formada por Pete Way cuando dejó UFO, se enfocaba hacia un sonido más heavy que el de estos, aunque sin dejar de lado el rock. Fin se encargó de grabar el debut Vices, el EP Waysted y el disco The Good, The bad and the Waysted. Tras esto, y sin haber logrado mucho éxito, dejó el grupo, que sólo sacaría un disco más antes de separarse. Tras esto, y hasta la reunión de 2003 en la que volvió a la banda, no se qué fue de su vida, aparte de algún temilla en discos tributo. Con una voz potente pero extremadamente rasgada, se trata de uno de los vocalistas con más feeling del heavy británico de los 80, si bien las características de su garganta le permiten moverse por otros estilos como el blues, el funk o el rock, con grandes reminiscencias a la voz de Rod Stewart pero más agresivo. Uno de esos vocalistas capaces de ponerte los pelos de punta con su impresionante fuerza.

Mike Tirelli: Este italoamericano, neoyorkino de nacimiento, se ganó el apodo de «el metrosexual» cuando le descubrimos «por accidente» en un concierto de Riot en 2007. Llegamos a la sala sin saber quién era el cantante que sustituía a Mike DiMeo, y salimos de la sala preguntando dónde podíamos conseguir algo grabado por este cantante. No ha tenido suerte en la vida, ni con sus bandas ni con la salud, ya que un cáncer de estómago casi se lo lleva hace un par de años, y aunque salvó su vida se quedó en la ruina económica. Pero centrándonos en lo positivo este vocalista ha tenido destacadas actuaciones en bandas como los Burning Starr de Jack Starr, los rockeros Strider, los eclécticos Holy Mother o los powermetaleros Messiah’s Kiss. Por desgracia nunca grabó nada con Riot, pero en mi recuerda quedará aquel concierto en el que le descubrimos. Su voz es increíble, con un rango medio y agudo impresionante. Tiene unos medios poderosos y con cuerpo muy similares a los de Dio, pero pudiendo moverse hacia tonos más agudos, como los de Rob Halford. Siempre he pensado que él debió ser el vocalista elegido por Judas Priest en los 90 en lugar de Ripper Owens. Una de las voces más impresionantes del heavy metal, aunque jamás logró dejar el underground.

En fin, ya estás tardando en empezara escuchar a esta gente, y a descubrir algunas de las mejores voces del rock.

Programando un activity de Android para que se abra a una hora definida

Ya sea para una aplicación de despertador, para programar una actualización diaria, para hacer una app de notas de aviso… cuando desarrollamos una app para android es muy útil (y a veces indispensable) poder aprovechar para programar que una aplicación se lance a una determinada hora.

Suponiendo que ya sabes sobre desarrollo Android, la idea es simple: creas una activity que, al recibir un evento de calendario (con la hora concreta) lanza la otra activity en cuestión. Por ejemplo, «Quiero que todos los días a las 12:01 la aplicación se conecte a la base de datos y actualice la información».

El primer paso, lo dicho, es crear una clase que herede de BroadcastReceiver, sobreescribiendo su método onReceive:

public class Temporizador extends BroadcastReceiver{
@Override 
	public void onReceive(Context context, Intent intent)  { 
            Intent actividadALanzar = new Intent(context, actividadALanzar.class);
            context.startActivity(actividadALanzar);
	}
}

Debemos declarar esta clase en el Android Manifest, dentro de la etiqueta

<receiver  android:process=":remote" android:name="Temporizador"></receiver>

Lo siguientes es crear la pantalla principal y programar el evento, usando una clase PendingIntent:

Intent intentoLanzar = new Intent(getBaseContext(), Temporizador.class);
PendingIntent pIntent=PendingIntent.getBroadcast(this, 0, intentoLanzar, PendingIntent.FLAG_UPDATE_CURRENT);

Finalmente basta con crear un objeto calendario, con las horas definidas, y utilizar el AlarmManager para lanzar el intento pendiente a la hora prefijada (en este caso, estará pillando la hora actual):

Calendar cal = Calendar.getInstance(); 
cal.setTimeInMillis(System.currentTimeMillis());
cal.set (Calendar.HOUR_OF_DAY, timePicker.getCurrentHour()); 
cal.set (Calendar.MINUTE, timePicker.getCurrentMinute()); 
cal.set (Calendar.SECOND, 0);

AlarmManager aMan = (AlarmManager)getSystemService(ALARM_SERVICE); 
aMan.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pIntent); 

Aunque este método os permite hacer llamadas periódicas a la aplicación, esto no es recomendable por el excesivo consumo de energía. Los servicios se crearon para hacer eso de forma eficiente.

Usando SHA-1 en C y C++

Estaba trasteando en C estos días como ejercicio y se me ha ocurrido utilizar una función de resumen (hash) SHA-1. Como el tema es profundamente complejo, lo que he hecho ha sido buscar una ya creada, dado que al tratarde de un algoritmo creado en 1995 existen múltiples. Voy a compartir el que he encontrado por ahí que funciona bien:

/* sha1.c : Implementation of the Secure Hash Algorithm */

/* SHA: NIST's Secure Hash Algorithm */

/*	This version written November 2000 by David Ireland of 
	DI Management Services Pty Limited <code@di-mgt.com.au>

	Adapted from code in the Python Cryptography Toolkit, 
	version 1.0.0 by A.M. Kuchling 1995.
*/

/* AM Kuchling's posting:- 
   Based on SHA code originally posted to sci.crypt by Peter Gutmann
   in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
   Modified to test for endianness on creation of SHA objects by AMK.
   Also, the original specification of SHA was found to have a weakness
   by NSA/NIST.  This code implements the fixed version of SHA.
*/

/* Here's the first paragraph of Peter Gutmann's posting:
   
The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
SHA, thanks to Jim Gillogly and an anonymous contributor for the information on
what's changed in the new version.  The fix is a simple change which involves
adding a single rotate in the initial expansion function.  It is unknown
whether this is an optimal solution to the problem which was discovered in the
SHA or whether it's simply a bandaid which fixes the problem with a minimum of
effort (for example the reengineering of a great many Capstone chips).
*/

/* h files included here to make this just one file ... */

/* global.h */

#ifndef _GLOBAL_H_
#define _GLOBAL_H_ 1

/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;

/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;

/* BYTE defines a unsigned character */
typedef unsigned char BYTE;

#ifndef TRUE
  #define FALSE	0
  #define TRUE	( !FALSE )
#endif /* TRUE */

#endif /* end _GLOBAL_H_ */

/* sha.h */

#ifndef _SHA_H_
#define _SHA_H_ 1

/* #include "global.h" */

/* The structure for storing SHS info */

typedef struct 
{
	UINT4 digest[ 5 ];            /* Message digest */
	UINT4 countLo, countHi;       /* 64-bit bit count */
	UINT4 data[ 16 ];             /* SHS data buffer */
	int Endianness;
} SHA_CTX;

/* Message digest functions */

void SHAInit(SHA_CTX *);
void SHAUpdate(SHA_CTX *, BYTE *buffer, int count);
void SHAFinal(BYTE *output, SHA_CTX *);

#endif /* end _SHA_H_ */

/* endian.h */

#ifndef _ENDIAN_H_
#define _ENDIAN_H_ 1

void endianTest(int *endianness);

#endif /* end _ENDIAN_H_ */

/* sha.c */

#include <stdio.h>
#include <string.h>

static void SHAtoByte(BYTE *output, UINT4 *input, unsigned int len);

/* The SHS block size and message digest sizes, in bytes */

#define SHS_DATASIZE    64
#define SHS_DIGESTSIZE  20


/* The SHS f()-functions.  The f1 and f3 functions can be optimized to
   save one boolean operation each - thanks to Rich Schroeppel,
   rcs@cs.arizona.edu for discovering this */

/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) )          // Rounds  0-19 */
#define f1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )           /* Rounds  0-19 */
#define f2(x,y,z)   ( x ^ y ^ z )                       /* Rounds 20-39 */
/*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) )   // Rounds 40-59 */
#define f3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )   /* Rounds 40-59 */
#define f4(x,y,z)   ( x ^ y ^ z )                       /* Rounds 60-79 */

/* The SHS Mysterious Constants */

#define K1  0x5A827999L                                 /* Rounds  0-19 */
#define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
#define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
#define K4  0xCA62C1D6L                                 /* Rounds 60-79 */

/* SHS initial values */

#define h0init  0x67452301L
#define h1init  0xEFCDAB89L
#define h2init  0x98BADCFEL
#define h3init  0x10325476L
#define h4init  0xC3D2E1F0L

/* Note that it may be necessary to add parentheses to these macros if they
   are to be called with expressions as arguments */
/* 32-bit rotate left - kludged with shifts */

#define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )

/* The initial expanding function.  The hash function is defined over an
   80-UINT2 expanded input array W, where the first 16 are copies of the input
   data, and the remaining 64 are defined by

        W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]

   This implementation generates these values on the fly in a circular
   buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
   optimization.

   The updated SHS changes the expanding function by adding a rotate of 1
   bit.  Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
   for this information */

#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
                                                 W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )


/* The prototype SHS sub-round.  The fundamental sub-round is:

        a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
        b' = a;
        c' = ROTL( 30, b );
        d' = c;
        e' = d;

   but this is implemented by unrolling the loop 5 times and renaming the
   variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
   This code is then replicated 20 times for each of the 4 functions, using
   the next 20 values from the W[] array each time */

#define subRound(a, b, c, d, e, f, k, data) \
    ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )

/* Initialize the SHS values */

void SHAInit(SHA_CTX *shsInfo)
{
    endianTest(&shsInfo->Endianness);
    /* Set the h-vars to their initial values */
    shsInfo->digest[ 0 ] = h0init;
    shsInfo->digest[ 1 ] = h1init;
    shsInfo->digest[ 2 ] = h2init;
    shsInfo->digest[ 3 ] = h3init;
    shsInfo->digest[ 4 ] = h4init;

    /* Initialise bit count */
    shsInfo->countLo = shsInfo->countHi = 0;
}


/* Perform the SHS transformation.  Note that this code, like MD5, seems to
   break some optimizing compilers due to the complexity of the expressions
   and the size of the basic block.  It may be necessary to split it into
   sections, e.g. based on the four subrounds

   Note that this corrupts the shsInfo->data area */

static void SHSTransform( digest, data )
     UINT4 *digest, *data ;
    {
    UINT4 A, B, C, D, E;     /* Local vars */
    UINT4 eData[ 16 ];       /* Expanded data */

    /* Set up first buffer and local data buffer */
    A = digest[ 0 ];
    B = digest[ 1 ];
    C = digest[ 2 ];
    D = digest[ 3 ];
    E = digest[ 4 ];
    memcpy( (POINTER)eData, (POINTER)data, SHS_DATASIZE );

    /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
    subRound( A, B, C, D, E, f1, K1, eData[  0 ] );
    subRound( E, A, B, C, D, f1, K1, eData[  1 ] );
    subRound( D, E, A, B, C, f1, K1, eData[  2 ] );
    subRound( C, D, E, A, B, f1, K1, eData[  3 ] );
    subRound( B, C, D, E, A, f1, K1, eData[  4 ] );
    subRound( A, B, C, D, E, f1, K1, eData[  5 ] );
    subRound( E, A, B, C, D, f1, K1, eData[  6 ] );
    subRound( D, E, A, B, C, f1, K1, eData[  7 ] );
    subRound( C, D, E, A, B, f1, K1, eData[  8 ] );
    subRound( B, C, D, E, A, f1, K1, eData[  9 ] );
    subRound( A, B, C, D, E, f1, K1, eData[ 10 ] );
    subRound( E, A, B, C, D, f1, K1, eData[ 11 ] );
    subRound( D, E, A, B, C, f1, K1, eData[ 12 ] );
    subRound( C, D, E, A, B, f1, K1, eData[ 13 ] );
    subRound( B, C, D, E, A, f1, K1, eData[ 14 ] );
    subRound( A, B, C, D, E, f1, K1, eData[ 15 ] );
    subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) );
    subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) );
    subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) );
    subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) );

    subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) );
    subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) );
    subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) );
    subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) );
    subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) );
    subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) );
    subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) );
    subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) );
    subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) );
    subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) );
    subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) );
    subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) );
    subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) );
    subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) );
    subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) );
    subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) );
    subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) );
    subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) );
    subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) );
    subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) );

    subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) );
    subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) );
    subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) );
    subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) );
    subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) );
    subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) );
    subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) );
    subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) );
    subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) );
    subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) );
    subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) );
    subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) );
    subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) );
    subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) );
    subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) );
    subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) );
    subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) );
    subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) );
    subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) );
    subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) );

    subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) );
    subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) );
    subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) );
    subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) );
    subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) );
    subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) );
    subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) );
    subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) );
    subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) );
    subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) );
    subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) );
    subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) );
    subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) );
    subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) );
    subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) );
    subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) );
    subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) );
    subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) );
    subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) );
    subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );

    /* Build message digest */
    digest[ 0 ] += A;
    digest[ 1 ] += B;
    digest[ 2 ] += C;
    digest[ 3 ] += D;
    digest[ 4 ] += E;
    }

/* When run on a little-endian CPU we need to perform byte reversal on an
   array of long words. */

static void longReverse(UINT4 *buffer, int byteCount, int Endianness )
{
    UINT4 value;

    if (Endianness==TRUE) return;
    byteCount /= sizeof( UINT4 );
    while( byteCount-- )
        {
        value = *buffer;
        value = ( ( value & 0xFF00FF00L ) >> 8  ) | \
                ( ( value & 0x00FF00FFL ) << 8 );
        *buffer++ = ( value << 16 ) | ( value >> 16 );
        }
}

/* Update SHS for a block of data */

void SHAUpdate(SHA_CTX *shsInfo, BYTE *buffer, int count)
{
    UINT4 tmp;
    int dataCount;

    /* Update bitcount */
    tmp = shsInfo->countLo;
    if ( ( shsInfo->countLo = tmp + ( ( UINT4 ) count << 3 ) ) < tmp )
        shsInfo->countHi++;             /* Carry from low to high */
    shsInfo->countHi += count >> 29;

    /* Get count of bytes already in data */
    dataCount = ( int ) ( tmp >> 3 ) & 0x3F;

    /* Handle any leading odd-sized chunks */
    if( dataCount )
        {
        BYTE *p = ( BYTE * ) shsInfo->data + dataCount;

        dataCount = SHS_DATASIZE - dataCount;
        if( count < dataCount )
            {
            memcpy( p, buffer, count );
            return;
            }
        memcpy( p, buffer, dataCount );
        longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness);
        SHSTransform( shsInfo->digest, shsInfo->data );
        buffer += dataCount;
        count -= dataCount;
        }

    /* Process data in SHS_DATASIZE chunks */
    while( count >= SHS_DATASIZE )
        {
        memcpy( (POINTER)shsInfo->data, (POINTER)buffer, SHS_DATASIZE );
        longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness );
        SHSTransform( shsInfo->digest, shsInfo->data );
        buffer += SHS_DATASIZE;
        count -= SHS_DATASIZE;
        }

    /* Handle any remaining bytes of data. */
    memcpy( (POINTER)shsInfo->data, (POINTER)buffer, count );
    }

/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern
   1 0* (64-bit count of bits processed, MSB-first) */

void SHAFinal(BYTE *output, SHA_CTX *shsInfo)
{
    int count;
    BYTE *dataPtr;

    /* Compute number of bytes mod 64 */
    count = ( int ) shsInfo->countLo;
    count = ( count >> 3 ) & 0x3F;

    /* Set the first char of padding to 0x80.  This is safe since there is
       always at least one byte free */
    dataPtr = ( BYTE * ) shsInfo->data + count;
    *dataPtr++ = 0x80;

    /* Bytes of padding needed to make 64 bytes */
    count = SHS_DATASIZE - 1 - count;

    /* Pad out to 56 mod 64 */
    if( count < 8 )
        {
        /* Two lots of padding:  Pad the first block to 64 bytes */
        memset( dataPtr, 0, count );
        longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness );
        SHSTransform( shsInfo->digest, shsInfo->data );

        /* Now fill the next block with 56 bytes */
        memset( (POINTER)shsInfo->data, 0, SHS_DATASIZE - 8 );
        }
    else
        /* Pad block to 56 bytes */
        memset( dataPtr, 0, count - 8 );

    /* Append length in bits and transform */
    shsInfo->data[ 14 ] = shsInfo->countHi;
    shsInfo->data[ 15 ] = shsInfo->countLo;

    longReverse( shsInfo->data, SHS_DATASIZE - 8, shsInfo->Endianness );
    SHSTransform( shsInfo->digest, shsInfo->data );

	/* Output to an array of bytes */
	SHAtoByte(output, shsInfo->digest, SHS_DIGESTSIZE);

	/* Zeroise sensitive stuff */
	memset((POINTER)shsInfo, 0, sizeof(shsInfo));
}

static void SHAtoByte(BYTE *output, UINT4 *input, unsigned int len)
{	/* Output SHA digest in byte array */
	unsigned int i, j;

	for(i = 0, j = 0; j < len; i++, j += 4) 
	{
        output[j+3] = (BYTE)( input[i]        & 0xff);
        output[j+2] = (BYTE)((input[i] >> 8 ) & 0xff);
        output[j+1] = (BYTE)((input[i] >> 16) & 0xff);
        output[j  ] = (BYTE)((input[i] >> 24) & 0xff);
	}
}


unsigned char digest[20];
unsigned char message[3] = {'a', 'b', 'c' };
unsigned char *mess56 = 
	"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";

/* Correct solutions from FIPS PUB 180-1 */
char *dig1 = "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D";
char *dig2 = "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1";
char *dig3 = "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F";

/* Output should look like:-
 a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d
 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D <= correct
 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 <= correct
 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f
 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F <= correct
*/

main()
{
	SHA_CTX sha;
	int i;
	BYTE big[1000];

	SHAInit(&sha);
	SHAUpdate(&sha, message, 3);
	SHAFinal(digest, &sha);

	for (i = 0; i < 20; i++)
	{
		if ((i % 4) == 0) printf(" ");
		printf("%02x", digest[i]);
	}
	printf("\n");
	printf(" %s <= correct\n", dig1);

	SHAInit(&sha);
	SHAUpdate(&sha, mess56, 56);
	SHAFinal(digest, &sha);

	for (i = 0; i < 20; i++)
	{
		if ((i % 4) == 0) printf(" ");
		printf("%02x", digest[i]);
	}
	printf("\n");
	printf(" %s <= correct\n", dig2);

	/* Fill up big array */
	for (i = 0; i < 1000; i++)
		big[i] = 'a';

	SHAInit(&sha);
	/* Digest 1 million x 'a' */
	for (i = 0; i < 1000; i++)
		SHAUpdate(&sha, big, 1000);
	SHAFinal(digest, &sha);

	for (i = 0; i < 20; i++)
	{
		if ((i % 4) == 0) printf(" ");
		printf("%02x", digest[i]);
	}
	printf("\n");
	printf(" %s <= correct\n", dig3);

	return 0;
}

/* endian.c */

void endianTest(int *endian_ness)
{
	if((*(unsigned short *) ("#S") >> 8) == '#')
	{
		/* printf("Big endian = no change\n"); */
		*endian_ness = !(0);
	}
	else
	{
		/* printf("Little endian = swap\n"); */
		*endian_ness = 0;
	}
}

He dejado todos los comentarios, aunque se os pueda hacer coñazo, por respeto a los creadores originales. La función original la podéis consultar aquí.

Para C++ por otra parte, podéis disfrutar de la librería libre Crypto++ con múltiples algoritmos, que podéis encontrar en este enlace.

Instalación de OpenERP en Ubunto o Debian

OpenERP es una de las soluciones empresariales más populares dentro del software libre. Con una enorme escalabilidad, nos permite modificarlo para crear módulos específicos para las necesidades de una empresa determinada. Utiliza PostgreSQL como SGBD y está programado en Python, por lo que el conocimiento de este lenguaje será clave para la realización de módulos, aunque si ya has trabajado con C, Java o C# la sorpresa será mínima, incluso para programadores PHP (programadores, no diseñadores gráficos que hacen webs a base de Dreamweaver y módulos prefabricados). Pero el desarrollo de módulos puede que lo toquemos más adelante, hoy vamos con la instalación del servidor web de OpenERP 6.0 sobre Ubuntu o sobre Debian. Mayormente es una traducción de este artículo en inglés… bueno, una adaptación explicada con mis palabras.

Vamos al principio, first step, preparar el equipo para toda la instalación: instalar un servidor, crear el usuario, instalar Postgres… Ya sabes, por partes te lo pongo en el siguiente ejemplo:

#Preparar el servidor
apt-get install openssh-server denyhosts
apt-get update
apt-get dist-upgrade

#Crear el usuario
adduser –system –home=/opt/openerp –group openerp passwd openerp

#Instalamos PostgreSQL, creamos la base de datos y el usuario
apt-get install postgresql
su – postgres
createuser –createdb –username postgres –no-createrole –pwprompt openerp
exit

#Instalamos los paquetes y librerías de Python, que falta nos van a hacer (tochazo del 15)

apt-get install python python-psycopg2 python-reportlab python-egenix-mxdatetime python-tz python-pychart python-mako python-pydot python-lxml python-vobject python-yaml python-dateutil python-pychart python-pydot python-webdav

apt-get install python-cherrypy3 python-formencode python-pybabel python-simplejson python-pyparsing

Ahí estamos, todo el equipo listo para instalar OpenERP. La cuestión es descargar el server y el cliente web, descomprimir todo, dar permisos… En el ejemplo lo tenéis todo:


#Descargamos ambos paquetes
wget http://www.openerp.com/download/stable/source/openerp-server-6.0.3.tar.gz
wget http://www.openerp.com/download/stable/source/openerp-web-6.0.3.tar.gz

#Descomprimir, cambiar permisos... etc:
cd /opt/openerp
tar xvf ~/openerp-server-6.0.3.tar.gz
tar xvf ~/openerp-web-6.0.3.tar.gz
chown -R openerp: *
cp -a openerp-server-6.0.3 server
cp -a openerp-web-6.0.3 web

Ahora toca tocar el archivo de configuración del servidor, cambiando el password de la base de datos. En la carpeta /etc/ le metéis mano a openerp-server.conf con el editor Nano. Busca la línea db_password y allí añade la contraseña buena.

Tras esto, toca cambiar al propietario:

sudo chown openerp:root /etc/openerp-server.conf
sudo chmod 640 /etc/openerp-server.conf

Ahora toca crear, o modificar, el script para que arranque con el sistema, modificando /etc/initd.d/openerp-server, tal que así:

#!/bin/sh

### BEGIN INIT INFO
# Provides:             openerp-server
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Should-Start:         $network
# Should-Stop:          $network
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Enterprise Resource Management software
# Description:          Open ERP is a complete ERP and CRM software.
### END INIT INFO

PATH=/bin:/sbin:/usr/bin
DAEMON=/opt/openerp/server/bin/openerp-server.py
NAME=openerp-server
DESC=openerp-server

# Specify the user name (Default: openerp).
USER=openerp

# Specify an alternate config file (Default: /etc/openerp-server.conf).
CONFIGFILE="/etc/openerp-server.conf"

# pidfile
PIDFILE=/var/run/$NAME.pid

# Additional options that are passed to the Daemon.
DAEMON_OPTS="-c $CONFIGFILE"

[ -x $DAEMON ] || exit 0
[ -f $CONFIGFILE ] || exit 0

checkpid() {
    [ -f $PIDFILE ] || return 1
    pid=`cat $PIDFILE`
    [ -d /proc/$pid ] && return 0
    return 1
}

case "${1}" in
        start)
                echo -n "Starting ${DESC}: "

                start-stop-daemon --start --quiet --pidfile ${PIDFILE} \
                        --chuid ${USER} --background --make-pidfile \
                        --exec ${DAEMON} -- ${DAEMON_OPTS}

                echo "${NAME}."
                ;;

        stop)
                echo -n "Stopping ${DESC}: "

                start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \
                        --oknodo

                echo "${NAME}."
                ;;

        restart|force-reload)
                echo -n "Restarting ${DESC}: "

                start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \
                        --oknodo

                sleep 1

                start-stop-daemon --start --quiet --pidfile ${PIDFILE} \
                        --chuid ${USER} --background --make-pidfile \
                        --exec ${DAEMON} -- ${DAEMON_OPTS}

                echo "${NAME}."
                ;;

        *)
                N=/etc/init.d/${NAME}
                echo "Usage: ${NAME} {start|stop|restart|force-reload}" >&2
                exit 1
                ;;
esac

exit 0

Tras eso cambiamos los permisos a root:

chmod 755 /etc/init.d/openerp-server
chown root: /etc/init.d/openerp-server

#Con el directorio de logs hay que hacer lo mismo
mkdir /var/log/openerp
chown openerp:root /var/log/openerp

#Y finalmente añadimos el servicio para que se inicie con el sistema:
update-rc.d openerp-server defaults

Ahora podéis probar a arrancar y ver si todo furrula: sudo /etc/init.d/openerp-server start y si la cosa va bien, en el puerto 8080 debería haber una página de prueba.

Pero claro, ahora toca el cliente web. El proceso es similar, tenéis que meterle mano a cd /etc/openerp-web.conf.

server.environment = "development"

# Some server parameters that you may want to tweak
server.socket_host = "0.0.0.0"
server.socket_port = 8080

# Sets the number of threads the server uses
server.thread_pool = 10

tools.sessions.on = True
tools.sessions.persistent = False

# Simple code profiling
server.profile_on = False
server.profile_dir = "profile"

# if this is part of a larger site, you can set the path
# to the TurboGears instance here
#server.webpath = ""

# Set to True if you are deploying your App behind a proxy
# e.g. Apache using mod_proxy
#tools.proxy.on = True

# If your proxy does not add the X-Forwarded-Host header, set
# the following to the *public* host url.
#tools.proxy.base = 'http://mydomain.com'

# logging
#log.access_file = "/var/log/openerp-web/access.log"
log.error_file = "/var/log/openerp/openerp-web-error.log"
log.access_level = "INFO"
log.error_level = "INFO"

# Set to false to disable CSRF checks
tools.csrf.on = True

# replace builtin traceback tools by cgitb
tools.log_tracebacks.on: False
tools.cgitb.on: True
# a default install can probably avoid logging those via cgitb as they're
# available in the server log
tools.cgitb.ignore=(
    openobject.errors.Concurrency,
    openobject.errors.TinyException)

# OpenERP Server
openerp.server.host = 'localhost'
openerp.server.port = '8070'
openerp.server.protocol = 'socket'
openerp.server.timeout = 450

# Web client settings
[openerp-web]
# filter dblists based on url pattern?
# NONE: No Filter
# EXACT: Exact Hostname
# UNDERSCORE: Hostname_
# BOTH: Exact Hostname or Hostname_

dblist.filter = 'NONE'

# whether to show Databases button on Login screen or not
dbbutton.visible = True

# will be applied on company logo
company.url = ''

Tras esto, de nuevo toca cambiar propietarios:

chown openerp:root /etc/openerp-web.conf
chmod 640 /etc/openerp-web.conf

Tras esto tocará automatizar el cliente web también, tocando /etc/init.d/nano openerp-web y dejando la cosa tal como en el ejemplo:

#!/bin/sh

### BEGIN INIT INFO
# Provides:             openerp-web
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# Should-Start:         $network
# Should-Stop:          $network
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    OpenERP Web - the Web Client of the OpenERP
# Description:          Open ERP is a complete ERP and CRM software.
### END INIT INFO

PATH="/sbin:/bin:/usr/sbin:/usr/bin"
DAEMON="/opt/openerp/web/openerp-web.py"
NAME="openerp-web"
DESC="openerp-web"

# Specify the user name (Default: openerp).
USER=openerp

# Specify an alternate config file (Default: /etc/openerp-web.conf).
CONFIGFILE="/etc/openerp-web.conf"

# pidfile
PIDFILE=/var/run/$NAME.pid

# Additional options that are passed to the Daemon.
DAEMON_OPTS="-c $CONFIGFILE"

[ -x $DAEMON ] || exit 0
[ -f $CONFIGFILE ] || exit 0

checkpid() {
    [ -f $PIDFILE ] || return 1
    pid=`cat $PIDFILE`
    [ -d /proc/$pid ] && return 0
    return 1
}

case "${1}" in
        start)
                echo -n "Starting ${DESC}: "

                start-stop-daemon --start --quiet --pidfile ${PIDFILE} \
                        --chuid ${USER} --background --make-pidfile \
                        --exec ${DAEMON} -- ${DAEMON_OPTS}

                echo "${NAME}."
                ;;

        stop)
                echo -n "Stopping ${DESC}: "

                start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \
                        --oknodo

                echo "${NAME}."
                ;;

        restart|force-reload)
                echo -n "Restarting ${DESC}: "

                start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \
                        --oknodo

                sleep 1

                start-stop-daemon --start --quiet --pidfile ${PIDFILE} \
                        --chuid ${USER} --background --make-pidfile \
                        --exec ${DAEMON} -- ${DAEMON_OPTS}

                echo "${NAME}."
                ;;

        *)
                N=/etc/init.d/${NAME}
                echo "Usage: ${NAME} {start|stop|restart|force-reload}" >&2
                exit 1
                ;;
esac

exit 0

En fin, de nuevo sólo nos queda cambiar los permisos de propietario e incluir el script en el inicio, para que todo vaya como la seda:

chmod 755 /etc/init.d/openerp-web
chown root: /etc/init.d/openerp-web

update-rc.d openerp-web defaults

Y con todo esto, el servidor y el cliente web ya están listos para trastear con OpenERP en vuestro equipo.