lunes, 30 de julio de 2007

SMF y Privilegios


Ha diferencia de las versiones anteriores de Solaris 6 y 7 donde para establecer privilegios teniamos que recurrir a software externo al sistema, como SUDO... y Solaris 8, 9 donde podiamos realizar este tipo de acciones con RBAC ya como parte del mismo. En Solaris 10 y OpenSolaris con la inclusión de SMF (Service Management Facility) la pespectiva cambia y podemos ser capaces de definir que usuario y que acciones puede realizar (parar, arrancar...) sobre un servicio del sistema que incluso levante un socket tcp/udp por debajo del puerto 1024 sin ser root.

En este ejemplo lo vamos a realizar con Apache2 gestionado como servicio a traves de SMF.

# svcs apache2
STATE STIME FMRI
disabled 19:12:02 svc:/network/http:apache2
# svcadm -v enable -s apache2
svc:/network/http:apache2 enabled.
# ps -aef | grep apache | grep -v grep
webservd 14836 14835 0 15:25:04 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 14837 14835 0 15:25:04 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 14839 14835 0 15:25:04 ? 0:00 /usr/apache2/bin/httpd -k start
root 14835 10895 0 15:25:03 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 14838 14835 0 15:25:04 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 14840 14835 0 15:25:04 ? 0:00 /usr/apache2/bin/httpd -k start
# ptree 14835
10895 zsched
14835 /usr/apache2/bin/httpd -k start
14836 /usr/apache2/bin/httpd -k start
14837 /usr/apache2/bin/httpd -k start
14838 /usr/apache2/bin/httpd -k start
14839 /usr/apache2/bin/httpd -k start
14840 /usr/apache2/bin/httpd -k start

Vemos como por defecto el proceso que realmente levanta el socket abierto en el puerto tcp 80 es iniciado como root y no tiene ningun tipo de privilegios.

# ppriv -S 14835
14835: /usr/apache2/bin/httpd -k start
flags =
E: zone
I: basic
P: zone
L: zone

Esto lo vamos a cambiar para el usuario webservd, asi:

# svcadm -v disable svc:/network/http:apache2
svc:/network/http:apache2 inhabilitado.
# svccfg -s apache2
svc:/network/http:apache2> setprop start/user = astring: webservd
svc:/network/http:apache2> setprop start/group = astring: webservd
svc:/network/http:apache2> setprop start/privileges = astring:
basic,!proc_session,!proc_info,!file_link_any,net_privaddr

svc:/network/http:apache2> setprop start/limit_privileges = astring: :default
svc:/network/http:apache2> setprop start/use_profile = boolean: false
svc:/network/http:apache2> setprop start/supp_groups = astring: :default
svc:/network/http:apache2> setprop start/working_directory = astring: :default
svc:/network/http:apache2> setprop start/project = astring: :default
svc:/network/http:apache2> setprop start/resource_pool = astring: :default
svc:/network/http:apache2> end
# svcprop -v -p start apache2
start/exec astring /lib/svc/method/http-apache2\ start
start/timeout_seconds count 60
start/type astring method
start/user astring webservd
start/group astring webservd
start/privileges astring
basic,!proc_session,!proc_info,!file_link_any,net_privaddr
start/limit_privileges astring :default
start/use_profile boolean false
start/supp_groups astring :default
start/working_directory astring :default
start/project astring :default
start/resource_pool astring :default
# svcadm -v refresh apache2
Action refresh set for svc:/network/http:apache2.
# svcadm -v enable -s apache2
svc:/network/http:apache2 habilitado.
# ps -fea|grep apache
webservd 3957 3953 0 19:21:13 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 3956 3953 1 19:21:13 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 3953 1 2 19:21:11 ? 0:01 /usr/apache2/bin/httpd -k start
webservd 3955 3953 1 19:21:13 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 3954 3953 0 19:21:13 ? 0:00 /usr/apache2/bin/httpd -k start
webservd 3958 3953 0 19:21:13 ? 0:00 /usr/apache2/bin/httpd -k start
# netstat -an|grep -i listen
*.22 *.* 0 0 49152 0 LISTEN
*.111 *.* 0 0 49152 0 LISTEN
*.59597 *.* 0 0 49152 0 LISTEN
*.80 *.* 0 0 49152 0 LISTEN
*.22 *.* 0 0 49152 0 LISTEN
*.80 *.* 0 0 49152 0 LISTEN

