Sustituye el usuario con SU
Javier Mora   15 Enero 2009
¿Has necesitado alguna vez ejecutar un mandato con los privilegios de otro usuario? ¿Has necesitado abrir una línea de mandato como QSECOFR? ¿Has necesitado cambiar el usuario actual de un trabajo? Todas estas actividades pueden realizarse con el mandato SU y algunas utilidades que presento en este artículo.

Como administrador del sistema de un System i y como desarrollador de aplicaciones para este equipo utilizo dos perfiles de usuario distintos: QSECOFR o similar para tareas de administración y el usuario USR para desarrollo. Ambos tienen privilegios y autorizaciones distintas. Si durante mi trabajo diario necesito realizar alguna tarea de configuración necesito abrir una sesión nueva bajo el usuario QSECOFR y al terminar, desconectar para seguir con mi trabajo. Existen instalaciones en las que está prohibido iniciar sesiones con usuarios de la clase *SECOFR desde terminales que no sean la consola. Esta medida se toma por cuestiones de seguridad ya que, de esta forma, la contraseña no viaja por la red (ni siquiera encriptada).

Para intentar paliar estos problemas he creado un nuevo mandato al que he llamado SU (Sustituir Usuario), que está inspirado en el comando "su" de los sistemas Unix/Linux, con el que se puede ejecutar un comando o un intérprete de comandos con otro usuario sin necesidad de cerrar la sesión. Este mandato necesita tres parámetros: el perfil de usuario sustituto, su contraseña y el mandato a ejecutar. Si todo es correcto, SU ejecutará el mandato con los mismos privilegios y autorizaciones del usuario suministrado.

¿Cómo funciona realmente SU? Es relativamente simple, se aprovechan tres APIs del sistema operativo: QSYGETPH, QWTSETP y QSYRLSPH. La primera valida un perfil de usuario y su contraseña y devuelve un descriptor que lo identifica. La segunda cambia el usuario actual del trabajo por el identificado por un descriptor. La última, libera el almacenamiento ocupado. Simplificando los pasos:

1. Se valida el usuario y la contraseña. Se obtiene un descriptor que identifica a ese usuario.
2. Se obtiene el descriptor que identifica al usuario actual del trabajo.
3. Se sustituye el usuario actual del trabajo por el suministrado en el paso 1.
4. Se ejecuta el mandato, con las autorizaciones del nuevo usuario.
5. Se restablece el usuario original del trabajo con el descriptor obtenido en el paso 2.
6. Se realizan operaciones de limpieza.

¿Qué he conseguido con esta nueva utilidad? Simplificar un poco mis tareas de administración. Cuando necesito cambiar algo de la configuración del sistema o realizar otra tarea administrativa que requiera de los privilegios de QSECOFR ejecuto lo siguiente:

SU USRPRF(QSECOFR) PWD(LACONTRASEÑA) CMD(CFGTCP)

si sólo quiero abrir una línea de mandato no indico el mandato a ejecutar.

Esta utilidad tiene una característica oscura: en la contraseña se puede especificar el valor especial *NOPWDCHK. Éste permite utilizar el usuario sin conocer la contraseña pero sólo cuando el usuario llamador tenga autorización *USE sobre el usuario que se quiera utilizar. Por ejemplo, QSECOFR podría utilizar el mandato SU para suplantar la identidad de cualquier otro usuario sin conocer su contraseña.

Creo que el código fuente está bastante documentado para entender el funcionamiento.

Además podréis encontrar los fuentes de otras utilidades (no las detallo) y algunos ejemplos de su uso. Básicamente, son unas envolturas de las APIs anteriores para poder utilizarse desde programas CL y un programa que permite cambiar el usuario actual del trabajo. Se incluye el programa CL SUI con los mandatos necesarios para compilar todas las utilidades.

Para compilar el mandato SU es necesario algo más. Son unos miembros fuentes de copia (/Copy) o de cabecera (como se identifican en otros lenguajes) con las declaraciones de las estructuras de datos y prototipos de las APIs utilizadas. En estos fuentes están todas las APIs que he necesitado utilizar alguna vez en alguno de mis programas. No están todas las del sistema pe ro hay bastantes. He intentado agrupar las APIs según su funcionalidad y el nombre de cada miembro intenta tener relación con la categoría de la API (según el manual). También he intentado mantener ciertos estándares de codificación pero no está del todo conseguido. Tengan en cuenta que algunos fuentes nacieron hace cinco años. En mi caso, todos estos miembros están ubicados en un archivo que he llamado API, si se cambia de lugar, será necesario realizar alguna adaptación. Ninguno de ellos se compila.

Espero que este nuevo mandato sea de alguna utilidad para el resto de los miembros de la comunidad System i/iSeries.

Hasta pronto.
SIDRA400
Entrada