        |
Protocolo REST entre TCM/3 (android 6) y tctiserver
Manual de referencia del API
Introducción
A continuación se documenta la comunicación entre el el servidor central de tcti (tctiserver) y software en de los móviles android 6 (TCM/3, en móviles galaxy S7).
El objetivo de dicho protocolo es:
- Realizar la autentificación (comprueba que el móvil es quien dice ser usando como usuario la MAC y como password el IMEI).
- Identificar la versión del terminal (en el propio mensaje de autentificación).
- Obtener el listado de estaciones autorizadas del terminal (es la respuesta al mensaje de autentificación).
- Confirmar el login/logout de un usuario en el terminal, usando DNE/PIN.
- Verificar el DNE/PIN para una acción.
Todo esto se consigue por medio de dos mensajes:
- estaciones.mem: autentificación, identificación versión terminal, obtención del listado de estaciones autorizadas.
- dnepin.mem: confirmar login/logout, verificar DNE/PIN.
El protocolo es REST, con dos peculiaridades:
- usa peticiones GET HTTP para simplificar y mantener el mismo protocolo que el que usa el TCM/3 contra los tcti de estación.
- las respuestas JSON vienen comprimidas y encriptadas según la manera habitual de sico para los JSON (dicho formato no se especifica en este documento). Estos mensajes se distinguen porque van con un "Content-Type" de "application/octet-stream".
Formato de las peticiones
Las peticiones son siempre:
GET nombrepeticion.mem?param=magic+mac+otrosparametros HTTP/1.0
Siendo:
- magic: es el magic o token de sesión, se calcula usando el challenge del mensaje de error de -2 ("Magic incorrecto"). Ver el final de este documento para más información.
- mac: la MAC del terminal
- otros parámetros: otros parámetros que dependen de la petición realizada.
Formato de las respuestas
El servidor puede mandar un HTTP_STATUS de:
- 200 (OK): Petición procesada, la respuesta que se envía contiene un JSON que el TCM/3 ha de parsear. El Content-Type es "application/octet-stream" por estar el JSON comprimido/encriptado.
- 400 (Bad request): La petición no ha sido reconocida, o tiene parámetros incorrectos. La respuesta es una página text/html.
- 401 (Unauthorized): Si la MAC enviada en la petición no está autorizada. Se devuelve un JSON de error por si se quiere tener la descipción del error. El Content-Type es "application/octet-stream" por estar el JSON comprimido/encriptado.
- 404 (Not found): Nombre de petición incorrecta (no es ni estaciones.mem ni dnepin.mem). La respuesta es una página text/html.
- 500 (Internal error): No se ha podido procesar la petición, generalmente por memoria insuficiente. Intentarlo de nuevo más tarde. La respuesta es una página text/html.
- 501 (Not implemented): El servidor no ha tiene implementado todavía esta petición. Este status no debería ocurrir, en caso de aparecer indica un bug en el servidor. La respuesta es una página text/html.
En el caso de que el JSON de respuesta esté comprimido/encriptado, el Content-Type será "application/octet-stream".
El JSON tiene una parte obligatoria (el "result") y luego o bien "error" si el result era negativo o bien "datatype"+"data" si el result era 0:
- result: -1 para el caso de error, 0 para OK. En caso de error existirá también la clave "error" que se detalla a continuación. En caso de "OK", la clave que existirá será la de "data".
- "error"
- code: el código de error.
- desc: la descripción del error.
- ...: otras claves específicas de este código de error (p.ej. challenge, pinkey,...).
- "datatype": "estaciones" o "dnepin" (indica que tipo de contenido hay en "data").
- "data": contiene la respuesta.
Mensajes de error
(This page is intentionally left blank)
| Tipo error | Contenido | Parámetros |
Error mac no autorizada (code -1) |
{
result:-1,
"error": {
code:-1,
desc:"MAC no autorizada"
}
}
|
- |
Error magic incorrecto (code -2) |
{
result:-1,
"error": {
code:-2,
desc:"Magic incorrecto",
challenge:"%s",
pinkey:"%i"
}
}
|
challenge:
cadena usada para calcular el nuevo magic
pinkey:
inicialización del número para encriptar el PIN en mensajes DNE/PIN
|
Error localización desconocida (code -3) |
{
result:-1,
"error": {
code:-3,
desc:"Localización desconocida"
}
}
|
- |
Error pinkey usado incorrecto (code -4) |
{
result:-1,
"error": {
code:-4,
desc:"Formato de PIN incorrecto"
}
}
|
- |
Error clave encriptación PIN (code -5) |
{
result:-1,
"error": {
code:-5,
desc:"Error clave encriptación PIN"
}
}
|
- |
Error petición PIN cancelada (code -6) |
{
result:-1,
"error": {
code:-6,
desc:"Error petición PIN cancelada"
}
}
|
- |
Error timeout en comprobación de PIN (code -7) |
{
result:-1,
"error": {
code:-7,
desc:"Error timeout en comprobación de PIN"
}
}
|
- |
Mensaje de estaciones.mem
La petición es:
estaciones.mem?param=magic+mac+versión
Siendo:
- magic: El magic o token de sesión. Si no se tiene, se rellena con 16 "0" (es decir: "0000000000000000").
- mac: La MAC del terminal, en minúsculas y usando dos-puntos para separar los elementos de la MAC (ejemplo: "01:23:45:ab:cd:ef").
- versión: La versión del programa (p.ej. "TCM:Android:3.0").
Ejemplo:
estaciones.mem?param=0000000000000000+2c:0e:3d:60:67:b2+TCM:Android:3.0
Códigos de error que puede dar esta petición:
- error -1 (MAC no autorizada)
- error -2 (MAGIC incorrecto)
- error -3 (Localización desconocida)
Respuesta correcta:
{
result:0,
"datatype":"estaciones",
"data":[{nombre:"Nombre estacion1",ip:"10.0.0.1",default:true},
{nombre:"Nombre estacion2",ip:"10.0.0.2",default:false},
{nombre:"Nombre estacion3",ip:"10.0.0.3",default:false}]
}
El campo "datatype" indica que es una respuesta a estaciones.mem.
El contenido de "data" es una array de objetos que tienen los elementos siguientes:
- nombre: El nombre de la estación tal y como está configurado en el tctiserver (p.ej. CNaciones). El nombre está abreviado, por lo que para el UI es mejor mostrar el nombre que proporciona el servidor tcti de estación, que el nombre completo (p.ej. "Campo de las Naciones").
- ip: La IP del tcti de estación (para hacer peticiones al tcti de estación el TCM se a esta IP, al puerto 10001).
- default: "true" si es la estación por defecto configurada para este terminal, "false" si es una estación autorizada pero que no hay que conectarse inicialmente a ella (sí se puede seleccionar desde menú, si es que el UI del TCM lo permite).
Mensaje de dnepin.mem
La petición es:
dnepin.mem?param=magic+mac+tipo+DNE+pinkey+pinencriptado
Siendo:
- magic: El magic o token de sesión. Si no se tiene, se rellena con 16 "0" (es decir: "0000000000000000").
- mac: La MAC del terminal, en minúsculas y usando dos-puntos para separar los elementos de la MAC (ejemplo: "01:23:45:ab:cd:ef").
- tipo: "entrada","salida","descanso" o "verificar".
- DNE: El DNE a hacer la entrada o verificar.
- pinkey: uno más del último pinkey usado ("pinkey+1"). NOTAS: El pinkey inicial se recibe en el mensaje de error de código -2 ("magic incorrecto"), cuyos datos se usan para realizar la autentificación. El pinkey inicial se considera ya usado y el primer mensaje que manda el TCM ha de ser el siguiente a ese pinkey inicial (pinkey_inicial+1).
- pinencriptado: 18 bytes que contienen una cadena urlencoded ("%7A%8F%17..."). Es el resultado de encriptar el PIN con el algoritmo que se explica más abajo.
Ejemplo:
dnepin.mem?param=1a884fac7911ffa3+2c:0e:3d:60:67:b2+verificar+01234+%AC%7C%8F%12%0C%77
Códigos de error que puede dar esta petición:
- error -1 (MAC no autorizada)
- error -2 (MAGIC incorrecto)
- error -4 (pinkey usado incorrecto)
- error -5 (error clave encriptación PIN)
- error -6 (error petición PIN cancelada por haber recibido una nueva petición de este terminal)
- errort-7 (timeout en comprobación de PIN si el servidor de controlid no contesta en 4 segundos)
Respuesta correcta:
{
result:0,
"datatype":"dnepin",
"data":{tipo:"verificar",
dne:"01234",
pin_ok: 1,
nombre: "Nombre Apellidos"}
}
El campo "datatype" indica que es una respuesta a dnepin.mem.
El contenido de "data" tiene los siguientes elementos:
- tipo: El tipo de petición a la que se está respondiendo.
- dne: El DNE que está verificando.
- pin_ok: 1 si DNE/PIN válido, 0 en caso de que el DNE/PIN incorrecto.
- nombre: En caso de DNE/PIN válido, es el nombre/apellidos que corresponden ese DNE.
Cálculo del pinencriptado
1. Se prepara un búffer con los 6 dígitos del PIN en plaintext.
2. Se calcula la clave, que es el sha256sum (binario) de la contcatenación de Mac, IMEI, Challenge, pinkey. NOTA: El Challenge es el que se recibió en el mensaje de error de código -2 ("magic incorrecto"), cuyos datos se usaron para realizar la autentificación.
3. Se hace un XOR de los 6 primeros bytes del sha256sum (binario) con los 6 dígitos del PIN plaintext
4. En el punto anterior se han obtenido 6 bytes binarios (xorresult). Se genera una cadena que es el printf("%%02X%%02X%%02X%%02X%%02X%%02X",xorresult[0],xorresult[1],...,xorresult[5]). El resultado de ese printf es el pin encriptado.
Notas adicionales
El API está organizado según los principios de REST. Un ejemplo sencillo de un API REST moderno se puede ver en este documento (pdf).
API root (se prueban en "round-robin"):
- http://16.13.62.60
- http://16.2.62.60
- http://16.0.62.18
API Endpoints:
- /estaciones.mem
- /dnepin.mem
Resumen de los "HTTP status code" usados
| Código | Explicación |
| 200 - OK | Se ha devuelto un resultado JSON tal y como se esperaba |
| 400 - Bad Request | Parámetros incorrectos en petición |
| 401 - Unauthorized | No autorizado (sólo en caso de MAC no autorizada) |
| 404 - Not found | Endpoint no encontrado |
| 500 - Internal error | Error del servidor (generalmente memoria insuficietnte) |
| 501 - Not implemented | Error del servidor (bug) |
Sobre los JSON devueltos
Los JSON de respuesta se devuelven comprimidos con gzip y encriptados con el algoritmo de Carlos (en ese orden).
Errores de autentificación e información de cómo reautentificarse
Los mensajes de error de autentificación son comunes a los dos endpoints, ya que ambos incluyen en los parámetros la MAC del terminal y el "magic" (o token) que sirve de identificador de sesión de dicho terminal con respecto al tcti. Problemas con la MAC y con el magic dan lugar a los errores relacionados con la autentificación.
En caso de que el magic del mensaje no sea el correcto (es decir, en caso de que no coincida con el que tiene almacenado el tctiserver en memoria), la respuesta a la petición es un mensaje de error con los datos necesarios para calcular el nuevo magic que tiene que usar dicho terminal. Este mensaje se manda con un "HTTP status code" de 200.
Error de magic incorrecto (el "%s" representa una cadena entre comillas, mientras que el "%i" representa un número entero entre comillas):
{
result:-1,
"error": {
code:-2,
desc:"Magic incorrecto",
challenge:"%s",
pinkey:"%i"
}
}
|
Para recalcular el magic correcto, se hace un sha256sum(MAC+IMEI+challenge) y el nuevo magic son los 16 últimos carácteres del resultado de dicho sha256sum.
|