Y teniendo en cuenta lo que significa cada privilegios, vemos los que le hemos asignado.

# ppriv -v -l proc_exec proc_fork net_privaddr
proc_exec
Allows a process to call execve().
proc_fork
Allows a process to call fork1()/forkall()/vfork()
Configuring the Apache2 Service 7
net_privaddr
Allows a process to bind to a privileged port number.
The privilege port numbers are 1-1023 (the traditional
UNIX privileged ports) as well as those ports marked as
"udp/tcp_extra_priv_ports" with the exception of the ports
reserved for use by NFS.
# ppriv -S 3953
3953: /usr/apache2/bin/httpd -k start
flags =
E: net_privaddr,proc_exec,proc_fork
I: net_privaddr,proc_exec,proc_fork
P: net_privaddr,proc_exec,proc_fork
L: all

Luego hemos conseguido que el usuario webservd sea capaz de arrancar y para el servicio apache2, levantando un socket en el puerto tcp 80 sin necesidad de cambiar la identidad a root en ningún momento.

Habilitar SAR


A diferencia de como podiamos habilitar este comando en versiones antiguas de Solaris (9 y anteriores), asi:

# vi /etc/init.d/perf
if [ -z "$_INIT_RUN_LEVEL" ]; then
set -- `/usr/bin/who -r`
_INIT_RUN_LEVEL="$7"
_INIT_RUN_NPREV="$8"
_INIT_PREV_LEVEL="$9"
fi

if [ $_INIT_RUN_LEVEL -ge 2 -a $_INIT_RUN_LEVEL -le 4 -a \
$_INIT_RUN_NPREV -eq 0 -a \( $_INIT_PREV_LEVEL = 1 -o \
$_INIT_PREV_LEVEL = S \) ]; then

/usr/bin/su sys -c "/usr/lib/sa/sadc /var/adm/sa/sa`date +%d`"
fi

Descomentando las lineas en negrita, y ejecutando este script:

# /etc/init.d/perf
# sar
10:43:26 unix restarts
Average 0 0 0 100
# uname -a
SunOS alfacar 5.9 Generic_118558-35 sun4u sparc SUNW,Ultra-5_10

Unicamente nos quedaría comprobar que todo queda listo en el cron.

# crontab -l sys
0 * * * 0-6 /usr/lib/sa/sa1
20,40 8-17 * * 1-5 /usr/lib/sa/sa1
5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 1200 -A

En Solaris 10 y OpenSolaris, con la aparición de SMF (Service Management Facility) como gestor de los distintos procesos de arranque del sistema, manteniendo todavia compatibilidad con los clásicos niveles de ejecución (Run Levels), se realiza de forma diferente:

# sar
sar: can't open /var/adm/sa/sa30
No such file or directory
# svcs |grep sa
online 10:38:51 svc:/system/sac:default
# svcadm enable svc:/system/sar:default
# svcs |grep sar
online 10:43:58 svc:/system/sar:default
# sar
SunOS opensolaris 5.11 snv_57 i86pc 07/30/2007
10:43:58 %usr %sys %wio %idle
10:43:58 unix restarts
# uname -a
SunOS opensolaris 5.11 snv_57 i86pc i386 i86pc
# crontab -l sys
0 * * * 0-6 /usr/lib/sa/sa1
20,40 8-17 * * 1-5 /usr/lib/sa/sa1
5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 1200 -A
# svcs | grep cron
online 11:00:11 svc:/system/cron:default
# svcadm restart svc:/system/cron:default
# tail -f /var/cron/log
! ******* CRON ABORTED ******** lun jul 30 11:02:55 2007
! *** cron started *** pid = 567 lun jul 30 11:02:55 2007