![]() | ![]() | Guía de programación de GNOME | ![]() |
---|
La seguridad es un tema complejo y en esta sección no se puede explicar ni de lejos todo lo relacionado. Intentaremos indicar las situaciones más comunes donde tus programas deben interesarse por la seguridad.
Es muy fácil crear hoyos de seguridad a través de la creación
incorrecta de archivos temporales en /tmp
.
Debes garantizar que los archivos que usarás no existen al
momento de su creación. Usar un nombre de archivo «único»
e «impredecible» no es suficiente; debes garantizar que el archivo
con ese nombre no será creado por alguien más entre el tiempo
en que se determina el nombre y el tiempo en que es efectivamente
creado (básicamente los ataques involucran que un tercero
cree un enlace simbólico al archivo que ellos quieren
sobreescribir).
Afortunadamente, esto es fácil de hacer. Usa el siguiente trozo de código:
char *filename; int fd; do { filename = tempnam (NULL, "foo"); if (!filename) { fprintf (stderr, "Could not create temporary file name\n"); exit (EXIT_FAILURE); } fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600); free (filename); } while (fd == -1);
Recuerde liberar filename usando la función
free()
y llamar a las funciones
close()
y unlink()
con el archivo respectivo cuando haya terminado; aquí
liberamos filename con free()
inmediatamente y así no causará una pérdida de memoria.
Si deseas usar la biblioteca estándar de E/S, puede usar la
función fdopen()
para transformar el
descriptor de archivo en FILE *, o puedes
usar la función tmpfile()
para hacerlo
en un solo paso.
Intenta no usar buffers de tamaño fijo. Los buffers de tamaño
fijo para cadenas constituyen los típicas fuentes de hoyos
explotables que pueden llegar a oscuros errores. Si definitivamente
debes usar buffers de tamaño fijo para cadenas, usa la función
g_snprintf()
para especificar el tamaño
máximo del buffer.
Glib proporciona la, muy conveniente, función
g_strdup_printf()
, la cual funciona como
sprintf()
pero automáticamente
localizará un buffer con el tamaño correcto. El valor de retorno
de esta función debiera ser liberada usando
g_free()
. A menudo es más conveniente de
usar que g_snprintf()
, ya que esta no
limita el tamaño de las cadenas que un programa puede manipular.
Si deseas concatenar un grupo de cadenas, puedes usar la función
g_strconcat()
, la cual recibe una lista
variable de cadenas y un puntero a NULL
como último argumento.
Bajo ninguna circunstancia crees un programa GTK+ con setuid root. Las bibliotecas de GTK+ y GNOME son grandes y complejas y no han tenido auditorías de seguridad. En cualquier caso, no debieras querer que una pieza tan grande código sea setuid root. Si definitivamente requieres usar privilegios de root para algo, escribe un programa que sea la interfaz de usuario como un proceso normal, sin privilegios y crea un programa nexo que tenga setuid y se encargue de realizar la operaciones «peligrosas». Además, notifica a las listas de correo de desarrollo de GNOME indicando que requieres que alguien realice una auditoría de seguridad a tu programa nexo.
En general, si no estás seguro si puedes crear un riesgo de seguridad, pregunte en las listas de correo de desarrollo de GNOME.
Puedes leer más sobre temas de seguridad que debieras encontrar cuando programes una aplicación Unix en el documento «Murphy's Law and Computer Security», de Wietse Wenema. Hay otros documentos de seguridad en el sitio fish.com que podrías encontrar interesante.
Puedes encontrar muchas otras guías útiles para escribir programas seguros en «Secure Programming for Linux and Unix HOWTO».
<< Corrección y robustez | Rendimiento >> |