# Seguridad

> Diseño previsto; aún no implementado.

## Qué es y qué no es

Sunfish es **deliberadamente sencillo**: HTTP y FTP **en claro**, para que funcione con
cualquier cliente, incluidos los de hace treinta años. Está pensado para **redes de confianza**
(una LAN doméstica, un taller, una red temporal).

- **Las contraseñas** (HTTP Basic, FTP, panel de administración) y los ficheros **viajan sin
  cifrar**: cualquiera en la misma red puede verlos.
- **Para compartir con seguridad** por redes que no son de confianza, existe un proyecto aparte
  con cifrado y claves por usuario; Sunfish no intenta cubrir ese caso.

Lo que sí se protege es el **servidor y su disco** frente a peticiones malintencionadas.

## Medidas

### Acceso al disco

- **Validación de rutas** común a web, FTP y WebDAV
  ([SHARES-Y-RUTAS.md](SHARES-Y-RUTAS.md#validación-de-rutas)): nada fuera de la carpeta del
  share, ni con `..`, ni con rutas absolutas, ni con enlaces simbólicos.
- **Permisos de escritura desactivados por defecto** en cada share; solo se activan
  explícitamente.
- **Subidas a fichero temporal** y renombrado al final; tamaño máximo opcional.
- **Se elimina la ejecución de programas** en el servidor (existía en la 2.0).
- **No requiere administrador:** el proceso tiene solo los permisos del usuario que lo ejecuta.

### Web

- **Todo texto** que se escribe en HTML o XML se escapa.
- **Ningún cambio por GET.** Crear, renombrar, borrar, subir y todo el panel son POST (o
  PUT/DELETE/MKCOL/MOVE en WebDAV).
- **Anti-CSRF sin cookies** (los navegadores antiguos pueden no tenerlas): cada formulario lleva
  un *token*. El token es un HMAC-SHA256 de (acción, share, ruta, hora en bloques de una hora)
  con una clave aleatoria generada en cada arranque. Otra web no puede leerlo, así que no puede
  falsificar el formulario.
- **Cabeceras** `X-Content-Type-Options: nosniff` y `Content-Security-Policy` sencilla en modo
  moderno.
- **El HTML subido a un share se sirve tal cual** (es la función "servir una web"), así que un
  share con `Upload` y `Listing` permite publicar páginas. Se avisa en la interfaz al activar las
  dos cosas a la vez.

### Contraseñas

- **Se guardan con PBKDF2-SHA256** (`Rfc2898DeriveBytes.Pbkdf2`), con sal y muchas iteraciones.
  La 2.0 guardaba la del panel en claro.
- **Caché de credenciales:** HTTP Basic reenvía la contraseña en cada petición, así que las ya
  verificadas se guardan en memoria (como HMAC, no en claro) durante un tiempo, para no
  recalcular PBKDF2 cada vez.
- **Intentos fallidos:** retardo creciente y bloqueo temporal por IP, en web, FTP y panel.

### Panel de administración

- **Desactivado por defecto.** Necesita contraseña y una IP incluida en `AllowFrom` (por defecto,
  solo el propio equipo).
- **Cambiar la contraseña o `AllowFrom`** desde el panel exige la actual.
- **No se puede dejar fuera a quien lo cambia:** una lista `AllowFrom` que no incluya la
  dirección desde la que se está conectado se rechaza.
- El panel no cambia el HTTP (puerto, interfaces): eso queda para quien tiene la aplicación.

### Red y recursos

- `Bind` permite limitar las interfaces de escucha (p. ej. solo la de la LAN).
- **Límites** de conexiones por IP, de tamaño de cabeceras, plazos de inactividad y peticiones
  por conexión.
- **FTP:**
  - modo activo solo hacia la IP del cliente y a puertos ≥ 1024;
  - rango de puertos pasivos acotado.
- **WebDAV:** sin `PROPFIND` de profundidad infinita; XML sin DTD.
- **ZIP de carpetas:** se puede desactivar por share (`Zip`), porque una carpeta enorme supone
  mucho trabajo de disco.

## Problemas de la 2.0 que se corrigen

| 2.0 | 3 |
|---|---|
| `Path.Combine(base, ruta)` sin validar: se podía salir del share | Validación común y comprobación de la ruta real |
| Nombres de fichero sin escapar en el HTML | Escapado siempre |
| Borrar y renombrar por GET | POST con *token* |
| Requería administrador; lo ejecutado heredaba la elevación | Sin administrador; sin ejecución |
| Contraseña del panel en claro en la configuración | PBKDF2 |
| 402 para "prohibido" | 403 |
