Finish server + client implementation (and fix bugs)
Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar> Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
parent
9cac4bf50d
commit
b503ad1204
10
Makefile
10
Makefile
|
@ -1,12 +1,8 @@
|
||||||
CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200809L
|
CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200809L
|
||||||
# CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200112L
|
LDFLAGS = -lpthread
|
||||||
|
|
||||||
LDFLAGS = -lpthread -lm
|
|
||||||
|
|
||||||
SERVER_SOURCES=src/args.c src/selector.c src/socks5nio.c src/confignio.c src/stm.c src/hello.c src/request.c src/netutils.c src/buffer.c src/server.c src/auth.c src/cmd.c src/parser.c src/parser_utils.c
|
SERVER_SOURCES=src/args.c src/selector.c src/socks5nio.c src/confignio.c src/stm.c src/hello.c src/request.c src/netutils.c src/buffer.c src/server.c src/auth.c src/cmd.c src/parser.c src/parser_utils.c
|
||||||
CLIENT_SOURCES=src/client.c
|
CLIENT_SOURCES=src/client.c src/netutils.c
|
||||||
SERVER_LIBS=include/args.h include/selector.h include/socks5nio.h include/stm.h include/hello.h include/request.h include/buffer.h include/server.h
|
|
||||||
CLIENT_LIBS=
|
|
||||||
SERVER_OBJECTS=$(SERVER_SOURCES:.c=.o)
|
SERVER_OBJECTS=$(SERVER_SOURCES:.c=.o)
|
||||||
CLIENT_OBJECTS=$(CLIENT_SOURCES:.c=.o)
|
CLIENT_OBJECTS=$(CLIENT_SOURCES:.c=.o)
|
||||||
SERVER_TARGET=socks5d
|
SERVER_TARGET=socks5d
|
||||||
|
@ -15,7 +11,7 @@ CLIENT_TARGET=client
|
||||||
all: $(SERVER_OBJECTS) $(SERVER_TARGET) $(CLIENT_OBJECTS) $(CLIENT_TARGET)
|
all: $(SERVER_OBJECTS) $(SERVER_TARGET) $(CLIENT_OBJECTS) $(CLIENT_TARGET)
|
||||||
|
|
||||||
%.o : %.c
|
%.o : %.c
|
||||||
$(CC) $(CCFLAGS) $(LDFLAGS) -I ./include -c $< -o $@
|
$(CC) $(CCFLAGS) -I ./include -c $< -o $@
|
||||||
|
|
||||||
$(SERVER_TARGET): $(SERVER_OBJECTS)
|
$(SERVER_TARGET): $(SERVER_OBJECTS)
|
||||||
$(CC) $(CCFLAGS) $(LDFLAGS) -I ./include -o $@ $^
|
$(CC) $(CCFLAGS) $(LDFLAGS) -I ./include -o $@ $^
|
||||||
|
|
59
README.md
59
README.md
|
@ -23,16 +23,52 @@ make all
|
||||||
|
|
||||||
## Ejecución <a name="ejecución"></a>
|
## Ejecución <a name="ejecución"></a>
|
||||||
|
|
||||||
Ahora, tendrá dos ejecutables: `client` y `server`. Note que primero debe correr el `server` y luego conectarse con el `client`.
|
Ahora, tendrá dos ejecutables: `client` y `socks5d`.
|
||||||
|
|
||||||
|
El servidor por defecto utilizará un _TOKEN_ que debe ser una `env` variable. Por ejemplo, puede configurar una mediante:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./server
|
export BPROXY_TOKEN=0x0FF1CEDEADB00B1E
|
||||||
|
```
|
||||||
|
|
||||||
|
Si no se encuentra una token al momento de ejecutar el `server` el mismo terminará con error.
|
||||||
|
|
||||||
|
Ahora, puede correr el `server` y luego, si desea hacer alguna configuración, conectarse con el `client`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./socks5d ${PARAMS}
|
||||||
```
|
```
|
||||||
|
|
||||||
y en otra terminal
|
y en otra terminal
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./client
|
./client ${PARAMS}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Casos de uso <a name="casos-de-uso"></a>
|
||||||
|
|
||||||
|
Se mostrarán dos casos típicos de uso del servidor.
|
||||||
|
|
||||||
|
Aquí se tiene al servidor proxy corriendo en 127.0.0.1:1080 y se utiliza a este para conectarse a 192.168.10.120:110 (una PC en la misma subred corriendo un servidor POP3 local). Además, se está autenticando con el usuario `user:pass`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./socks5d -u user:pass
|
||||||
|
ncat -C -v --proxy 127.0.0.1:1080 --proxy-type socks5 192.168.10.120 110 --proxy-auth user:pass
|
||||||
|
```
|
||||||
|
|
||||||
|
Por otro lado, aquí se usó `curl` para acceder a http://api.ipify.org mediante el proxy (también corriendo en la misma IP que el ejemplo anterior).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./socks5d -u user:pass
|
||||||
|
curl -x socks5://user:pass@127.0.0.1:1080 http://api.ipify.org
|
||||||
|
```
|
||||||
|
|
||||||
|
En este caso se quiere obtener la cantidad de páginas de usuarios que hay en el servidor proxy, mediante -L se especifica la direccion IP del servidor de configuración (por defecto 127.0.0.1), con -P se especifica el puerto (por defecto 8080).
|
||||||
|
Una vez que se obtiene la cantidad de páginas se le pide el listado de usuarios pertenecientes a la 2da página, en caso de que el servidor no cuente con usuarios suficientes para tener 2 páginas, imprimirá un error especificando que el valor pasado no es válido. En cambio, si se cuentan con usuarios suficientes se listarán separados por un '\n'
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./client 1148926835748244254 -L 192.168.10.119 -P 8100 -f
|
||||||
|
./client 1148926835748244254 -L 192.168.10.119 -P 8100 -u 2
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testeos <a name="tests"></a>
|
## Testeos <a name="tests"></a>
|
||||||
|
@ -46,29 +82,18 @@ make test
|
||||||
Por último, si quiere hacer un análisis dinámico (usando [valgrind](https://valgrind.org/)) puede hacerlo mediante:
|
Por último, si quiere hacer un análisis dinámico (usando [valgrind](https://valgrind.org/)) puede hacerlo mediante:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
valgrind ./server
|
valgrind ./socks5d
|
||||||
```
|
|
||||||
|
|
||||||
y en otra terminal
|
|
||||||
|
|
||||||
```bash
|
|
||||||
valgrind ./client
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Limpieza <a name="limpieza"></a>
|
## Limpieza <a name="limpieza"></a>
|
||||||
Si desea borrar los archivos creados luego de la compilación debe correr:
|
Si desea borrar los archivos creados luego de la compilación (y los testeos si se hubiesen corrido) debe correr:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make clean
|
make clean
|
||||||
```
|
```
|
||||||
|
|
||||||
Note que si, además, quiere borrar el output de los tests (de `PVS-Studio` específicamente), lo puede hacer con:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make cleanTest
|
|
||||||
```
|
|
||||||
|
|
||||||
# Autores
|
# Autores
|
||||||
|
### Bottler:
|
||||||
- Barmasch, Juan Martín (61033)
|
- Barmasch, Juan Martín (61033)
|
||||||
- Bellver, Ezequiel (61268)
|
- Bellver, Ezequiel (61268)
|
||||||
- Lo Coco, Santiago (61301)
|
- Lo Coco, Santiago (61301)
|
631
docs/rfc.txt
631
docs/rfc.txt
|
@ -1,4 +1,4 @@
|
||||||
Bottler Protocol version 1
|
Bottler Configuration Protocol version 1
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
|
|
||||||
|
@ -11,11 +11,10 @@ Note:
|
||||||
format diagrams represent the length of the corresponding field, in
|
format diagrams represent the length of the corresponding field, in
|
||||||
octets. Where a given octet must take on a specific value, the
|
octets. Where a given octet must take on a specific value, the
|
||||||
syntax X'hh' is used to denote the value of the single octet in that
|
syntax X'hh' is used to denote the value of the single octet in that
|
||||||
field. When the word 'Variable' is used, it indicates that the
|
field. When the size of a field is a range, it indicates that the
|
||||||
corresponding field has a variable length defined either by an
|
corresponding field has a variable length defined either by an
|
||||||
associated (one or two octet) length field, or by a data type field.
|
associated (one or two octet) length field.
|
||||||
|
Fields taking more than one octet are in network octet order.
|
||||||
NETWORK ORDER!!!
|
|
||||||
|
|
||||||
2. Requests
|
2. Requests
|
||||||
|
|
||||||
|
@ -29,45 +28,33 @@ Note:
|
||||||
|
|
||||||
The VER field is set to X'01' for this version of the protocol. The
|
The VER field is set to X'01' for this version of the protocol. The
|
||||||
TOKEN field contains 8 bytes that authenticates the request. The
|
TOKEN field contains 8 bytes that authenticates the request. The
|
||||||
CMD field describes the command that will be run. The
|
CMD field describes the command that will be run. The PARAMETERS
|
||||||
PARAMETERS field describes the parameters that will be passed
|
field describes the parameters that will be passed depending on the
|
||||||
depending on the CMD field value.
|
CMD field value.
|
||||||
|
|
||||||
The values currently defined for CMD are:
|
The values currently defined for CMD are:
|
||||||
|
|
||||||
o X'00' GET METRICS
|
o X'00' GET METRICS
|
||||||
o X'01' GET BUFFER SIZE
|
o X'01' GET USER PAGES
|
||||||
o X'02' SET BUFFER SIZE
|
o X'02' LIST USERS
|
||||||
o X'03' GET TIMEOUT VALUE
|
o X'03' MODIFY USERNAME
|
||||||
o X'04' SET TIMEOUT VALUE
|
o X'04' MODIFY PASSWORD
|
||||||
o X'05' GET USER PAGES
|
o X'05' ADD USER
|
||||||
o X'06' LIST USERS
|
o X'06' DELETE USER
|
||||||
o X'07' GET USER LAST CONNECTION
|
o X'07' GET PASSWORD DISSECTOR STATUS
|
||||||
o X'08' MODIFY USERNAME
|
o X'08' SET PASSWORD DISSECTOR
|
||||||
o X'09' MODIFY PASSWORD
|
o X'09' GET PROXY AUTHENTICATION STATUS
|
||||||
o X'0A' ADD USER
|
o X'0A' SET PROXY AUTHENTICATION
|
||||||
o X'0B' DELETE USER
|
|
||||||
o X'0C' GET PASSWORD DISSECTOR STATUS
|
|
||||||
o X'0D' ENABLE/DISABLE PASSWORD DISSECTOR
|
|
||||||
o X'0E' GET PROXY AUTHENTICATION STATUS
|
|
||||||
o X'0F' ENABLE/DISABLE PROXY AUTHENTICATION
|
|
||||||
o X'10' GET PROXY SERVER STATUS
|
|
||||||
o X'11' START/STOP PROXY SERVER
|
|
||||||
o X'12' RESET PROXY SERVER
|
|
||||||
|
|
||||||
TODO: metodo para saber cuanto tiene una página? o lo hardcodeamos en el proto?
|
|
||||||
|
|
||||||
TODO: unknown command 0xFE
|
3. Commands
|
||||||
TODO: get users de ettercap (not quite)
|
|
||||||
|
|
||||||
2. Commands
|
3.1. CMD: X'00' - GET METRICS
|
||||||
|
|
||||||
CMD: X'00' - GET METRICS
|
Requests historical metrics values. Which are historical
|
||||||
|
connections, current connections and total bytes transmitted.
|
||||||
Requests historical metrics values. Which are hostorical
|
Connections are represented as an unsigned int taking 4 bytes
|
||||||
connections, current connections and total bytes transmited.
|
Total bytes transmitted as an unsigned long taking 8 bytes.
|
||||||
Connections are represented as an unisgned int taking 4 bytes
|
|
||||||
Total bytes transmited as a unsigned long taking 8 bytes.
|
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
|
@ -86,15 +73,17 @@ CMD: X'00' - GET METRICS
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'01' - GET BUFFER SIZE
|
3.2. CMD: X'01' - GET USER PAGES
|
||||||
|
|
||||||
Requests buffer size used for the proxy SOCKS server.
|
Requests amount of pages of valid users for the proxy SOCKS
|
||||||
Response comes with a response code and one integer
|
server.
|
||||||
representing the buffer size taking 2 bytes.
|
Response comes as an unsigned integer taking 2 bytes representing
|
||||||
|
amount of pages available containing the usernames of all valid users.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
|
@ -103,122 +92,6 @@ CMD: X'01' - GET BUFFER SIZE
|
||||||
| X'01' | 8 | X'01' |
|
| X'01' | 8 | X'01' |
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+-----------+
|
|
||||||
| VER | CODE | BUFF SIZE |
|
|
||||||
+-------+--------+-----------+
|
|
||||||
| X'01' | 1 | 2 |
|
|
||||||
+-------+--------+-----------+
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'02' - SET BUFFER SIZE
|
|
||||||
|
|
||||||
TODO: decidir bien los tamaños
|
|
||||||
|
|
||||||
Requests the modification of the buffer size used for the
|
|
||||||
proxy SOCKS server. Value must be between 256 and 16.384
|
|
||||||
Response comes with a response code indicating the output
|
|
||||||
of the action required
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+-----------+
|
|
||||||
| VER | TOKEN | CMD | BUFF SIZE |
|
|
||||||
+-------+-------+---------+-----------+
|
|
||||||
| X'01' | 8 | X'02' | 2 |
|
|
||||||
+-------+-------+---------+-----------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'03' - GET TIMEOUT VALUE
|
|
||||||
|
|
||||||
Requests the timeout value used in the proxy SOCKS server.
|
|
||||||
Response comes with a response code and one integer
|
|
||||||
representing the timeout value taking 2 bytes.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+
|
|
||||||
| VER | TOKEN | CMD |
|
|
||||||
+-------+-------+---------+
|
|
||||||
| X'01' | 8 | X'03' |
|
|
||||||
+-------+-------+---------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+---------+
|
|
||||||
| VER | CODE | TIMEOUT |
|
|
||||||
+-------+--------+---------+
|
|
||||||
| X'01' | 1 | 2 |
|
|
||||||
+-------+--------+---------+
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'04' - SET TIMEOUT VALUE
|
|
||||||
|
|
||||||
TODO: decidir bien los valores
|
|
||||||
|
|
||||||
Requests the modification of the timeout value used in the
|
|
||||||
proxy SOCKS server. Value must be between 128 and 2048
|
|
||||||
Response comes with a response code indicating the output
|
|
||||||
of the action required
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+---------+
|
|
||||||
| VER | TOKEN | CMD | TIMEOUT |
|
|
||||||
+-------+-------+---------+---------+
|
|
||||||
| X'01' | 8 | X'04' | 2 |
|
|
||||||
+-------+-------+---------+---------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'05' - GET USER PAGES
|
|
||||||
|
|
||||||
Requests amount of pages of valid users for the proxy SOCKS
|
|
||||||
server.
|
|
||||||
Response comes as an integers taking 2 bytes. (representing)
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+
|
|
||||||
| VER | TOKEN | CMD |
|
|
||||||
+-------+-------+---------+
|
|
||||||
| X'01' | 8 | X'05' |
|
|
||||||
+-------+-------+---------+
|
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
+-------+--------+-------+
|
+-------+--------+-------+
|
||||||
| VER | CODE | PAGES |
|
| VER | CODE | PAGES |
|
||||||
|
@ -229,49 +102,59 @@ CMD: X'05' - GET USER PAGES
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'06' - LIST USERS
|
3.3. CMD: X'02' - LIST USERS
|
||||||
|
|
||||||
Requests amount of pages of valid users for the proxy SOCKS
|
Requests an user page containing usernames of valid users for
|
||||||
server.
|
the proxy SOCKS server for a given page number.
|
||||||
Response comes as an integers taking 2 bytes. (representing)
|
Response comes as ascii values representing each username
|
||||||
|
separated by a '\n'. Maximum 5 users per response.
|
||||||
|
If there are less than 5 then the last username will have
|
||||||
|
"\n\n" at the end.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| VER | TOKEN | CMD | PAGE |
|
| VER | TOKEN | CMD | PAGE |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| X'01' | 8 | X'06' | 2 |
|
| X'01' | 8 | X'02' | 2 |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
+-------+--------+---------------+
|
+-------+--------+---------------+
|
||||||
| VER | CODE | PAGE |
|
| VER | CODE | PAGE SIZE |
|
||||||
+-------+--------+---------------+
|
+-------+--------+---------------+
|
||||||
| X'01' | 1 | Page size |
|
| X'01' | 1 | Page size |
|
||||||
+-------+--------+---------------+
|
+-------+--------+---------------+
|
||||||
|
|
||||||
|
PAGE represents a page number greater or equal to 1.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
o X'C0' INVALID PARAMETER VALUE
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'08' - MODIFY USERNAME
|
The INVALID PARAMETER VALUE code will be returned when
|
||||||
|
PAGE value is not a valid page.
|
||||||
|
|
||||||
|
3.4. CMD: X'03' - MODIFY USERNAME
|
||||||
|
|
||||||
Modifies username of user of proxy server.
|
Modifies username of user of proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+-----------+---------+----------+
|
+-------+-------+---------+--------+-----------+---------+----------+
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME | NULEN | NUNAME |
|
| VER | TOKEN | CMD | ULEN | UNAME | NULEN | NUNAME |
|
||||||
+-------+-------+---------+--------+-----------+---------+----------+
|
+-------+-------+---------+--------+-----------+---------+----------+
|
||||||
| X'01' | 8 | X'08' | 1 | 1 to 255 | 1 | 1 to 255 |
|
| X'01' | 8 | X'03' | 1 | 1 to 255 | 1 | 1 to 255 |
|
||||||
+-------+-------+---------+--------+-----------+---------+----------+
|
+-------+-------+---------+--------+-----------+---------+----------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -282,31 +165,39 @@ CMD: X'08' - MODIFY USERNAME
|
||||||
+-------+--------+
|
+-------+--------+
|
||||||
|
|
||||||
UNAME and NUNAME are valid SOCKSv5 usernames. NUNAME
|
UNAME and NUNAME are valid SOCKSv5 usernames. NUNAME
|
||||||
represents de new value for the username of the user
|
represents the new value for the username of the user
|
||||||
with the username UNAME. ULEN describes the length of
|
with the username UNAME. ULEN describes the length of
|
||||||
UNAME, NULEN describes the length of NUNAME.
|
UNAME, NULEN describes the length of NUNAME.
|
||||||
|
Both UNAME and NUNAME must only contain printable ASCII
|
||||||
|
characters other than ':'.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
o X'C0' INVALID PARAMETER VALUE
|
||||||
o X'C1' USER NOT FOUND
|
o X'C1' USER NOT FOUND
|
||||||
|
o X'C1' USER ALREADY EXISTS
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'09' - MODIFY PASSWORD
|
The INVALID PARAMETER VALUE code will be returned when
|
||||||
|
ULEN or NULEN is 0 or when there are invalid characters
|
||||||
|
in either UNAME or NUNAME.
|
||||||
|
|
||||||
|
3.5. CMD: X'04' - MODIFY PASSWORD
|
||||||
|
|
||||||
Modifies password of user of proxy server with username
|
Modifies password of user of proxy server with username
|
||||||
UNAME.
|
UNAME.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
| X'01' | 8 | X'09' | 1 | 1 to 255 | 1 | 1 to 255 |
|
| X'01' | 8 | X'04' | 1 | 1 to 255 | 1 | 1 to 255 |
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -318,30 +209,37 @@ CMD: X'09' - MODIFY PASSWORD
|
||||||
|
|
||||||
UNAME is a valid SOCKSv5 username and PASS is a valid
|
UNAME is a valid SOCKSv5 username and PASS is a valid
|
||||||
SOCKSv5 password. PASS represents de new value for the
|
SOCKSv5 password. PASS represents de new value for the
|
||||||
passowrd of the user with the username UNAME. ULEN
|
password of the user with the username UNAME. ULEN
|
||||||
describes the length of UNAME, PLEN describes the
|
describes the length of UNAME, PLEN describes the
|
||||||
length of PASS.
|
length of PASS.
|
||||||
|
Both UNAME and PASS must only contain printable ASCII
|
||||||
|
characters other than ':'.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
o X'C0' INVALID PARAMETER VALUE
|
||||||
o X'C1' USER NOT FOUND
|
o X'C1' USER NOT FOUND
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0A' - ADD USER
|
The INVALID PARAMETER VALUE code will be returned when
|
||||||
|
ULEN or PLEN is 0 or when there are invalid characters
|
||||||
|
in either UNAME or PASS.
|
||||||
|
|
||||||
|
3.6. CMD: X'05' - ADD USER
|
||||||
|
|
||||||
Adds a user to the proxy server.
|
Adds a user to the proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
| X'01' | 8 | X'0A' | 1 | 1 to 255 | 1 | 1 to 255 |
|
| X'01' | 8 | X'05' | 1 | 1 to 255 | 1 | 1 to 255 |
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
+-------+-------+---------+--------+-----------+-------+----------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -356,26 +254,34 @@ CMD: X'0A' - ADD USER
|
||||||
for the username of the new user and PASS represents
|
for the username of the new user and PASS represents
|
||||||
the value for the password of user. ULEN describes the
|
the value for the password of user. ULEN describes the
|
||||||
length of UNAME, PLEN describes the length of PASS.
|
length of UNAME, PLEN describes the length of PASS.
|
||||||
|
Both UNAME and PASS must only contain printable ASCII
|
||||||
|
characters other than ':'.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
o X'C0' INVALID PARAMETER VALUE
|
||||||
|
o X'C2' USER ALREADY EXISTS
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0B' - DELETE USER
|
The INVALID PARAMETER VALUE code will be returned when
|
||||||
|
ULEN or PLEN is 0 or when there are invalid characters
|
||||||
|
in either UNAME or PASS.
|
||||||
|
|
||||||
|
|
||||||
|
3.7. CMD: X'06' - DELETE USER
|
||||||
Deletes a user from the proxy server.
|
Deletes a user from the proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+-----------+
|
+-------+-------+---------+--------+-----------+
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME |
|
| VER | TOKEN | CMD | ULEN | UNAME |
|
||||||
+-------+-------+---------+--------+-----------+
|
+-------+-------+---------+--------+-----------+
|
||||||
| X'01' | 8 | X'0B' | 1 | 1 to 255 |
|
| X'01' | 8 | X'06' | 1 | 1 to 255 |
|
||||||
+-------+-------+---------+--------+-----------+
|
+-------+-------+---------+--------+-----------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -388,21 +294,28 @@ CMD: X'0B' - DELETE USER
|
||||||
UNAME is a valid SOCKSv5 username. UNAME represents
|
UNAME is a valid SOCKSv5 username. UNAME represents
|
||||||
the value for the username of the user to be deleted.
|
the value for the username of the user to be deleted.
|
||||||
ULEN describes the length of UNAME.
|
ULEN describes the length of UNAME.
|
||||||
|
UNAME must only contain printable ASCII
|
||||||
|
characters other than ':'.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
o X'C0' INVALID PARAMETER VALUE
|
||||||
o X'C1' USER NOT FOUND
|
o X'C1' USER NOT FOUND
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0C' - GET PASSWORD DISSECTOR STATUS
|
The INVALID PARAMETER VALUE code will be returned when
|
||||||
|
ULEN or PLEN is 0 or when there are invalid characters
|
||||||
|
in either UNAME or PASS.
|
||||||
|
|
||||||
|
3.8. CMD: X'07' - GET PASSWORD DISSECTOR STATUS
|
||||||
|
|
||||||
Requests the status of the password dissector service on
|
Requests the status of the password dissector service on
|
||||||
the proxy server.
|
the proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action and a STATUS representing the status of the
|
the action and a STATUS representing the status of the
|
||||||
password dissector.
|
password dissector.
|
||||||
|
|
||||||
|
@ -410,7 +323,7 @@ CMD: X'0C' - GET PASSWORD DISSECTOR STATUS
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
| VER | TOKEN | CMD |
|
| VER | TOKEN | CMD |
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
| X'01' | 8 | X'0C' |
|
| X'01' | 8 | X'07' |
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -422,28 +335,29 @@ CMD: X'0C' - GET PASSWORD DISSECTOR STATUS
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
STATUS represents the status of the password dissector
|
||||||
service. If STATUS is X'00' then password dissector
|
service. If STATUS is X'00' then password dissector
|
||||||
service is down. Any other value representes password
|
service is down. Any other value greater than 0 represents
|
||||||
dissector being active.
|
password dissector being active.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0D' - SET PASSWORD DISSECTOR STATUS
|
3.9. CMD: X'08' - SET PASSWORD DISSECTOR STATUS
|
||||||
|
|
||||||
Modifies the status of the password dissector service on
|
Modifies the status of the password dissector service on
|
||||||
the proxy server.
|
the proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| VER | TOKEN | CMD | STATUS |
|
| VER | TOKEN | CMD | STATUS |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| X'01' | 8 | X'0D' | 1 |
|
| X'01' | 8 | X'08' | 1 |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -455,23 +369,24 @@ CMD: X'0D' - SET PASSWORD DISSECTOR STATUS
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
STATUS represents the status of the password dissector
|
||||||
service. If STATUS is X'00' then password dissector
|
service. If STATUS is X'00' then password dissector
|
||||||
service will be turned off. Any other value representes
|
service will be turned off. Any other value greater than 0
|
||||||
password dissector being turned on. In case that the
|
represents password dissector being turned on. In case that the
|
||||||
STATUS value is the same of the password dissector service's
|
STATUS value is the same of the password dissector service's
|
||||||
then the instruction will be ignored.
|
then the instruction will be ignored.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0E' - GET PROXY AUTHENTICATION STATUS
|
3.10. CMD: X'09' - GET PROXY AUTHENTICATION STATUS
|
||||||
|
|
||||||
Requests the status of the authentication service on the
|
Requests the status of the authentication service on the
|
||||||
proxy server.
|
proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action and a STATUS representing the status of the
|
the action and a STATUS representing the status of the
|
||||||
authentication service.
|
authentication service.
|
||||||
|
|
||||||
|
@ -479,7 +394,7 @@ CMD: X'0E' - GET PROXY AUTHENTICATION STATUS
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
| VER | TOKEN | CMD |
|
| VER | TOKEN | CMD |
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
| X'01' | 8 | X'0E' |
|
| X'01' | 8 | X'09' |
|
||||||
+-------+-------+---------+
|
+-------+-------+---------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -491,28 +406,29 @@ CMD: X'0E' - GET PROXY AUTHENTICATION STATUS
|
||||||
|
|
||||||
STATUS represents the status of the authentication
|
STATUS represents the status of the authentication
|
||||||
service. If STATUS is X'00' then authentication service
|
service. If STATUS is X'00' then authentication service
|
||||||
is down. Any other value representes authentication
|
is down. Any other value greater than 0 represents
|
||||||
being active.
|
authentication being active.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0F' - SET PROXY AUTHENTICATION STATUS
|
3.11. CMD: X'0A' - SET PROXY AUTHENTICATION STATUS
|
||||||
|
|
||||||
Modifies the status of the authentication service on the
|
Modifies the status of the authentication service on the
|
||||||
proxy server.
|
proxy server.
|
||||||
Response comes as with a code representing the output of
|
Response comes with a code representing the output of
|
||||||
the action.
|
the action.
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| VER | TOKEN | CMD | STATUS |
|
| VER | TOKEN | CMD | STATUS |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
| X'01' | 8 | X'0F' | 1 |
|
| X'01' | 8 | X'0A' | 1 |
|
||||||
+-------+-------+---------+--------+
|
+-------+-------+---------+--------+
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
@ -522,332 +438,37 @@ CMD: X'0F' - SET PROXY AUTHENTICATION STATUS
|
||||||
| X'01' | 1 |
|
| X'01' | 1 |
|
||||||
+-------+--------+
|
+-------+--------+
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
|
||||||
service. If STATUS is X'00' then
|
|
||||||
authentication service will be turned off. Any other
|
|
||||||
value representesauthentication being turned on.
|
|
||||||
In case that the STATUS value is the same of the
|
|
||||||
password dissector service's then the instruction will
|
|
||||||
be ignored.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3. Replies
|
|
||||||
|
|
||||||
The SOCKS request information is sent by the client as soon as
|
|
||||||
it has established a connection to the SOCKS server, and completed
|
|
||||||
the authentication negotiations. The server evaluates the request,
|
|
||||||
and returns a reply formed as follows:
|
|
||||||
|
|
||||||
+-----+-----+
|
|
||||||
| VER | REP |
|
|
||||||
+-----+-----+
|
|
||||||
| 1 | 1 |
|
|
||||||
+-----+-----+
|
|
||||||
|
|
||||||
Where:
|
|
||||||
|
|
||||||
o VER protocol version: X'05'
|
|
||||||
o REP Reply field:
|
|
||||||
o X'00' succeeded
|
|
||||||
o X'01' general SOCKS server failure
|
|
||||||
o X'02' connection not allowed by ruleset
|
|
||||||
o X'03' Network unreachable
|
|
||||||
o X'04' Host unreachable
|
|
||||||
o X'05' Connection refused
|
|
||||||
o X'06' TTL expired
|
|
||||||
o X'07' Command not supported
|
|
||||||
o X'08' Address type not supported
|
|
||||||
o X'09' to X'FF' unassigned
|
|
||||||
|
|
||||||
9. References The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'C1' USER NOT FOUND
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'09' - MODIFY PASSWORD
|
|
||||||
|
|
||||||
Modifies password of user of proxy server with username
|
|
||||||
UNAME.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
| X'01' | 8 | X'09' | 1 | 1 to 255 | 1 | 1 to 255 |
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
UNAME is a valid SOCKSv5 username and PASS is a valid
|
|
||||||
SOCKSv5 password. PASS represents de new value for the
|
|
||||||
passowrd of the user with the username UNAME. ULEN
|
|
||||||
describes the length of UNAME, PLEN describes the
|
|
||||||
length of PASS.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'C1' USER NOT FOUND
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'0A' - ADD USER
|
|
||||||
|
|
||||||
Adds a user to the proxy server.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME | PLEN | PASS |
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
| X'01' | 8 | X'0A' | 1 | 1 to 255 | 1 | 1 to 255 |
|
|
||||||
+-------+-------+---------+--------+-----------+-------+----------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
UNAME is a valid SOCKSv5 username and PASS is a
|
|
||||||
valid SOCKSv5 password. UNAME represents the value
|
|
||||||
for the username of the new user and PASS represents
|
|
||||||
the value for the password of user. ULEN describes the
|
|
||||||
length of UNAME, PLEN describes the length of PASS.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'0B' - DELETE USER
|
|
||||||
|
|
||||||
Deletes a user from the proxy server.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+--------+-----------+
|
|
||||||
| VER | TOKEN | CMD | ULEN | UNAME |
|
|
||||||
+-------+-------+---------+--------+-----------+
|
|
||||||
| X'01' | 8 | X'0B' | 1 | 1 to 255 |
|
|
||||||
+-------+-------+---------+--------+-----------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
UNAME is a valid SOCKSv5 username. UNAME represents
|
|
||||||
the value for the username of the user to be deleted.
|
|
||||||
ULEN describes the length of UNAME.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'C0' INVALID PARAMETER VALUE
|
|
||||||
o X'C1' USER NOT FOUND
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'0C' - GET PASSWORD DISSECTOR STATUS
|
|
||||||
|
|
||||||
Requests the status of the password dissector service on
|
|
||||||
the proxy server.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action and a STATUS representing the status of the
|
|
||||||
password dissector.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+
|
|
||||||
| VER | TOKEN | CMD |
|
|
||||||
+-------+-------+---------+
|
|
||||||
| X'01' | 8 | X'0C' |
|
|
||||||
+-------+-------+---------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+--------+
|
|
||||||
| VER | CODE | STATUS |
|
|
||||||
+-------+--------+--------+
|
|
||||||
| X'01' | 1 | 1 |
|
|
||||||
+-------+--------+--------+
|
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
|
||||||
service. If STATUS is X'00' then password dissector
|
|
||||||
service is down. Any other value representes password
|
|
||||||
dissector being active.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'0D' - SET PASSWORD DISSECTOR STATUS
|
|
||||||
|
|
||||||
Modifies the status of the password dissector service on
|
|
||||||
the proxy server.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
| VER | TOKEN | CMD | STATUS |
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
| X'01' | 8 | X'0D' | 1 |
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
|
||||||
| VER | CODE |
|
|
||||||
+-------+--------+
|
|
||||||
| X'01' | 1 |
|
|
||||||
+-------+--------+
|
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
|
||||||
service. If STATUS is X'00' then password dissector
|
|
||||||
service will be turned off. Any other value representes
|
|
||||||
password dissector being turned on. In case that the
|
|
||||||
STATUS value is the same of the password dissector service's
|
|
||||||
then the instruction will be ignored.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
|
||||||
|
|
||||||
o X'00' OK
|
|
||||||
o X'B0' INVALID TOKEN
|
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
CMD: X'0E' - GET PROXY AUTHENTICATION STATUS
|
|
||||||
|
|
||||||
Requests the status of the authentication service on the
|
|
||||||
proxy server.
|
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action and a STATUS representing the status of the
|
|
||||||
authentication service.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+
|
|
||||||
| VER | TOKEN | CMD |
|
|
||||||
+-------+-------+---------+
|
|
||||||
| X'01' | 8 | X'0E' |
|
|
||||||
+-------+-------+---------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+--------+
|
|
||||||
| VER | CODE | STATUS |
|
|
||||||
+-------+--------+--------+
|
|
||||||
| X'01' | 1 | 1 |
|
|
||||||
+-------+--------+--------+
|
|
||||||
|
|
||||||
STATUS represents the status of the authentication
|
STATUS represents the status of the authentication
|
||||||
service. If STATUS is X'00' then authentication service
|
service. If STATUS is X'00' then authentication
|
||||||
is down. Any other value representes authentication
|
service will be turned off. Any other value greater
|
||||||
being active.
|
than 0 represents authentication being turned on.
|
||||||
|
In case that the STATUS value is the same of the
|
||||||
|
password dissector service's then the instruction
|
||||||
|
will be ignored.
|
||||||
|
|
||||||
The possible values for CODE are:
|
The possible values for CODE are:
|
||||||
|
|
||||||
o X'00' OK
|
o X'00' OK
|
||||||
|
o X'A0' SERVER ERROR
|
||||||
o X'B0' INVALID TOKEN
|
o X'B0' INVALID TOKEN
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
o X'D0' VERSION NOT SUPPORTED
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
o X'FF' METHOD NOT SUPPORTED
|
||||||
|
|
||||||
CMD: X'0F' - SET PROXY AUTHENTICATION STATUS
|
4. Considerations
|
||||||
|
|
||||||
Modifies the status of the authentication service on the
|
If an invalid CMD is requested to a server, it must
|
||||||
proxy server.
|
respond with a package such as:
|
||||||
Response comes as with a code representing the output of
|
|
||||||
the action.
|
|
||||||
|
|
||||||
Request:
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
| VER | TOKEN | CMD | STATUS |
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
| X'01' | 8 | X'0F' | 1 |
|
|
||||||
+-------+-------+---------+--------+
|
|
||||||
|
|
||||||
Response:
|
|
||||||
+-------+--------+
|
+-------+--------+
|
||||||
| VER | CODE |
|
| VER | CODE |
|
||||||
+-------+--------+
|
+-------+--------+
|
||||||
| X'01' | 1 |
|
| X'01' | X'FE' |
|
||||||
+-------+--------+
|
+-------+--------+
|
||||||
|
|
||||||
STATUS represents the status of the password dissector
|
Where the CODE X'FE' means that the command is unknown.
|
||||||
service. If STATUS is X'00' then
|
|
||||||
authentication service will be turned off. Any other
|
|
||||||
value representesauthentication being turned on.
|
|
||||||
In case that the STATUS value is the same of the
|
|
||||||
password dissector service's then the instruction will
|
|
||||||
be ignored.
|
|
||||||
|
|
||||||
The possible values for CODE are:
|
5. Authors
|
||||||
|
|
||||||
o X'00' OK
|
Barmasch, Juan Martín (61033)
|
||||||
o X'B0' INVALID TOKEN
|
Bellver, Ezequiel (61268)
|
||||||
o X'D0' VERSION NOT SUPPORTED
|
Lo Coco, Santiago (61301)
|
||||||
o X'FF' METHOD NOT SUPPORTED
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3. Replies
|
|
||||||
|
|
||||||
The SOCKS request information is sent by the client as soon as
|
|
||||||
it has established a connection to the SOCKS server, and completed
|
|
||||||
the authentication negotiations. The server evaluates the request,
|
|
||||||
and returns a reply formed as follows:
|
|
||||||
|
|
||||||
+-----+-----+
|
|
||||||
| VER | REP |
|
|
||||||
+-----+-----+
|
|
||||||
| 1 | 1 |
|
|
||||||
+-----+-----+
|
|
||||||
|
|
||||||
Where:
|
|
||||||
|
|
||||||
o VER protocol version: X'05'
|
|
||||||
o REP Reply field:
|
|
||||||
o X'00' succeeded
|
|
||||||
o X'01' general SOCKS server failure
|
|
||||||
o X'02' connection not allowed by ruleset
|
|
||||||
o X'03' Network unreachable
|
|
||||||
o X'04' Host unreachable
|
|
||||||
o X'05' Connection refused
|
|
||||||
o X'06' TTL expired
|
|
||||||
o X'07' Command not supported
|
|
||||||
o X'08' Address type not supported
|
|
||||||
o X'09' to X'FF' unassigned
|
|
||||||
|
|
||||||
9. References
|
|
||||||
|
|
157
docs/socks5d.8
157
docs/socks5d.8
|
@ -1,132 +1,121 @@
|
||||||
.\" Macros
|
.\" Macros
|
||||||
.ds PX \s-1POSIX\s+1
|
.ds PX \s-1POSIX\s+1
|
||||||
.de EXAMPLE .\" Format de los ejemplos
|
.de EXAMPLE .\" Example formta
|
||||||
.RS 10
|
.RS 10
|
||||||
.BR "\\$1"
|
.BR "\\$1"
|
||||||
.RE
|
.RE
|
||||||
..
|
..
|
||||||
|
|
||||||
.TH socks5d 0.0.0 "24 de mayo 2022"
|
.TH socks5d 1.0 "21 June 2022"
|
||||||
.LO 8
|
.LO 8
|
||||||
.SH NAME
|
.SH NAME
|
||||||
socks5d \- proxy SOCKS versión 5 con esteroides
|
socks5d \- proxy SOCKS version 5 (BProxy)
|
||||||
|
|
||||||
.SH SINOPSIS
|
.SH SYNOPSIS
|
||||||
.HP 10
|
.HP 10
|
||||||
.B socks5d
|
.B socks5d
|
||||||
[ POSIX style options ]
|
[ POSIX style options ]
|
||||||
|
|
||||||
.SH OPCIONES
|
.SH OPTIONS
|
||||||
|
|
||||||
.\".IP "\fB\-d\fB"
|
|
||||||
.\"Establece que debe ejecutar con la configuración predeterminada.
|
|
||||||
.\".IP
|
|
||||||
.\"Aquellos servidores donde la configuración sea persistente (el enunciado
|
|
||||||
.\"no lo requiere) presentan un desafío a la hora de realizar pruebas ya que
|
|
||||||
.\"se debe conocer la configuración actual.
|
|
||||||
.\".IP
|
|
||||||
.\"En esos casos esta opción olvida toda configuración previa y establece
|
|
||||||
.\"la configuración predeterminada.
|
|
||||||
.\".IP
|
|
||||||
.\"La configuración predeterminada consiste en tener apagada las transformaciones.
|
|
||||||
|
|
||||||
.IP "\fB-h\fR"
|
.IP "\fB-h\fR"
|
||||||
Imprime la ayuda y termina.
|
Prints help.
|
||||||
|
|
||||||
.IP "\fB\-l\fB \fIdirección-socks\fR"
|
.IP "\fB\-l\fB \fIsocks-address\fR"
|
||||||
Establece la dirección donde servirá el proxy SOCKS.
|
Establishes address where proxy SOCKS will be served.
|
||||||
Por defecto escucha en todas las interfaces.
|
By default listens in every interface.
|
||||||
|
|
||||||
.IP "\fB\-N\fB"
|
.IP "\fB\-L\fB \fImanagement-address\fR"
|
||||||
Deshabilita los passwords disectors.
|
Establishes address where management srrver will be served.
|
||||||
|
By default listens to loopback.
|
||||||
|
|
||||||
.IP "\fB\-L\fB \fIdirección-de-management\fR"
|
.IP "\fB\-p\fB \fIsocks-port\fR"
|
||||||
Establece la dirección donde servirá el servicio de
|
TCP port where it will listen for incoming SOCKS connections.
|
||||||
management. Por defecto escucha únicamente en loopback.
|
Default value is \fI1080\fR.
|
||||||
|
|
||||||
.IP "\fB\-p\fB \fIpuerto-local\fR"
|
.IP "\fB\-P\fB \fImanagement-port\fR"
|
||||||
Puerto TCP donde escuchará por conexiones entrantes SOCKS.
|
UDP port where it will listen for incoming Bottler Configuration Protocol connections
|
||||||
Por defecto el valor es \fI1080\fR.
|
Default value is \fI8080\fR.
|
||||||
|
|
||||||
.IP "\fB\-P\fB \fIpuerto-conf\fR"
|
|
||||||
Puerto SCTP donde escuchará por conexiones entrante del protocolo
|
|
||||||
de configuración. Por defecto el valor es \fI8080\fR.
|
|
||||||
|
|
||||||
.IP "\fB\-u\fB \fIuser:pass\fR"
|
.IP "\fB\-u\fB \fIuser:pass\fR"
|
||||||
Declara un usuario del proxy con su contraseña. Se puede utilizar
|
Declares a proxy user with its password <uname>:<pass>.
|
||||||
hasta 10 veces.
|
A maximum of 1024 users is established.
|
||||||
|
|
||||||
|
|
||||||
.IP "\fB\-v\fB"
|
.IP "\fB\-v\fB"
|
||||||
Imprime información sobre la versión versión y termina.
|
Prints version information.
|
||||||
|
|
||||||
.SH REGISTRO DE ACCESO
|
.SH ACCESS LOGGING
|
||||||
|
|
||||||
Registra el uso del proxy en salida estandar. Una conexión por línea. Los campos de una
|
Logs use of proxy server in standard output and file \fIaccess.log\fR. A line per connections.
|
||||||
línea separado por tabs:
|
Each field is delimited by a space:
|
||||||
|
|
||||||
.IP "\fBfecha\fR"
|
.IP "\fBdate\fR"
|
||||||
que se procesó la conexión en formato ISO-8601.
|
in which the connection has been made in ISO-8601 format.
|
||||||
Ejemplo 2022-06-15T19:56:34Z.
|
Example 2022-06-15T19:56:34Z.
|
||||||
|
|
||||||
.IP "\fBnombre de usuario\fR"
|
.IP "\fBusername\fR"
|
||||||
que hace el requerimiento.
|
that makes the request. \fIanon\fR if not authenticated.
|
||||||
Ejemplo juan.
|
Example user123.
|
||||||
|
|
||||||
.IP "\fBtipo de registro\fR"
|
.IP "\fBregister type\fR"
|
||||||
Siempre el caracter A.
|
Always character A.
|
||||||
|
|
||||||
.IP "\fBdireccion IP origen\fR"
|
.IP "\fBorigin IP address\fR"
|
||||||
desde donde se conectó el usuario.
|
from which the user made the connection.
|
||||||
Ejemplo ::1.
|
Example ::1.
|
||||||
|
|
||||||
.IP "\fBpuerto origen\fR"
|
.IP "\fBorigin port\fR"
|
||||||
desde donde se conectó el usuario.
|
from which the user made the connection.
|
||||||
Ejemplo 54786.
|
Example 54786.
|
||||||
|
|
||||||
.IP "\fBdestino\fR"
|
.IP "\fBdestination\fR"
|
||||||
a donde nos conectamos. nombre o dirección IP (según ATY).
|
to which the connection has been made. Name or IP address (according to ATY).
|
||||||
Ejemplo www.itba.edu.ar.
|
Example www.itba.edu.ar.
|
||||||
Ejemplo ::1.
|
Example ::1.
|
||||||
|
|
||||||
.IP "\fBpuerto destino\fR" a donde nos conectamos.
|
.IP "\fBdestination port\fR"
|
||||||
Ejemplo 443.
|
to which the connection has been made.
|
||||||
|
Example 443.
|
||||||
|
|
||||||
.IP "\fBstatus\fR" status SOCKS (0 exito, ...)
|
.IP "\fBstatus\fR"
|
||||||
Status code de SOCKSv5. Ejemplo 0.
|
status SOCKS (0 success, ...)
|
||||||
|
Status code de SOCKSv5. Example 0.
|
||||||
|
|
||||||
|
|
||||||
.SH REGISTRO DE PASSWORDS
|
.SH PASSWORD LOGGING
|
||||||
|
|
||||||
Registra las credenciales descubiertas en salida estandar. Una credencial por línea.
|
Logs uncovered credentials in standard output and file \fIpasswords.log\fR. One
|
||||||
Los campos de una línea separados por tabs:
|
credential per line. Fields are delimited by spaces:
|
||||||
|
|
||||||
.IP "\fBfecha\fR"
|
.IP "\fBdate\fR"
|
||||||
que se procesó la conexión en formato ISO-8601.
|
in which the connection has been processed in ISO-8601 format.
|
||||||
Ejemplo 2020-06-15T19:56:34Z.
|
Example 2020-06-15T19:56:34Z.
|
||||||
|
|
||||||
.IP "\fBnombre de usuario\fR"
|
.IP "\fBusername\fR"
|
||||||
que hace el requerimiento.
|
that makes the request. \fIanon\fR if not authenticated
|
||||||
Ejemplo juan.
|
Example user123.
|
||||||
|
|
||||||
.IP "\fBtipo de registro\fR"
|
.IP "\fBregister type\fR"
|
||||||
Siempre el caracter P.
|
Always character P.
|
||||||
|
|
||||||
|
|
||||||
.IP "\fBprotocolo\fR"
|
.IP "\fBprotocol\fR"
|
||||||
Protocolo del que se trata. HTTP o POP3.
|
Inferred protocol user. If unknown then UNK.
|
||||||
|
Between partenthesis if suspected.
|
||||||
|
|
||||||
.IP "\fBdestino\fR"
|
.IP "\fBdestination\fR"
|
||||||
a donde nos conectamos. nombre o dirección IP (según ATY).
|
to which the connection has been made. Name or IP address (according to ATY).
|
||||||
Ejemplo www.itba.edu.ar.
|
Example www.itba.edu.ar.
|
||||||
Ejemplo ::1.
|
Example ::1.
|
||||||
|
|
||||||
.IP "\fBpuerto destino\fR" a donde nos conectamos.
|
.IP "\fBdestination port\fR"
|
||||||
Ejemplo 443.
|
to which the connection has been made.
|
||||||
|
Example 443.
|
||||||
|
|
||||||
.IP "\fBusuario\fR"
|
.IP "\fBdiss_user\fR"
|
||||||
Usuario descubierto.
|
Uncovered username.
|
||||||
|
|
||||||
.IP "\fBpassword\fR"
|
.IP "\fBdiss_pass\fR"
|
||||||
Password descubierta.
|
Uncovered password.
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MAX_USERS 10
|
#define MAX_USERS 1024
|
||||||
|
|
||||||
typedef struct user_t {
|
typedef struct user_t {
|
||||||
char * name;
|
char * name;
|
||||||
char * pass;
|
char * pass;
|
||||||
|
int ulen;
|
||||||
} user_t;
|
} user_t;
|
||||||
|
|
||||||
struct socks5args {
|
struct socks5args {
|
||||||
|
@ -19,7 +20,7 @@ struct socks5args {
|
||||||
|
|
||||||
bool dissector_enabled;
|
bool dissector_enabled;
|
||||||
|
|
||||||
int nusers;
|
unsigned nusers;
|
||||||
|
|
||||||
user_t users[MAX_USERS];
|
user_t users[MAX_USERS];
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ enum auth_state {
|
||||||
auth_passwd,
|
auth_passwd,
|
||||||
auth_done,
|
auth_done,
|
||||||
auth_error_unsupported_version,
|
auth_error_unsupported_version,
|
||||||
|
auth_user_error
|
||||||
};
|
};
|
||||||
|
|
||||||
struct auth_parser {
|
struct auth_parser {
|
||||||
|
@ -21,7 +22,7 @@ struct auth_parser {
|
||||||
void * data;
|
void * data;
|
||||||
enum auth_state state;
|
enum auth_state state;
|
||||||
int user_pos;
|
int user_pos;
|
||||||
char username[255];
|
char * username;
|
||||||
char idx;
|
char idx;
|
||||||
char password[255];
|
char password[255];
|
||||||
uint8_t * verified;
|
uint8_t * verified;
|
||||||
|
@ -40,6 +41,6 @@ extern const char * auth_error(const struct auth_parser *p);
|
||||||
|
|
||||||
void auth_parser_close(struct auth_parser *p);
|
void auth_parser_close(struct auth_parser *p);
|
||||||
|
|
||||||
extern int auth_marshall(buffer * b, uint8_t method);
|
extern int auth_marshall(buffer * b, uint8_t status);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define BUFFER_H
|
#define BUFFER_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h> // size_t, ssize_t
|
#include <unistd.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* buffer.c - buffer con acceso directo (útil para I/O) que mantiene
|
* buffer.c - buffer con acceso directo (útil para I/O) que mantiene
|
||||||
|
|
|
@ -2,29 +2,25 @@
|
||||||
#define CLIENT_H
|
#define CLIENT_H
|
||||||
|
|
||||||
#define CMD_GET_METRICS 0x00
|
#define CMD_GET_METRICS 0x00
|
||||||
#define CMD_GET_BUFFER_SIZE 0x01
|
#define CMD_GET_USER_PAGES 0x01
|
||||||
#define CMD_SET_BUFFER_SIZE 0x02
|
#define CMD_LIST_USERS 0x02
|
||||||
#define CMD_GET_TIMEOUT 0x03
|
#define CMD_MODIFY_USERNAME 0x03
|
||||||
#define CMD_SET_TIMEOUT 0x04
|
#define CMD_MODIFY_PASSWORD 0x04
|
||||||
#define CMD_GET_USER_PAGES 0x05
|
#define CMD_ADD_USER 0x05
|
||||||
#define CMD_LIST_USERS 0x06
|
#define CMD_DELETE_USER 0x06
|
||||||
#define CMD_GET_USER_LAST_CONNECTION 0x07
|
#define CMD_GET_PASSWORD_DISSECTOR_STATUS 0x07
|
||||||
#define CMD_MODIFY_USERNAME 0x08
|
#define CMD_MODIFY_PASSWORD_DISSECTOR_STATUS 0x08
|
||||||
#define CMD_MODIFY_PASSWORD 0x09
|
#define CMD_GET_AUTHENTICATION_STATUS 0x09
|
||||||
#define CMD_ADD_USER 0x0A
|
#define CMD_MODIFY_AUTHENTICATION_STATUS 0x0A
|
||||||
#define CMD_DELETE_USER 0x00B
|
|
||||||
#define CMD_GET_PASSWORD_DISSECTOR_STATUS 0x0C
|
|
||||||
#define CMD_MODIFY_PASSWORD_DISSECTOR_STATUS 0x0D
|
|
||||||
#define CMD_GET_AUTHENTICATION_STATUS 0x0E
|
|
||||||
#define CMD_MODIFY_AUTHENTICATION_STATUS 0x0F
|
|
||||||
#define CMD_GET_PROXY_SERVER_STATUS 0x10
|
|
||||||
#define CMD_CHANGE_PROXY_SERVER_STATUS 0x11
|
|
||||||
#define CMD_RESTART_PROXY_SERVER 0x12
|
|
||||||
|
|
||||||
|
|
||||||
#define RESPONSE_OK 0x00
|
#define RESPONSE_OK 0x00
|
||||||
|
#define RESPONSE_SERVER_ERROR 0xA0
|
||||||
#define RESPONSE_INVALID_TOKEN 0xB0
|
#define RESPONSE_INVALID_TOKEN 0xB0
|
||||||
|
#define RESPONSE_INVALID_PARAMETER 0xC0
|
||||||
|
#define RESPONSE_USER_NOT_FOUND 0xC1
|
||||||
|
#define RESPONSE_USER_ALREADY_EXISTS 0xC2
|
||||||
#define RESPONSE_VERSION_NOT_SUPPORTED 0xD0
|
#define RESPONSE_VERSION_NOT_SUPPORTED 0xD0
|
||||||
|
#define RESPONSE_UNKNOWN_COMMAND 0xFE
|
||||||
#define RESPONSE_CMD_NOT_SUPPORTED 0xFF
|
#define RESPONSE_CMD_NOT_SUPPORTED 0xFF
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,27 +8,28 @@
|
||||||
#define STR_SIZE 255
|
#define STR_SIZE 255
|
||||||
|
|
||||||
#define CMD_GET_METRICS 0x00
|
#define CMD_GET_METRICS 0x00
|
||||||
#define CMD_GET_BUFFER_SIZE 0x01
|
#define CMD_GET_USER_PAGES 0x01
|
||||||
#define CMD_SET_BUFFER_SIZE 0x02
|
#define CMD_LIST_USERS 0x02
|
||||||
#define CMD_GET_TIMEOUT 0x03
|
#define CMD_MODIFY_USERNAME 0x03
|
||||||
#define CMD_SET_TIMEOUT 0x04
|
#define CMD_MODIFY_PASSWORD 0x04
|
||||||
#define CMD_GET_USER_PAGES 0x05
|
#define CMD_ADD_USER 0x05
|
||||||
#define CMD_LIST_USERS 0x06
|
#define CMD_DELETE_USER 0x006
|
||||||
#define CMD_GET_USER_LAST_CONNECTION 0x07
|
#define CMD_GET_PASSWORD_DISSECTOR_STATUS 0x07
|
||||||
#define CMD_MODIFY_USERNAME 0x08
|
#define CMD_MODIFY_PASSWORD_DISSECTOR_STATUS 0x08
|
||||||
#define CMD_MODIFY_PASSWORD 0x09
|
#define CMD_GET_AUTHENTICATION_STATUS 0x09
|
||||||
#define CMD_ADD_USER 0x0A
|
#define CMD_MODIFY_AUTHENTICATION_STATUS 0x0A
|
||||||
#define CMD_DELETE_USER 0x00B
|
|
||||||
#define CMD_GET_PASSWORD_DISSECTOR_STATUS 0x0C
|
|
||||||
#define CMD_MODIFY_PASSWORD_DISSECTOR_STATUS 0x0D
|
|
||||||
#define CMD_GET_AUTHENTICATION_STATUS 0x0E
|
|
||||||
#define CMD_MODIFY_AUTHENTICATION_STATUS 0x0F
|
|
||||||
#define CMD_GET_PROXY_SERVER_STATUS 0x10
|
|
||||||
#define CMD_CHANGE_PROXY_SERVER_STATUS 0x11
|
|
||||||
#define CMD_RESTART_PROXY_SERVER 0x12
|
|
||||||
|
|
||||||
#define CMD_NOT_SUPPORTED_CMD 0xFF
|
#define CMD_NOT_SUPPORTED_CMD 0xFF
|
||||||
|
|
||||||
|
#define CONFIG_OK 0x00
|
||||||
|
#define CONFIG_SERVER_ERROR 0xA0
|
||||||
|
#define CONFIG_INVALID_TOKEN 0xB0
|
||||||
|
#define CONFIG_INVALID_PARAMETER 0xC0
|
||||||
|
#define CONFIG_USER_NOT_FOUND 0xC1
|
||||||
|
#define CONFIG_ALREADY_USER_EXISTS 0xC2
|
||||||
|
#define CONFIG_VERSION_NOT_SUPPORTED 0xD0
|
||||||
|
#define CONFIG_UNKNOWN_COMMAND 0xFE
|
||||||
|
|
||||||
enum cmd_state {
|
enum cmd_state {
|
||||||
cmd_version,
|
cmd_version,
|
||||||
cmd_token,
|
cmd_token,
|
||||||
|
@ -38,6 +39,7 @@ enum cmd_state {
|
||||||
cmd_error_unsupported_version,
|
cmd_error_unsupported_version,
|
||||||
cmd_error_invalid_token,
|
cmd_error_invalid_token,
|
||||||
cmd_error_unsupported_command,
|
cmd_error_unsupported_command,
|
||||||
|
cmd_error_invalid_parameter
|
||||||
};
|
};
|
||||||
|
|
||||||
enum param_state {
|
enum param_state {
|
||||||
|
@ -78,6 +80,8 @@ struct cmd_parser {
|
||||||
void * parameters;
|
void * parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern bool is_valid(uint8_t c);
|
||||||
|
|
||||||
void cmd_parser_init(struct cmd_parser * p);
|
void cmd_parser_init(struct cmd_parser * p);
|
||||||
|
|
||||||
enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b);
|
enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b);
|
||||||
|
@ -86,10 +90,8 @@ enum cmd_state cmd_consume(buffer * b, struct cmd_parser * p, bool * errored);
|
||||||
|
|
||||||
bool cmd_is_done(enum cmd_state state, bool * errored);
|
bool cmd_is_done(enum cmd_state state, bool * errored);
|
||||||
|
|
||||||
extern const char * cmd_error(const struct cmd_parser * p);
|
extern uint8_t cmd_error(const struct cmd_parser * p);
|
||||||
|
|
||||||
void cmd_parser_close(struct cmd_parser * p);
|
void cmd_parser_close(struct cmd_parser * p);
|
||||||
|
|
||||||
//extern int cmd_marshall(buffer * b, uint8_t method);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "stm.h"
|
#include "stm.h"
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
|
||||||
#define BUFF_SIZE 1024
|
#define BUFF_SIZE 4096
|
||||||
|
|
||||||
struct cmd_st {
|
struct cmd_st {
|
||||||
buffer *rb, *wb;
|
buffer *rb, *wb;
|
||||||
|
|
|
@ -80,6 +80,4 @@ extern int request_marshall(buffer * b, const enum socks_response_status status)
|
||||||
|
|
||||||
enum socks_response_status errno_to_socks(int e);
|
enum socks_response_status errno_to_socks(int e);
|
||||||
|
|
||||||
enum socks_response_status cmd_resolve(struct request * request, struct sockaddr ** originaddr, socklen_t * origin_len, int * domain);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
#ifndef SERVER_H
|
#ifndef SERVER_H
|
||||||
#define SERVER_H
|
#define SERVER_H
|
||||||
|
|
||||||
|
#define PAGE_SIZE 5
|
||||||
|
#define USERNAME_MAX_LEN 256
|
||||||
|
|
||||||
int findUser(char * username);
|
int findUser(char * username);
|
||||||
|
|
||||||
int check_password(int idx, char * password);
|
int check_password(int idx, char * password);
|
||||||
bool add_user(char * username, char * password);
|
int add_user(char * username, char * password);
|
||||||
bool modify_username(char * old_uname, char * new_uname);
|
int modify_username(char * old_uname, char * new_uname);
|
||||||
bool modify_password(char * uname, char * new_pwd);
|
int modify_password(char * uname, char * new_pwd);
|
||||||
bool delete_user(char * uname);
|
bool delete_user(char * uname);
|
||||||
|
size_t get_user_pages();
|
||||||
|
bool get_users(char * buff, int page);
|
||||||
|
uint8_t verify_token(uint64_t token);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
32
src/args.c
32
src/args.c
|
@ -30,28 +30,35 @@ static void user(char * s, user_t * user) {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
p++;
|
p++;
|
||||||
char * uname = malloc(strlen(s) + 1);
|
char * uname = malloc(strlen(s) + 1);
|
||||||
|
if (uname == NULL)
|
||||||
|
return;
|
||||||
strcpy(uname, s);
|
strcpy(uname, s);
|
||||||
char * pass = malloc(strlen(p) + 1);
|
char * pass = malloc(strlen(p) + 1);
|
||||||
|
if (pass == NULL) {
|
||||||
|
free(uname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
strcpy(pass, p);
|
strcpy(pass, p);
|
||||||
user->name = uname;
|
user->name = uname;
|
||||||
user->pass = pass;
|
user->pass = pass;
|
||||||
|
user->ulen = strlen(uname) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void version(void) {
|
static void version(void) {
|
||||||
fprintf(stderr, "BProxy v0.0\nITBA Protocolos de Comunicación 2021/1 -- Grupo 7\nVer LICENSE.md\n");
|
fprintf(stderr, "BProxy v1.0\nITBA Protocolos de Comunicación 2021/1 -- Group 7\nSee LICENSE.md\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(const char *progname) {
|
static void usage(const char *progname) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s [OPTION]\n\n"
|
"Usage: %s [OPTION]\n\n"
|
||||||
" -h Imprime la ayuda y termina.\n"
|
" -h Prints help.\n"
|
||||||
" -l <SOCKS addr> Dirección donde servirá el proxy SOCKS.\n"
|
" -l <SOCKS addr> Address where proxy SOCKS will be served.\n"
|
||||||
" -L <conf addr> Dirección donde servirá el servicio de management.\n"
|
" -L <conf addr> Address where management service will be served.\n"
|
||||||
" -p <SOCKS port> Puerto entrante conexiones SOCKS.\n"
|
" -p <SOCKS port> Port for incoming SOCKS connections.\n"
|
||||||
" -P <conf port> Puerto entrante conexiones configuracion.\n"
|
" -P <conf port> Port for incoming configuration connections.\n"
|
||||||
" -u <name>:<pass> Usuario y contraseña de usuario que puede usar el proxy. Hasta 500.\n"
|
" -u <name>:<pass> Username and password of proxy user. Up to 1024.\n"
|
||||||
" -v Imprime información sobre la versión y termina.\n\n",
|
" -v Prints version information.\n\n",
|
||||||
progname);
|
progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +69,7 @@ void parse_args(const int argc, char ** argv, struct socks5args * args) {
|
||||||
args->socks_addr = NULL;
|
args->socks_addr = NULL;
|
||||||
args->socks_port = 1080;
|
args->socks_port = 1080;
|
||||||
|
|
||||||
args->mng_addr = "127.0.0.1";
|
args->mng_addr = NULL;
|
||||||
args->mng_port = 8080;
|
args->mng_port = 8080;
|
||||||
|
|
||||||
args->dissector_enabled = true;
|
args->dissector_enabled = true;
|
||||||
|
@ -70,7 +77,7 @@ void parse_args(const int argc, char ** argv, struct socks5args * args) {
|
||||||
int c;
|
int c;
|
||||||
int nusers = 0;
|
int nusers = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
c = getopt(argc, argv, "hl:L:Np:P:u:v");
|
c = getopt(argc, argv, "hl:L:p:P:u:v");
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -84,9 +91,6 @@ void parse_args(const int argc, char ** argv, struct socks5args * args) {
|
||||||
case 'L':
|
case 'L':
|
||||||
args->mng_addr = optarg;
|
args->mng_addr = optarg;
|
||||||
break;
|
break;
|
||||||
case 'N':
|
|
||||||
args->dissector_enabled = false;
|
|
||||||
break;
|
|
||||||
case 'p':
|
case 'p':
|
||||||
args->socks_port = port(optarg);
|
args->socks_port = port(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -106,7 +110,7 @@ void parse_args(const int argc, char ** argv, struct socks5args * args) {
|
||||||
version();
|
version();
|
||||||
exit(0);
|
exit(0);
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown argument %d.\n", c);
|
fprintf(stderr, "Unknown argument %d.\n", c);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/auth.c
22
src/auth.c
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
|
||||||
|
// es imprimible y distinto de ':'
|
||||||
|
bool is_valid(uint8_t c) {
|
||||||
|
return c >= 0x20 && c <= 0x7E && c != 0x3A;
|
||||||
|
}
|
||||||
|
|
||||||
void auth_parser_init(struct auth_parser * p) {
|
void auth_parser_init(struct auth_parser * p) {
|
||||||
p->state = auth_version;
|
p->state = auth_version;
|
||||||
p->remaining = 0;
|
p->remaining = 0;
|
||||||
|
@ -28,6 +33,9 @@ enum auth_state auth_parser_feed(struct auth_parser * p, uint8_t b) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case auth_uname:
|
case auth_uname:
|
||||||
|
if (!is_valid(b)) {
|
||||||
|
p->state = auth_user_error;
|
||||||
|
}
|
||||||
*(p->username + p->idx++) = (char) b;
|
*(p->username + p->idx++) = (char) b;
|
||||||
p->remaining--;
|
p->remaining--;
|
||||||
|
|
||||||
|
@ -50,6 +58,9 @@ enum auth_state auth_parser_feed(struct auth_parser * p, uint8_t b) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case auth_passwd:
|
case auth_passwd:
|
||||||
|
if (!is_valid(b)) {
|
||||||
|
p->state = auth_user_error;
|
||||||
|
}
|
||||||
*(p->password + p->idx++) = (char) b;
|
*(p->password + p->idx++) = (char) b;
|
||||||
p->remaining--;
|
p->remaining--;
|
||||||
|
|
||||||
|
@ -64,9 +75,10 @@ enum auth_state auth_parser_feed(struct auth_parser * p, uint8_t b) {
|
||||||
break;
|
break;
|
||||||
case auth_done:
|
case auth_done:
|
||||||
case auth_error_unsupported_version:
|
case auth_error_unsupported_version:
|
||||||
|
case auth_user_error:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown state %d\n", p->state);
|
fprintf(stderr, "Unknown state %d\n", p->state);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +89,7 @@ extern bool auth_is_done(const enum auth_state state, bool * errored) {
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
case auth_user_error:
|
||||||
case auth_error_unsupported_version:
|
case auth_error_unsupported_version:
|
||||||
if (0 != errored) {
|
if (0 != errored) {
|
||||||
*errored = true;
|
*errored = true;
|
||||||
|
@ -96,7 +109,10 @@ extern const char * auth_error(const struct auth_parser *p) {
|
||||||
char * ret;
|
char * ret;
|
||||||
switch (p->state) {
|
switch (p->state) {
|
||||||
case auth_error_unsupported_version:
|
case auth_error_unsupported_version:
|
||||||
ret = "unsupported version";
|
ret = "Unsupported version";
|
||||||
|
break;
|
||||||
|
case auth_user_error:
|
||||||
|
ret = "User error";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = "";
|
ret = "";
|
||||||
|
@ -123,7 +139,7 @@ extern enum auth_state auth_consume(buffer * b, struct auth_parser *p, bool * er
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int auth_marshall(buffer * b, const uint8_t status) {
|
extern int auth_marshall(buffer * b, uint8_t status) {
|
||||||
size_t n;
|
size_t n;
|
||||||
uint8_t * buff = buffer_write_ptr(b, &n);
|
uint8_t * buff = buffer_write_ptr(b, &n);
|
||||||
if (n < 2) {
|
if (n < 2) {
|
||||||
|
|
|
@ -59,7 +59,6 @@ buffer_read_adv(buffer *b, const ssize_t bytes) {
|
||||||
assert(b->read <= b->write);
|
assert(b->read <= b->write);
|
||||||
|
|
||||||
if (b->read == b->write) {
|
if (b->read == b->write) {
|
||||||
// compactacion poco costosa
|
|
||||||
buffer_compact(b);
|
buffer_compact(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +87,6 @@ buffer_write(buffer *b, uint8_t c) {
|
||||||
void
|
void
|
||||||
buffer_compact(buffer *b) {
|
buffer_compact(buffer *b) {
|
||||||
if (b->data == b->read) {
|
if (b->data == b->read) {
|
||||||
// nada por hacer
|
|
||||||
} else if (b->read == b->write) {
|
} else if (b->read == b->write) {
|
||||||
b->read = b->data;
|
b->read = b->data;
|
||||||
b->write = b->data;
|
b->write = b->data;
|
||||||
|
|
560
src/client.c
560
src/client.c
|
@ -14,53 +14,68 @@
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <netutils.h>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
#define MAX_SIZE 524
|
#define MAX_SIZE 524
|
||||||
#define MAX_RECV_SIZE 1024
|
#define MAX_RECV_SIZE 1500
|
||||||
|
#define PAGE_SIZE 5
|
||||||
|
#define MAX_USERNAME_LEN 256
|
||||||
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
static unsigned short get_port(const char *s) {
|
||||||
|
char *end = 0;
|
||||||
|
const long sl = strtol(s, &end, 10);
|
||||||
|
|
||||||
|
if (end == s || '\0' != *end || ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) || sl < 0 || sl > USHRT_MAX) {
|
||||||
|
fprintf(stderr, "Port should be in the range of 1-65536: %s\n", s);
|
||||||
|
exit(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return (unsigned short) sl;
|
||||||
|
}
|
||||||
|
|
||||||
static void version(void) {
|
static void version(void) {
|
||||||
fprintf(stderr, "BProxy v1.0\nITBA Protocolos de Comunicación 2021/1 -- Grupo 7\nVer LICENSE.md\n");
|
fprintf(stdout, "BProxy v1.0\nITBA Protocolos de Comunicación 2021/1 -- Group 7\nSee LICENSE.md\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(const char * progname) {
|
static void usage(const char * progname) {
|
||||||
fprintf(stderr,
|
fprintf(stdout,
|
||||||
"Usage: %s [token] [OPTION]\n\n"
|
"Usage: %s [OPTION]\n\n"
|
||||||
" -h Imprime la ayuda y termina.\n"
|
" -h Prints help\n"
|
||||||
" -m Obtener métricas del servidor.\n"
|
" -v Prints client version\n"
|
||||||
" -b Obtener el tamaño del buffer.\n"
|
" [TOKEN] -m Get server metrics\n"
|
||||||
" -B <value> Modificar el tamaño del buffer.\n"
|
" [TOKEN] -f Get amount of user pages\n"
|
||||||
" -t Obtener el valor del timeout.\n"
|
" [TOKEN] -u <page> Get users in a page\n"
|
||||||
" -T <value> Modificar el valor del timeout.\n"
|
" [TOKEN] -c <name>:<new_name> Change username from <name> to <new_name>\n"
|
||||||
" -f Obtener cantidad de páginas de nombres de usuario.\n"
|
" [TOKEN] -p <name>:<new_pass> Change user' with username <name> password\n"
|
||||||
" -u <page> Obtener nombres de usuario de la página especificada.\n"
|
" [TOKEN] -n <name>:<pass> Adds user to proxy server\n"
|
||||||
" -l <name> Obtener la última conexión del usuario específicado.\n"
|
" [TOKEN] -d <name> Deletes user from proxy server\n"
|
||||||
" -c <name>:<new_name> Nombre de usuario y nuevo nombre de usuario\n"
|
" [TOKEN] -s Get password dissector status\n"
|
||||||
" -p <name>:<new_pass> Nombre de usuario y su nueva contraseña\n"
|
" [TOKEN] -S <state> Modify password dissector status\n"
|
||||||
" -n <name>:<pass> Nombre de usuario y contraseña del usuario que desea ser agregado\n"
|
" [TOKEN] -a Get proxy authentication status\n"
|
||||||
" -d <name> Nombre del usuario que desea ser borrado\n"
|
" [TOKEN] -L <conf addr> Address of management service.\n"
|
||||||
" -s Obtener el estado del disector de contraseñas POP3.\n"
|
" [TOKEN] -P <conf port> Port of management service.\n"
|
||||||
" -S <estado> Modificar el estado del disector de contraseñas POP3.\n"
|
" [TOKEN] -A <state> Modify proxy authentication status\n"
|
||||||
" -a Obtener el estado de la autorización del proxy.\n"
|
"Where TOKEN is an 8-byte unsigned integer\n\n",
|
||||||
" -A <estado> Modificar el estado de la autorización del proxy.\n"
|
|
||||||
" -z Obtener el estado del servidor proxy.\n"
|
|
||||||
" -Z <estado> Modificar el estado del servidor proxy.\n"
|
|
||||||
" -r Reinicia el servidor\n\n",
|
|
||||||
progname);
|
progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// aceptar -L
|
uint8_t parse_args(int argc, char ** argv, uint8_t * buffer, char ** address, unsigned short * port) {
|
||||||
uint8_t parse_args(int argc, char ** argv, uint8_t * buffer) {
|
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (argc <= 1 || argv[1][0] == '-') {
|
if (argc <= 1) {
|
||||||
fprintf(stderr, "You must enter a valid token.\n");
|
fprintf(stderr, "You must enter a valid token\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sent_token = false;
|
||||||
|
|
||||||
|
if (argv[1][0] != '-') {
|
||||||
uint64_t token = atol(argv[1]);
|
uint64_t token = atol(argv[1]);
|
||||||
|
|
||||||
buffer[0] = 0x01;
|
buffer[0] = 0x01;
|
||||||
|
@ -78,284 +93,439 @@ uint8_t parse_args(int argc, char ** argv, uint8_t * buffer) {
|
||||||
argv[i] = argv[i+1];
|
argv[i] = argv[i+1];
|
||||||
}
|
}
|
||||||
argc--;
|
argc--;
|
||||||
|
sent_token = true;
|
||||||
c = getopt(argc, argv, "hmbtfsazrB:T:l:u:c:A:S:p:n:d:Z:");
|
|
||||||
// retorna : o ? si le falta el argumento
|
|
||||||
if (c == -1) {
|
|
||||||
fprintf(stderr, "One option required\n");
|
|
||||||
exit(EXIT_FAILURE); // TODO: chequear bien
|
|
||||||
return 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < 3 && argc > 2) {
|
char args = 0;
|
||||||
fprintf(stderr, "Only one option allowed\n");
|
bool Lpresent = false, Ppresent = false;
|
||||||
|
while (args < 3) {
|
||||||
|
if (args == 1) {
|
||||||
|
if (!(Lpresent || Ppresent))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (args == 2) {
|
||||||
|
if (!(Lpresent && Ppresent))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = getopt(argc, argv, "hvmfu:c:p:n:d:sS:aA:L:P:");
|
||||||
|
if (c == -1) {
|
||||||
|
fprintf(stderr, "A valid option is required\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
uint8_t ulen, plen, nulen;
|
size_t ulen, plen, nulen;
|
||||||
char * p;
|
char * p;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
buffer[9] = 0x00;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
buffer[9] = 0x01;
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
buffer[9] = 0x02;
|
|
||||||
buffer[9] = (uint16_t) atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
buffer[9] = 0x03;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
buffer[9] = 0x04;
|
|
||||||
value = atoi(optarg);
|
|
||||||
buffer[10] = value >> 8;
|
|
||||||
buffer[11] = (uint8_t) value;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
buffer[9] = 0x05;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
buffer[9] = 0x06;
|
|
||||||
value = atoi(optarg);
|
|
||||||
buffer[10] = value >> 8;
|
|
||||||
buffer[11] = (uint8_t) value;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
buffer[9] = 0x07;
|
|
||||||
ulen = strlen(optarg);
|
|
||||||
buffer[10] = ulen;
|
|
||||||
strcat((char *) buffer, optarg);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
buffer[9] = 0x08;
|
|
||||||
char *n = strchr(optarg, ':');
|
|
||||||
*n = 0;
|
|
||||||
n++;
|
|
||||||
ulen = strlen(optarg);
|
|
||||||
nulen = strlen(n);
|
|
||||||
buffer[10] = ulen;
|
|
||||||
strcat((char *) buffer, optarg);
|
|
||||||
buffer[11+ulen] = nulen;
|
|
||||||
strcat((char *) buffer, n);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
buffer[9] = 0x09;
|
|
||||||
p = strchr(optarg, ':');
|
|
||||||
*p = 0;
|
|
||||||
p++;
|
|
||||||
ulen = strlen(optarg);
|
|
||||||
plen = strlen(p);
|
|
||||||
buffer[10] = ulen;
|
|
||||||
strcat((char *) buffer, optarg);
|
|
||||||
buffer[11+ulen] = plen;
|
|
||||||
strcat((char *) buffer, p);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
buffer[9] = 0x0A;
|
|
||||||
p = strchr(optarg, ':');
|
|
||||||
*p = 0;
|
|
||||||
p++;
|
|
||||||
ulen = strlen(optarg);
|
|
||||||
plen = strlen(p);
|
|
||||||
buffer[10] = ulen;
|
|
||||||
strcat((char *) buffer, optarg);
|
|
||||||
buffer[11+ulen] = plen;
|
|
||||||
strcat((char *) buffer, p);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
buffer[9] = 0x0B;
|
|
||||||
ulen = strlen(optarg);
|
|
||||||
buffer[10] = ulen;
|
|
||||||
strcat((char *) buffer, optarg);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
buffer[9] = 0x0C;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
buffer[9] = 0x0D;
|
|
||||||
buffer[10] = (uint8_t) atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
buffer[9] = 0x0E;
|
|
||||||
break;
|
|
||||||
case 'A':
|
|
||||||
buffer[9] = 0x0F;
|
|
||||||
buffer[10] = (uint8_t) atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'z':
|
|
||||||
buffer[9] = 0x10;
|
|
||||||
break;
|
|
||||||
case 'Z':
|
|
||||||
buffer[9] = 0x11;
|
|
||||||
buffer[10] = (uint8_t) atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
buffer[9] = 0x12;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
default:
|
case 'm':
|
||||||
fprintf(stderr, "Unknown argument %d.\n", c);
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
buffer[9] = CMD_GET_METRICS;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_GET_USER_PAGES;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_LIST_USERS;
|
||||||
|
value = atoi(optarg);
|
||||||
|
buffer[10] = value >> 8;
|
||||||
|
buffer[11] = (uint8_t) value;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_MODIFY_USERNAME;
|
||||||
|
char *n = strchr(optarg, ':');
|
||||||
|
if (n == NULL) {
|
||||||
|
fprintf(stderr, "New username not found\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*n = 0;
|
||||||
|
n++;
|
||||||
|
ulen = strlen(optarg);
|
||||||
|
if (ulen == 0 || ulen > 255) {
|
||||||
|
fprintf(stderr, "Username length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
nulen = strlen(n);
|
||||||
|
if (nulen == 0 || nulen > 255) {
|
||||||
|
fprintf(stderr, "New username length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[10] = (uint8_t) ulen;
|
||||||
|
strcat((char *) buffer, optarg);
|
||||||
|
buffer[11+ulen] = (uint8_t) nulen;
|
||||||
|
strcat((char *) buffer, n);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_MODIFY_PASSWORD;
|
||||||
|
p = strchr(optarg, ':');
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(stderr, "New password not found\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
p++;
|
||||||
|
ulen = strlen(optarg);
|
||||||
|
if (ulen == 0 || ulen > 255) {
|
||||||
|
fprintf(stderr, "Username length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
plen = strlen(p);
|
||||||
|
if (plen == 0 || plen > 255) {
|
||||||
|
fprintf(stderr, "Password length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[10] = (uint8_t) ulen;
|
||||||
|
strcat((char *) buffer, optarg);
|
||||||
|
buffer[11+ulen] = (uint8_t) plen;
|
||||||
|
strcat((char *) buffer, p);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_ADD_USER;
|
||||||
|
p = strchr(optarg, ':');
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(stderr, "New password not found\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
p++;
|
||||||
|
ulen = strlen(optarg);
|
||||||
|
if (ulen == 0 || ulen > 255) {
|
||||||
|
fprintf(stderr, "Username length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
plen = strlen(p);
|
||||||
|
if (plen == 0 || plen > 255) {
|
||||||
|
fprintf(stderr, "Password length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[10] = (uint8_t) ulen;
|
||||||
|
strcat((char *) buffer, optarg);
|
||||||
|
buffer[11+ulen] = (uint8_t) plen;
|
||||||
|
strcat((char *) buffer, p);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_DELETE_USER;
|
||||||
|
ulen = strlen(optarg);
|
||||||
|
if (ulen == 0 || ulen > 255) {
|
||||||
|
fprintf(stderr, "Username length must be between 1 and 255\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[10] = (uint8_t) ulen;
|
||||||
|
strcat((char *) buffer, optarg);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_GET_PASSWORD_DISSECTOR_STATUS;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_MODIFY_PASSWORD_DISSECTOR_STATUS;
|
||||||
|
buffer[10] = (uint8_t) atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_GET_AUTHENTICATION_STATUS;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
buffer[9] = CMD_MODIFY_AUTHENTICATION_STATUS;
|
||||||
|
buffer[10] = (uint8_t) atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
Lpresent = true;
|
||||||
|
*address = optarg;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
if (!sent_token) {
|
||||||
|
fprintf(stderr, "Token required for desired command\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
Ppresent = true;
|
||||||
|
*port = get_port(optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown argument %d\n", c);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
args++;
|
||||||
|
}
|
||||||
|
|
||||||
return buffer[9];
|
return buffer[9];
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_response(uint8_t * buffer, uint8_t cmd) {
|
int parse_response(uint8_t * buffer, uint8_t cmd) {
|
||||||
if (buffer[0] != 0x01) {
|
if (buffer[0] != 0x01) {
|
||||||
fprintf(stderr, "Incorrect response version.\n");
|
fprintf(stderr, "Incorrect response version\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t now_conn = 0, total_conn = 0;
|
uint32_t now_conn = 0, total_conn = 0;
|
||||||
uint64_t bytes = 0;
|
uint64_t bytes = 0;
|
||||||
|
uint16_t pages, k = 0, users = 0;
|
||||||
|
|
||||||
switch (buffer[1]) {
|
switch (buffer[1]) {
|
||||||
case RESPONSE_OK:
|
case RESPONSE_OK:
|
||||||
fprintf(stdout, "Success.\n");
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case CMD_GET_METRICS:
|
case CMD_GET_METRICS:
|
||||||
fprintf(stdout, "Metrics:\n");
|
fprintf(stdout, "Metrics:\n");
|
||||||
total_conn += buffer[2];
|
total_conn += buffer[2];
|
||||||
total_conn <<= 24;
|
total_conn <<= 8;
|
||||||
total_conn += buffer[3];
|
total_conn += buffer[3];
|
||||||
total_conn <<= 16;
|
total_conn <<= 8;
|
||||||
total_conn += buffer[4];
|
total_conn += buffer[4];
|
||||||
total_conn <<= 8;
|
total_conn <<= 8;
|
||||||
total_conn += buffer[5];
|
total_conn += buffer[5];
|
||||||
|
|
||||||
now_conn += buffer[6];
|
now_conn += buffer[6];
|
||||||
now_conn <<= 24;
|
now_conn <<= 8;
|
||||||
now_conn += buffer[7];
|
now_conn += buffer[7];
|
||||||
now_conn <<= 16;
|
now_conn <<= 8;
|
||||||
now_conn += buffer[8];
|
now_conn += buffer[8];
|
||||||
now_conn <<= 8;
|
now_conn <<= 8;
|
||||||
now_conn += buffer[9];
|
now_conn += buffer[9];
|
||||||
|
|
||||||
bytes += buffer[10];
|
bytes += buffer[10];
|
||||||
bytes <<= 56;
|
bytes <<= 8;
|
||||||
bytes += buffer[11];
|
bytes += buffer[11];
|
||||||
bytes <<= 48;
|
bytes <<= 8;
|
||||||
bytes += buffer[12];
|
bytes += buffer[12];
|
||||||
bytes <<= 40;
|
bytes <<= 8;
|
||||||
bytes += buffer[13];
|
bytes += buffer[13];
|
||||||
bytes <<= 32;
|
bytes <<= 8;
|
||||||
bytes += buffer[14];
|
bytes += buffer[14];
|
||||||
bytes <<= 24;
|
bytes <<= 8;
|
||||||
bytes += buffer[15];
|
bytes += buffer[15];
|
||||||
bytes <<= 16;
|
bytes <<= 8;
|
||||||
bytes += buffer[16];
|
bytes += buffer[16];
|
||||||
bytes <<= 8;
|
bytes <<= 8;
|
||||||
bytes += buffer[17];
|
bytes += buffer[17];
|
||||||
|
|
||||||
fprintf(stdout, "\tTotal connections: %u\n\tCurrent connections: %u\n\tTotal bytes transferred: %lu\n", total_conn, now_conn, bytes);
|
fprintf(stdout, "\tTotal connections: %u\n\tCurrent connections: %u\n\tTotal bytes transferred: %lu\n", total_conn, now_conn, bytes);
|
||||||
break;
|
break;
|
||||||
/*
|
|
||||||
case CMD_GET_BUFFER_SIZE:
|
|
||||||
break;
|
|
||||||
case CMD_SET_BUFFER_SIZE:
|
|
||||||
break;
|
|
||||||
case CMD_GET_TIMEOUT:
|
|
||||||
break;
|
|
||||||
case CMD_SET_TIMEOUT:
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
case CMD_GET_USER_PAGES:
|
case CMD_GET_USER_PAGES:
|
||||||
fprintf(stdout, "User pages: ...\n"); // buffer[2 y 3];
|
pages = buffer[2];
|
||||||
|
pages <<= 8;
|
||||||
|
pages += buffer[3];
|
||||||
|
fprintf(stdout, "User pages: %u\n", pages);
|
||||||
break;
|
break;
|
||||||
case CMD_LIST_USERS:
|
case CMD_LIST_USERS:
|
||||||
fprintf(stdout, "Users... \n");
|
fprintf(stdout, "Users:\n");
|
||||||
break;
|
while (users < PAGE_SIZE && !(k > 2 && buffer[k - 1] == '\n' && buffer[k] == '\n')) {
|
||||||
case CMD_GET_USER_LAST_CONNECTION:
|
if (buffer[k] == '\n')
|
||||||
fprintf(stdout, "Users... \n");
|
users++;
|
||||||
|
putchar(buffer[k++]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_GET_PASSWORD_DISSECTOR_STATUS:
|
case CMD_GET_PASSWORD_DISSECTOR_STATUS:
|
||||||
fprintf(stdout, "Password dissector status: %s\n", buffer[2] ? "ON" : "OFF");
|
fprintf(stdout, "Password dissector status: %s\n", buffer[2] ? "ON" : "OFF");
|
||||||
break;
|
break;
|
||||||
case CMD_MODIFY_PASSWORD_DISSECTOR_STATUS:
|
|
||||||
break;
|
|
||||||
case CMD_GET_AUTHENTICATION_STATUS:
|
case CMD_GET_AUTHENTICATION_STATUS:
|
||||||
fprintf(stdout, "Proxy authentication status: %s\n", buffer[2] ? "ON" : "OFF");
|
fprintf(stdout, "Proxy authentication status: %s\n", buffer[2] ? "ON" : "OFF");
|
||||||
break;
|
break;
|
||||||
|
case CMD_MODIFY_PASSWORD_DISSECTOR_STATUS:
|
||||||
case CMD_MODIFY_AUTHENTICATION_STATUS:
|
case CMD_MODIFY_AUTHENTICATION_STATUS:
|
||||||
break;
|
|
||||||
case CMD_GET_PROXY_SERVER_STATUS:
|
|
||||||
fprintf(stdout, "Proxy server status: %s\n", buffer[2] ? "ON" : "OFF");
|
|
||||||
break;
|
|
||||||
case CMD_MODIFY_USERNAME:
|
case CMD_MODIFY_USERNAME:
|
||||||
case CMD_MODIFY_PASSWORD:
|
case CMD_MODIFY_PASSWORD:
|
||||||
case CMD_ADD_USER:
|
case CMD_ADD_USER:
|
||||||
case CMD_DELETE_USER:
|
case CMD_DELETE_USER:
|
||||||
case CMD_CHANGE_PROXY_SERVER_STATUS:
|
fprintf(stdout, "Success\n");
|
||||||
case CMD_RESTART_PROXY_SERVER:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case RESPONSE_SERVER_ERROR:
|
||||||
|
fprintf(stderr, "ERROR - Server error\n");
|
||||||
break;
|
break;
|
||||||
case RESPONSE_INVALID_TOKEN:
|
case RESPONSE_INVALID_TOKEN:
|
||||||
fprintf(stdout, "Invalid token.\n");
|
fprintf(stderr, "ERROR - Invalid token\n");
|
||||||
|
break;
|
||||||
|
case RESPONSE_INVALID_PARAMETER:
|
||||||
|
fprintf(stderr, "ERROR - Parameter value is invalid for requested command\n");
|
||||||
break;
|
break;
|
||||||
case RESPONSE_CMD_NOT_SUPPORTED:
|
case RESPONSE_CMD_NOT_SUPPORTED:
|
||||||
fprintf(stdout, "Command not supported.\n");
|
fprintf(stderr, "ERROR - Command not supported\n");
|
||||||
break;
|
break;
|
||||||
case RESPONSE_VERSION_NOT_SUPPORTED:
|
case RESPONSE_VERSION_NOT_SUPPORTED:
|
||||||
fprintf(stdout, "Version not supported.\n");
|
fprintf(stderr, "ERROR - Version not supported\n");
|
||||||
|
break;
|
||||||
|
case RESPONSE_UNKNOWN_COMMAND:
|
||||||
|
fprintf(stderr, "ERROR - Unknown command\n");
|
||||||
|
break;
|
||||||
|
case RESPONSE_USER_NOT_FOUND:
|
||||||
|
fprintf(stderr, "ERROR - Specified user not found\n");
|
||||||
|
break;
|
||||||
|
case RESPONSE_USER_ALREADY_EXISTS:
|
||||||
|
fprintf(stderr, "ERROR - Username already exists\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
fprintf(stderr, "ERROR - Unknown response status\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
const char *err_msg = NULL;
|
const char *err_msg = NULL;
|
||||||
|
uint8_t * recv_buffer = NULL;
|
||||||
|
|
||||||
struct sockaddr_in addr;
|
uint8_t buffer[MAX_SIZE] = {0};
|
||||||
memset(&addr, 0, sizeof(addr));
|
char * address = NULL;
|
||||||
addr.sin_family = AF_INET;
|
unsigned short port = 0;
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
uint8_t cmd = parse_args(argc, argv, buffer, &address, &port);
|
||||||
addr.sin_port = htons(8080);
|
int client = -1;
|
||||||
|
|
||||||
const int client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
unsigned char buf[sizeof(struct in6_addr)];
|
||||||
|
int domain = AF_INET;
|
||||||
|
if (address != NULL) {
|
||||||
|
if (inet_pton(AF_INET6, address, buf)) {
|
||||||
|
domain = AF_INET6;
|
||||||
|
} else if (!inet_pton(AF_INET, address, buf)) {
|
||||||
|
err_msg = "Incorrect network address";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr_ipv4;
|
||||||
|
if (domain == AF_INET) {
|
||||||
|
memset(&addr_ipv4, 0, sizeof(addr_ipv4));
|
||||||
|
addr_ipv4.sin_family = AF_INET;
|
||||||
|
if (address != NULL) {
|
||||||
|
if (inet_pton(AF_INET, address, &addr_ipv4.sin_addr) <= 0) {
|
||||||
|
err_msg = "Incorrect network address";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addr_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
}
|
||||||
|
if (port != 0) {
|
||||||
|
addr_ipv4.sin_port = htons(port);
|
||||||
|
} else {
|
||||||
|
addr_ipv4.sin_port = htons(8080);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 addr_ipv6;
|
||||||
|
if (domain == AF_INET6) {
|
||||||
|
memset(&addr_ipv6, 0, sizeof(addr_ipv6));
|
||||||
|
addr_ipv6.sin6_family = AF_INET6;
|
||||||
|
if (inet_pton(AF_INET6, address, &addr_ipv6.sin6_addr) <= 0) {
|
||||||
|
err_msg = "Incorrect network address";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
if (port != 0) {
|
||||||
|
addr_ipv6.sin6_port = htons(port);
|
||||||
|
} else {
|
||||||
|
addr_ipv6.sin6_port = htons(8080);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (client < 0) {
|
if (client < 0) {
|
||||||
err_msg = "Unable to create UDP socket";
|
err_msg = "Unable to create UDP socket";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(client, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
char buff[SOCKADDR_TO_HUMAN_MIN + 1];
|
||||||
|
if (domain == AF_INET) {
|
||||||
|
sockaddr_to_human(buff, SOCKADDR_TO_HUMAN_MIN, (const struct sockaddr *) &addr_ipv4);
|
||||||
|
fprintf(stdout, "Connecting to %s\n\n", buff);
|
||||||
|
if (connect(client, (struct sockaddr *) &addr_ipv4, sizeof(addr_ipv4)) < 0) {
|
||||||
err_msg = "Unable to connect to UDP socket";
|
err_msg = "Unable to connect to UDP socket";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
sockaddr_to_human(buff, SOCKADDR_TO_HUMAN_MIN, (const struct sockaddr *) &addr_ipv6);
|
||||||
|
fprintf(stdout, "Connecting to %s\n\n", buff);
|
||||||
|
if (connect(client, (struct sockaddr *) &addr_ipv6, sizeof(addr_ipv6)) < 0) {
|
||||||
|
err_msg = "Unable to connect to UDP socket";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t buffer[MAX_SIZE] = {0};
|
ssize_t sent;
|
||||||
uint8_t cmd = parse_args(argc, argv, buffer);
|
if (domain == AF_INET) {
|
||||||
|
sent = sendto(client, buffer, N(buffer), 0, NULL, sizeof(addr_ipv4));
|
||||||
ssize_t sent = sendto(client, buffer, N(buffer), 0, NULL, sizeof(addr));
|
|
||||||
if (sent < 0) {
|
if (sent < 0) {
|
||||||
err_msg = "Unable to send cmd";
|
err_msg = "Unable to send cmd";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
uint8_t * recv_buffer = calloc(1, MAX_RECV_SIZE);
|
}
|
||||||
|
else {
|
||||||
|
sent = sendto(client, buffer, N(buffer), 0, NULL, sizeof(addr_ipv6));
|
||||||
|
if (sent < 0) {
|
||||||
|
err_msg = "Unable to send cmd";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recv_buffer = calloc(1, MAX_RECV_SIZE);
|
||||||
|
if (recv_buffer == NULL) {
|
||||||
|
err_msg = "Malloc failed";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
ssize_t received = recvfrom(client, recv_buffer, MAX_RECV_SIZE, 0, NULL, NULL);
|
ssize_t received = recvfrom(client, recv_buffer, MAX_RECV_SIZE, 0, NULL, NULL);
|
||||||
if (received < 0) {
|
if (received < 0) {
|
||||||
err_msg = "Unable to receive cmd";
|
err_msg = "Unable to receive cmd";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_response(recv_buffer, cmd);
|
int ret = parse_response(recv_buffer, cmd);
|
||||||
err_msg = NULL;
|
err_msg = NULL;
|
||||||
|
|
||||||
int ret = EXIT_SUCCESS;
|
|
||||||
finally:
|
finally:
|
||||||
|
if (recv_buffer != NULL) {
|
||||||
free(recv_buffer);
|
free(recv_buffer);
|
||||||
|
}
|
||||||
if (err_msg) {
|
if (err_msg) {
|
||||||
perror(err_msg);
|
perror(err_msg);
|
||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
|
|
57
src/cmd.c
57
src/cmd.c
|
@ -2,7 +2,6 @@
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
|
||||||
|
@ -40,16 +39,22 @@ enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b) {
|
||||||
switch (p->param_state) {
|
switch (p->param_state) {
|
||||||
case param_ulen:
|
case param_ulen:
|
||||||
p->remaining = b;
|
p->remaining = b;
|
||||||
|
if (p->remaining == 0)
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
p->param_state = param_uname;
|
p->param_state = param_uname;
|
||||||
break;
|
break;
|
||||||
case param_uname:
|
case param_uname:
|
||||||
|
if (!is_valid(b)) {
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*(p->username + p->idx++) = (char) b;
|
*(p->username + p->idx++) = (char) b;
|
||||||
p->remaining--;
|
p->remaining--;
|
||||||
if (p->remaining == 0) {
|
if (p->remaining == 0) {
|
||||||
*(p->username + p->idx++) = 0;
|
*(p->username + p->idx++) = 0;
|
||||||
p->idx = 0;
|
p->idx = 0;
|
||||||
|
|
||||||
if (*p->cmd == CMD_DELETE_USER || *p->cmd == CMD_GET_USER_LAST_CONNECTION)
|
if (*p->cmd == CMD_DELETE_USER)
|
||||||
p->state = cmd_done;
|
p->state = cmd_done;
|
||||||
else if (*p->cmd == CMD_MODIFY_USERNAME)
|
else if (*p->cmd == CMD_MODIFY_USERNAME)
|
||||||
p->param_state = param_new_ulen;
|
p->param_state = param_new_ulen;
|
||||||
|
@ -59,9 +64,15 @@ enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b) {
|
||||||
break;
|
break;
|
||||||
case param_plen:
|
case param_plen:
|
||||||
p->remaining = b;
|
p->remaining = b;
|
||||||
|
if (p->remaining == 0)
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
p->param_state = param_passwd;
|
p->param_state = param_passwd;
|
||||||
break;
|
break;
|
||||||
case param_passwd:
|
case param_passwd:
|
||||||
|
if (!is_valid(b)) {
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*(p->password + p->idx++) = (char) b;
|
*(p->password + p->idx++) = (char) b;
|
||||||
p->remaining--;
|
p->remaining--;
|
||||||
|
|
||||||
|
@ -77,9 +88,15 @@ enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b) {
|
||||||
break;
|
break;
|
||||||
case param_new_ulen:
|
case param_new_ulen:
|
||||||
p->remaining = b;
|
p->remaining = b;
|
||||||
|
if (p->remaining == 0)
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
p->param_state = param_new_uname;
|
p->param_state = param_new_uname;
|
||||||
break;
|
break;
|
||||||
case param_new_uname:
|
case param_new_uname:
|
||||||
|
if (!is_valid(b)) {
|
||||||
|
p->state = cmd_error_invalid_parameter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*(p->new_username + p->idx++) = (char) b;
|
*(p->new_username + p->idx++) = (char) b;
|
||||||
p->remaining--;
|
p->remaining--;
|
||||||
|
|
||||||
|
@ -101,10 +118,11 @@ enum cmd_state cmd_parser_feed(struct cmd_parser * p, uint8_t b) {
|
||||||
case cmd_done:
|
case cmd_done:
|
||||||
case cmd_error_unsupported_version:
|
case cmd_error_unsupported_version:
|
||||||
case cmd_error_unsupported_command:
|
case cmd_error_unsupported_command:
|
||||||
|
case cmd_error_invalid_parameter:
|
||||||
case cmd_error_invalid_token:
|
case cmd_error_invalid_token:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown state %d\n", p->state);
|
fprintf(stderr, "Unknown state %d\n", p->state);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return p->state;
|
return p->state;
|
||||||
|
@ -114,7 +132,10 @@ extern bool cmd_is_done(const enum cmd_state state, bool * errored) {
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
case cmd_error_unsupported_command:
|
||||||
|
case cmd_error_invalid_token:
|
||||||
case cmd_error_unsupported_version:
|
case cmd_error_unsupported_version:
|
||||||
|
case cmd_error_invalid_parameter:
|
||||||
if (0 != errored) {
|
if (0 != errored) {
|
||||||
*errored = true;
|
*errored = true;
|
||||||
}
|
}
|
||||||
|
@ -129,20 +150,23 @@ extern bool cmd_is_done(const enum cmd_state state, bool * errored) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const char * cmd_error(const struct cmd_parser * p) {
|
extern uint8_t cmd_error(const struct cmd_parser * p) {
|
||||||
char * ret;
|
uint8_t ret;
|
||||||
switch (p->state) {
|
switch (p->state) {
|
||||||
case cmd_error_unsupported_version:
|
case cmd_error_unsupported_version:
|
||||||
ret = "Unsupported version";
|
ret = CONFIG_VERSION_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
case cmd_error_unsupported_command:
|
case cmd_error_unsupported_command:
|
||||||
ret = "Unsupported command";
|
ret = CMD_NOT_SUPPORTED_CMD;
|
||||||
break;
|
break;
|
||||||
case cmd_error_invalid_token:
|
case cmd_error_invalid_token:
|
||||||
ret = "Invalid token";
|
ret = CONFIG_INVALID_TOKEN;
|
||||||
|
break;
|
||||||
|
case cmd_error_invalid_parameter:
|
||||||
|
ret = CONFIG_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = "";
|
ret = CONFIG_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +175,6 @@ extern const char * cmd_error(const struct cmd_parser * p) {
|
||||||
|
|
||||||
extern void cmd_parser_close(struct cmd_parser * p) {}
|
extern void cmd_parser_close(struct cmd_parser * p) {}
|
||||||
|
|
||||||
|
|
||||||
extern enum cmd_state cmd_consume(buffer * b, struct cmd_parser * p, bool * errored) {
|
extern enum cmd_state cmd_consume(buffer * b, struct cmd_parser * p, bool * errored) {
|
||||||
enum cmd_state st = p->state;
|
enum cmd_state st = p->state;
|
||||||
|
|
||||||
|
@ -165,17 +188,3 @@ extern enum cmd_state cmd_consume(buffer * b, struct cmd_parser * p, bool * erro
|
||||||
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extern int cmd_marshall(buffer * b, const uint8_t status) {
|
|
||||||
// size_t n;
|
|
||||||
// uint8_t * buff = buffer_write_ptr(b, &n);
|
|
||||||
// if (n < 2) {
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// buff[0] = 0x01;
|
|
||||||
// buff[1] = status;
|
|
||||||
//
|
|
||||||
// buffer_write_adv(b, 2);
|
|
||||||
// return 2;
|
|
||||||
//}
|
|
||||||
|
|
136
src/confignio.c
136
src/confignio.c
|
@ -14,14 +14,13 @@
|
||||||
|
|
||||||
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
#define TOKEN 0x0FF1CEDEADB00B1E
|
|
||||||
|
|
||||||
static void on_token(struct cmd_parser * p, const uint64_t token) {
|
static void on_token(struct cmd_parser * p, const uint64_t token) {
|
||||||
*p->verified = (token - (uint64_t) TOKEN == 0);
|
*p->verified = verify_token(token);
|
||||||
p->state = cmd_cmd;
|
p->state = cmd_cmd;
|
||||||
if (!*p->verified)
|
if (!*p->verified) {
|
||||||
p->state = cmd_error_invalid_token;
|
p->state = cmd_error_invalid_token;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void on_cmd(struct cmd_parser * p, const uint8_t cmd) {
|
static void on_cmd(struct cmd_parser * p, const uint8_t cmd) {
|
||||||
uint8_t * selected = p->cmd;
|
uint8_t * selected = p->cmd;
|
||||||
|
@ -29,38 +28,14 @@ static void on_cmd(struct cmd_parser * p, const uint8_t cmd) {
|
||||||
case CMD_GET_METRICS:
|
case CMD_GET_METRICS:
|
||||||
*selected = CMD_GET_METRICS;
|
*selected = CMD_GET_METRICS;
|
||||||
break;
|
break;
|
||||||
case CMD_GET_BUFFER_SIZE:
|
|
||||||
*selected = CMD_GET_BUFFER_SIZE;
|
|
||||||
break;
|
|
||||||
case CMD_SET_BUFFER_SIZE:
|
|
||||||
*selected = CMD_SET_BUFFER_SIZE;
|
|
||||||
p->state = cmd_parameters;
|
|
||||||
p->remaining = 2;
|
|
||||||
p->param_state = param_value;
|
|
||||||
break;
|
|
||||||
case CMD_GET_TIMEOUT:
|
|
||||||
*selected = CMD_GET_TIMEOUT;
|
|
||||||
break;
|
|
||||||
case CMD_SET_TIMEOUT:
|
|
||||||
*selected = CMD_SET_TIMEOUT;
|
|
||||||
p->state = cmd_parameters;
|
|
||||||
p->remaining = 2;
|
|
||||||
p->param_state = param_value;
|
|
||||||
break;
|
|
||||||
case CMD_GET_USER_PAGES:
|
case CMD_GET_USER_PAGES:
|
||||||
*selected = CMD_GET_USER_PAGES;
|
*selected = CMD_GET_USER_PAGES;
|
||||||
break;
|
break;
|
||||||
case CMD_LIST_USERS:
|
case CMD_LIST_USERS:
|
||||||
*selected = CMD_LIST_USERS;
|
*selected = CMD_LIST_USERS;
|
||||||
p->state = cmd_parameters;
|
p->state = cmd_parameters;
|
||||||
p->param_state = param_byte;
|
p->param_state = param_value;
|
||||||
p->remaining = 1;
|
p->remaining = 2;
|
||||||
break;
|
|
||||||
case CMD_GET_USER_LAST_CONNECTION:
|
|
||||||
*selected = CMD_GET_USER_LAST_CONNECTION;
|
|
||||||
p->state = cmd_parameters;
|
|
||||||
p->param_state = param_ulen;
|
|
||||||
p->remaining = 1;
|
|
||||||
break;
|
break;
|
||||||
case CMD_MODIFY_USERNAME:
|
case CMD_MODIFY_USERNAME:
|
||||||
*selected = CMD_MODIFY_USERNAME;
|
*selected = CMD_MODIFY_USERNAME;
|
||||||
|
@ -104,35 +79,11 @@ static void on_cmd(struct cmd_parser * p, const uint8_t cmd) {
|
||||||
p->param_state = param_byte;
|
p->param_state = param_byte;
|
||||||
p->remaining = 1;
|
p->remaining = 1;
|
||||||
break;
|
break;
|
||||||
case CMD_GET_PROXY_SERVER_STATUS:
|
|
||||||
*selected = CMD_GET_PROXY_SERVER_STATUS;
|
|
||||||
break;
|
|
||||||
case CMD_CHANGE_PROXY_SERVER_STATUS:
|
|
||||||
*selected = CMD_CHANGE_PROXY_SERVER_STATUS;
|
|
||||||
p->state = cmd_parameters;
|
|
||||||
p->param_state = param_byte;
|
|
||||||
p->remaining = 1;
|
|
||||||
break;
|
|
||||||
case CMD_RESTART_PROXY_SERVER:
|
|
||||||
*selected = CMD_RESTART_PROXY_SERVER;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
*selected = CMD_NOT_SUPPORTED_CMD;
|
*selected = CMD_NOT_SUPPORTED_CMD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//void cmd_process(struct cmd_st * d) {
|
|
||||||
//// unsigned ret = WRITE;
|
|
||||||
//
|
|
||||||
// uint8_t m = d->status;
|
|
||||||
// const uint8_t r = m ? 0x00 : 0xFF;
|
|
||||||
// if (cmd_marshall(d->wb, (enum cmd_response_status) r) == -1) {
|
|
||||||
//// ret = ERROR;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//// return ret;
|
|
||||||
//}
|
|
||||||
|
|
||||||
#define ATTACHMENT(key) ((struct config *)(key)->data)
|
#define ATTACHMENT(key) ((struct config *)(key)->data)
|
||||||
|
|
||||||
static void config_read_init(struct selector_key * key) {
|
static void config_read_init(struct selector_key * key) {
|
||||||
|
@ -154,7 +105,6 @@ static void config_read_init(struct selector_key * key) {
|
||||||
cmd_parser_init(&d->parser);
|
cmd_parser_init(&d->parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
||||||
struct cmd_st *d = &ATTACHMENT(key)->client.cmd;
|
struct cmd_st *d = &ATTACHMENT(key)->client.cmd;
|
||||||
|
|
||||||
|
@ -165,23 +115,20 @@ ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t status;
|
|
||||||
ssize_t i = 0;
|
ssize_t i = 0;
|
||||||
buff[i++] = 0x01;
|
buff[i++] = 0x01;
|
||||||
|
|
||||||
if (!d->verified) {
|
if (d->status == CMD_NOT_SUPPORTED_CMD || d->status == CONFIG_VERSION_NOT_SUPPORTED || d->status == CONFIG_INVALID_PARAMETER || d->status == CONFIG_INVALID_TOKEN) {
|
||||||
buff[i++] = 0xB0;
|
|
||||||
buffer_write_adv(b, i);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
if (d->status == 0xFF || d->status == 0xD0 || d->status == 0xC0) {
|
|
||||||
buff[i++] = d->status;
|
buff[i++] = d->status;
|
||||||
buffer_write_adv(b, i);
|
buffer_write_adv(b, i);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
uint64_t bytes;
|
uint64_t bytes;
|
||||||
uint32_t total_conn, now_conn;
|
uint32_t total_conn, now_conn;
|
||||||
|
uint16_t pages, k = 0, users = 0, status = 1;
|
||||||
|
uint8_t buffer[PAGE_SIZE * USERNAME_MAX_LEN];
|
||||||
|
|
||||||
buff[i++] = 0x00;
|
buff[i++] = 0x00;
|
||||||
switch (d->cmd) {
|
switch (d->cmd) {
|
||||||
|
@ -210,31 +157,56 @@ ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
||||||
buff[i++] = (uint8_t) bytes;
|
buff[i++] = (uint8_t) bytes;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
// case CMD_GET_BUFFER_SIZE:
|
|
||||||
// break;
|
|
||||||
// case CMD_SET_BUFFER_SIZE:
|
|
||||||
// break;
|
|
||||||
// case CMD_GET_TIMEOUT:
|
|
||||||
// break;
|
|
||||||
// case CMD_SET_TIMEOUT:
|
|
||||||
// break;
|
|
||||||
case CMD_GET_USER_PAGES:
|
case CMD_GET_USER_PAGES:
|
||||||
|
pages = get_user_pages();
|
||||||
|
buff[i++] = (uint8_t) (pages >> 8);
|
||||||
|
buff[i++] = (uint8_t) pages;
|
||||||
break;
|
break;
|
||||||
case CMD_LIST_USERS:
|
case CMD_LIST_USERS:
|
||||||
|
if (!get_users((char *) buffer, d->value - 1)) {
|
||||||
|
buff[status] = CONFIG_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
case CMD_GET_USER_LAST_CONNECTION:
|
}
|
||||||
|
while (users < PAGE_SIZE && !(k > 0 && buffer[k - 1] == '\n' && buffer[k] == '\n')) {
|
||||||
|
if (buffer[k] == '\n') {
|
||||||
|
users++;
|
||||||
|
}
|
||||||
|
buff[i++] = buffer[k++];
|
||||||
|
}
|
||||||
|
buff[i++] = buffer[k];
|
||||||
break;
|
break;
|
||||||
case CMD_MODIFY_USERNAME:
|
case CMD_MODIFY_USERNAME:
|
||||||
status = modify_username(d->username, d->new_username);
|
ret = modify_username(d->username, d->new_username);
|
||||||
|
if (!ret) {
|
||||||
|
buff[status] = CONFIG_USER_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else if (ret == -1) {
|
||||||
|
buff[status] = CONFIG_SERVER_ERROR;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_MODIFY_PASSWORD:
|
case CMD_MODIFY_PASSWORD:
|
||||||
status = modify_password(d->username, d->password);
|
ret = modify_password(d->username, d->password);
|
||||||
|
if (!ret) {
|
||||||
|
buff[status] = CONFIG_USER_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else if (ret == -1) {
|
||||||
|
buff[status] = CONFIG_SERVER_ERROR;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_ADD_USER:
|
case CMD_ADD_USER:
|
||||||
status = add_user(d->username, d->password);
|
ret = add_user(d->username, d->password);
|
||||||
|
if (ret == -1) {
|
||||||
|
buff[status] = CONFIG_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
else if (ret == -2) {
|
||||||
|
buff[status] = CONFIG_ALREADY_USER_EXISTS;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_DELETE_USER:
|
case CMD_DELETE_USER:
|
||||||
status = delete_user(d->username);
|
if (!delete_user(d->username)) {
|
||||||
|
buff[status] = CONFIG_USER_NOT_FOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_GET_PASSWORD_DISSECTOR_STATUS:
|
case CMD_GET_PASSWORD_DISSECTOR_STATUS:
|
||||||
buff[i++] = get_pass_dissector_status();
|
buff[i++] = get_pass_dissector_status();
|
||||||
|
@ -248,15 +220,8 @@ ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
||||||
case CMD_MODIFY_AUTHENTICATION_STATUS:
|
case CMD_MODIFY_AUTHENTICATION_STATUS:
|
||||||
set_auth_status(d->byte);
|
set_auth_status(d->byte);
|
||||||
break;
|
break;
|
||||||
case CMD_GET_PROXY_SERVER_STATUS:
|
|
||||||
break;
|
|
||||||
case CMD_CHANGE_PROXY_SERVER_STATUS:
|
|
||||||
break;
|
|
||||||
case CMD_RESTART_PROXY_SERVER:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown command\n");
|
buff[status] = CONFIG_UNKNOWN_COMMAND;
|
||||||
buff[i++] = 0xFE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +229,6 @@ ssize_t cmd_process(struct selector_key *key, buffer * b) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: manejo de errores
|
|
||||||
void config_read(struct selector_key *key) {
|
void config_read(struct selector_key *key) {
|
||||||
struct cmd_st *d = &ATTACHMENT(key)->client.cmd;
|
struct cmd_st *d = &ATTACHMENT(key)->client.cmd;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
@ -281,7 +245,9 @@ void config_read(struct selector_key *key) {
|
||||||
buffer_write_adv(d->rb, n);
|
buffer_write_adv(d->rb, n);
|
||||||
const enum cmd_state st = cmd_consume(d->rb, &d->parser, &error);
|
const enum cmd_state st = cmd_consume(d->rb, &d->parser, &error);
|
||||||
|
|
||||||
if (cmd_is_done(st, &error)) {
|
if (cmd_is_done(st, 0)) {
|
||||||
|
if (error)
|
||||||
|
d->status = cmd_error(&d->parser);
|
||||||
if (SELECTOR_SUCCESS == selector_set_interest_key(key, OP_WRITE)) {
|
if (SELECTOR_SUCCESS == selector_set_interest_key(key, OP_WRITE)) {
|
||||||
if (cmd_process(key, d->wb) == 0)
|
if (cmd_process(key, d->wb) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -40,7 +40,7 @@ enum hello_state hello_parser_feed(struct hello_parser * p, uint8_t b) {
|
||||||
case hello_error_unsupported_version:
|
case hello_error_unsupported_version:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown state %d\n", p->state);
|
fprintf(stderr, "Unknown state %d\n", p->state);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,18 +37,16 @@ struct parser_event * parser_feed(struct parser *p, const uint8_t c) {
|
||||||
|
|
||||||
const struct parser_state_transition *state = p->def->states[p->state];
|
const struct parser_state_transition *state = p->def->states[p->state];
|
||||||
const size_t n = p->def->states_n[p->state];
|
const size_t n = p->def->states_n[p->state];
|
||||||
bool matched = false;
|
bool matched;
|
||||||
|
|
||||||
for (unsigned i = 0; i < n ; i++) {
|
for (unsigned i = 0; i < n ; i++) {
|
||||||
const int when = state[i].when;
|
const int when = state[i].when;
|
||||||
if (state[i].when <= 0xFF) {
|
if (state[i].when <= 0xFF) {
|
||||||
matched = (c == when);
|
matched = (c == when);
|
||||||
} else if (state[i].when == ANY) {
|
} else if (state[i].when == (int) ANY) {
|
||||||
matched = true;
|
matched = true;
|
||||||
} else if (state[i].when > 0xFF) {
|
|
||||||
matched = (type & when);
|
|
||||||
} else {
|
} else {
|
||||||
matched = false;
|
matched = (type & when);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matched) {
|
if (matched) {
|
||||||
|
|
|
@ -55,17 +55,10 @@ struct parser_definition * parser_utils_strcmpi(const char *s) {
|
||||||
|
|
||||||
struct parser_definition * def = calloc(1, sizeof(struct parser_definition));
|
struct parser_definition * def = calloc(1, sizeof(struct parser_definition));
|
||||||
|
|
||||||
// struct parser_definition def = {
|
|
||||||
// .start_state = 0,
|
|
||||||
// .states_count = 0,
|
|
||||||
// .states = NULL,
|
|
||||||
// .states_n = NULL,
|
|
||||||
// };
|
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
// estados fijos
|
// Estados fijos
|
||||||
const size_t st_eq = n;
|
const size_t st_eq = n;
|
||||||
const size_t st_neq = n + 1;
|
const size_t st_neq = n + 1;
|
||||||
|
|
||||||
|
@ -106,13 +99,6 @@ struct parser_definition * parser_utils_strcmpi(const char *s) {
|
||||||
def->states = (struct parser_state_transition **) states;
|
def->states = (struct parser_state_transition **) states;
|
||||||
def->states_n = (size_t *) nstates;
|
def->states_n = (size_t *) nstates;
|
||||||
|
|
||||||
// struct parser_definition def = {
|
|
||||||
// .start_state = 0,
|
|
||||||
// .states_count = n + 2,
|
|
||||||
// // .states = (const struct parser_state_transition **) states,
|
|
||||||
// // .states_n = (const size_t *) nstates,
|
|
||||||
// };
|
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,46 +212,6 @@ extern int request_marshall(buffer * b, const enum socks_response_status status)
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO REPLACE CON sockaddr_storage
|
|
||||||
enum socks_response_status cmd_resolve(struct request * request, struct sockaddr ** originaddr, socklen_t * origin_len, int * domain) {
|
|
||||||
enum socks_response_status ret = status_general_SOCKS_server_failure;
|
|
||||||
*domain = AF_INET;
|
|
||||||
struct sockaddr * addr = 0x00;
|
|
||||||
socklen_t addrlen = 0;
|
|
||||||
|
|
||||||
switch (request->dest_addr_type) {
|
|
||||||
case socks_req_addr_domain: {
|
|
||||||
// TODO: SOPORTAR DOMAIN QUE VIENE CON IPV6
|
|
||||||
struct hostent * hp = gethostbyname(request->dest_addr.fqdn);
|
|
||||||
if (hp == 0) {
|
|
||||||
memset(&request->dest_addr, 0x00, sizeof(request->dest_addr));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
request->dest_addr.ipv4.sin_family = hp->h_addrtype;
|
|
||||||
memcpy((char *) &request->dest_addr.ipv4.sin_addr, *hp->h_addr_list, hp->h_length);
|
|
||||||
}
|
|
||||||
case socks_req_addr_ipv4:
|
|
||||||
// *domain = AF_INET;
|
|
||||||
addr = (struct sockaddr *)&(request->dest_addr.ipv4);
|
|
||||||
addrlen = sizeof(request->dest_addr.ipv4);
|
|
||||||
request->dest_addr.ipv4.sin_port = request->dest_port;
|
|
||||||
break;
|
|
||||||
case socks_req_addr_ipv6:
|
|
||||||
*domain = AF_INET6;
|
|
||||||
addr = (struct sockaddr *) &(request->dest_addr.ipv6);
|
|
||||||
addrlen = sizeof(request->dest_addr.ipv6);
|
|
||||||
request->dest_addr.ipv6.sin6_port = request->dest_port;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return status_address_type_not_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
*originaddr = addr;
|
|
||||||
*origin_len = addrlen;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum socks_response_status errno_to_socks(int e) {
|
enum socks_response_status errno_to_socks(int e) {
|
||||||
enum socks_response_status ret = status_general_SOCKS_server_failure;
|
enum socks_response_status ret = status_general_SOCKS_server_failure;
|
||||||
switch (e) {
|
switch (e) {
|
||||||
|
|
247
src/server.c
247
src/server.c
|
@ -20,6 +20,7 @@
|
||||||
#include "socks5nio.h"
|
#include "socks5nio.h"
|
||||||
#include "confignio.h"
|
#include "confignio.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
@ -31,17 +32,42 @@ static void sigterm_handler(const int signal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct socks5args * args;
|
static struct socks5args * args;
|
||||||
|
uint64_t config_token;
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
char * token = getenv("BPROXY_TOKEN");
|
||||||
|
if (token != NULL) {
|
||||||
|
config_token = strtoul(token, NULL, 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "No token defined\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
args = malloc(sizeof(struct socks5args));
|
args = malloc(sizeof(struct socks5args));
|
||||||
parse_args(argc, argv, args);
|
parse_args(argc, argv, args);
|
||||||
|
|
||||||
|
printf("\033[0;36m");
|
||||||
|
printf("$$\\\n"
|
||||||
|
"$$ |\n"
|
||||||
|
"$$ |\n"
|
||||||
|
"$$$$$$$\\ $$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\ $$\\ $$\\ \n"
|
||||||
|
"$$ __$$\\ $$ __$$\\ $$ __$$\\ $$ __$$\\ \\$$\\ $$ |$$ | $$ |\n"
|
||||||
|
"$$ | $$ |$$ / $$ |$$ | \\__|$$ / $$ | \\$$$$ / $$ | $$ |\n"
|
||||||
|
"$$ | $$ |$$ | $$ |$$ | $$ | $$ | $$ $$< $$ | $$ |\n"
|
||||||
|
"$$$$$$$ |$$$$$$$ |$$ | \\$$$$$$ |$$ /\\$$\\ \\$$$$$$$ |\n"
|
||||||
|
"\\_______/ $$ ____/ \\__| \\______/ \\__/ \\__| \\____$$ |\n"
|
||||||
|
" $$ | $$\\ $$ |\n"
|
||||||
|
" $$ | \\$$$$$$ |\n"
|
||||||
|
" \\__| \\______/\n\n");
|
||||||
|
printf("\033[0m");
|
||||||
|
|
||||||
close(STDIN_FILENO);
|
close(STDIN_FILENO);
|
||||||
|
|
||||||
const char *err_msg = NULL;
|
const char *err_msg = NULL;
|
||||||
selector_status ss = SELECTOR_SUCCESS;
|
selector_status ss = SELECTOR_SUCCESS;
|
||||||
fd_selector selector = NULL;
|
fd_selector selector = NULL;
|
||||||
|
struct config * config_ret = NULL;
|
||||||
|
struct config * config_ret_ipv6 = NULL;
|
||||||
|
|
||||||
// ------
|
// ------
|
||||||
// TCP
|
// TCP
|
||||||
|
@ -78,7 +104,10 @@ int main(int argc, char **argv) {
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Listening on TCP port %u\n", args->socks_port);
|
if (args->socks_addr != NULL)
|
||||||
|
fprintf(stdout, "Proxy SOCKS listening on %s:%u TCP\n", args->socks_addr, args->socks_port);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "Proxy SOCKS listening on 0.0.0.0:%u TCP\n", args->socks_port);
|
||||||
|
|
||||||
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
||||||
|
|
||||||
|
@ -114,7 +143,10 @@ int main(int argc, char **argv) {
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Listening on TCP port %u\n", args->socks_port);
|
if (args->socks_addr != NULL)
|
||||||
|
fprintf(stdout, "Proxy SOCKS listening on %s:%u TCP\n", args->socks_addr, args->socks_port);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "Proxy SOCKS listening on :::%u TCP\n", args->socks_port);
|
||||||
|
|
||||||
setsockopt(server_ipv6, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
setsockopt(server_ipv6, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
||||||
setsockopt(server_ipv6, SOL_IPV6, IPV6_V6ONLY, &(int) { 1 }, sizeof(int));
|
setsockopt(server_ipv6, SOL_IPV6, IPV6_V6ONLY, &(int) { 1 }, sizeof(int));
|
||||||
|
@ -134,23 +166,40 @@ int main(int argc, char **argv) {
|
||||||
// UDP
|
// UDP
|
||||||
// ------
|
// ------
|
||||||
|
|
||||||
|
int domain_udp = -1;
|
||||||
|
if (args->mng_addr != NULL) {
|
||||||
|
if (inet_pton(AF_INET, args->mng_addr, buf)) {
|
||||||
|
domain_udp = AF_INET;
|
||||||
|
} else if (inet_pton(AF_INET6, args->mng_addr, buf)) {
|
||||||
|
domain_udp = AF_INET6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sockaddr_in udp_addr;
|
struct sockaddr_in udp_addr;
|
||||||
|
int udp_server;
|
||||||
|
if (domain_udp == AF_INET || domain_udp == -1) {
|
||||||
memset(&udp_addr, 0, sizeof(udp_addr));
|
memset(&udp_addr, 0, sizeof(udp_addr));
|
||||||
udp_addr.sin_family = AF_INET;
|
udp_addr.sin_family = AF_INET;
|
||||||
|
if (domain_udp == AF_INET) {
|
||||||
if (inet_pton(AF_INET, args->mng_addr, &udp_addr.sin_addr) <= 0) {
|
if (inet_pton(AF_INET, args->mng_addr, &udp_addr.sin_addr) <= 0) {
|
||||||
err_msg = "Incorrect network address";
|
err_msg = "Incorrect network address";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
// udp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
} else {
|
||||||
|
udp_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
}
|
||||||
udp_addr.sin_port = htons(args->mng_port);
|
udp_addr.sin_port = htons(args->mng_port);
|
||||||
|
|
||||||
const int udp_server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
udp_server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (udp_server < 0) {
|
if (udp_server < 0) {
|
||||||
err_msg = "Unable to create UDP socket";
|
err_msg = "Unable to create UDP socket";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Listening on UDP port %u\n", args->mng_port);
|
if (args->mng_addr != NULL)
|
||||||
|
fprintf(stdout, "Management service listening on %s:%u UDP\n", args->mng_addr, args->mng_port);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "Management service listening on 127.0.0.1:%u UDP\n", args->mng_port);
|
||||||
|
|
||||||
setsockopt(udp_server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
setsockopt(udp_server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
||||||
|
|
||||||
|
@ -164,10 +213,64 @@ int main(int argc, char **argv) {
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct config * config_ret = malloc(sizeof(struct config));
|
config_ret = malloc(sizeof(struct config));
|
||||||
|
if (config_ret == NULL) {
|
||||||
|
err_msg = "Malloc failed";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
memset(config_ret, 0x00, sizeof(*config_ret));
|
memset(config_ret, 0x00, sizeof(*config_ret));
|
||||||
buffer_init(&config_ret->read_buffer, N(config_ret->raw_buff_a), config_ret->raw_buff_a);
|
buffer_init(&config_ret->read_buffer, N(config_ret->raw_buff_a), config_ret->raw_buff_a);
|
||||||
buffer_init(&config_ret->write_buffer, N(config_ret->raw_buff_b), config_ret->raw_buff_b);
|
buffer_init(&config_ret->write_buffer, N(config_ret->raw_buff_b), config_ret->raw_buff_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 udp_addr_ipv6;
|
||||||
|
int udp_server_ipv6;
|
||||||
|
if (domain_udp == AF_INET6 || domain_udp == -1) {
|
||||||
|
memset(&udp_addr_ipv6, 0, sizeof(udp_addr_ipv6));
|
||||||
|
udp_addr_ipv6.sin6_family = AF_INET6;
|
||||||
|
if (domain_udp == AF_INET6) {
|
||||||
|
if (inet_pton(AF_INET6, args->mng_addr, &udp_addr_ipv6.sin6_addr) <= 0) {
|
||||||
|
err_msg = "Incorrect network address";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
udp_addr_ipv6.sin6_addr = in6addr_loopback;
|
||||||
|
}
|
||||||
|
udp_addr_ipv6.sin6_port = htons(args->mng_port);
|
||||||
|
|
||||||
|
udp_server_ipv6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (udp_server_ipv6 < 0) {
|
||||||
|
err_msg = "Unable to create UDP socket";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args->mng_addr != NULL)
|
||||||
|
fprintf(stdout, "Management service listening on %s:%u UDP\n", args->mng_addr, args->mng_port);
|
||||||
|
else
|
||||||
|
fprintf(stdout, "Management service listening on ::1:%u UDP\n", args->mng_port);
|
||||||
|
|
||||||
|
setsockopt(udp_server_ipv6, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
|
||||||
|
setsockopt(udp_server_ipv6, SOL_IPV6, IPV6_V6ONLY, &(int) { 1 }, sizeof(int));
|
||||||
|
|
||||||
|
if (bind(udp_server_ipv6, (struct sockaddr *) &udp_addr_ipv6, sizeof(udp_addr_ipv6)) < 0) {
|
||||||
|
err_msg = "Unable to bind UDP socket";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(udp_server_ipv6, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
err_msg = "Unable to put UDP socket into non-blocking mode";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_ret_ipv6 = malloc(sizeof(struct config));
|
||||||
|
if (config_ret_ipv6 == NULL) {
|
||||||
|
err_msg = "Malloc failed";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
memset(config_ret_ipv6, 0x00, sizeof(*config_ret));
|
||||||
|
buffer_init(&config_ret_ipv6->read_buffer, N(config_ret_ipv6->raw_buff_a), config_ret_ipv6->raw_buff_a);
|
||||||
|
buffer_init(&config_ret_ipv6->write_buffer, N(config_ret_ipv6->raw_buff_b), config_ret_ipv6->raw_buff_b);
|
||||||
|
}
|
||||||
|
|
||||||
signal(SIGTERM, sigterm_handler);
|
signal(SIGTERM, sigterm_handler);
|
||||||
signal(SIGINT, sigterm_handler);
|
signal(SIGINT, sigterm_handler);
|
||||||
|
@ -221,21 +324,36 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selector_fd_set_nio(udp_server) == -1) {
|
|
||||||
err_msg = "Getting config socket flags";
|
|
||||||
goto finally;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct fd_handler config = {
|
const struct fd_handler config = {
|
||||||
.handle_read = config_read,
|
.handle_read = config_read,
|
||||||
.handle_write = NULL,
|
.handle_write = NULL,
|
||||||
.handle_close = NULL,
|
.handle_close = NULL,
|
||||||
};
|
};
|
||||||
|
if (domain_udp == AF_INET || domain_udp == -1) {
|
||||||
|
if (selector_fd_set_nio(udp_server) == -1) {
|
||||||
|
err_msg = "Getting config socket flags";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
|
||||||
ss = selector_register(selector, udp_server, &config, OP_READ, config_ret);
|
ss = selector_register(selector, udp_server, &config, OP_READ, config_ret);
|
||||||
if (ss != SELECTOR_SUCCESS) {
|
if (ss != SELECTOR_SUCCESS) {
|
||||||
err_msg = "Registering fd";
|
err_msg = "Registering fd";
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain_udp == AF_INET6 || domain_udp == -1) {
|
||||||
|
if (selector_fd_set_nio(udp_server_ipv6) == -1) {
|
||||||
|
err_msg = "Getting config socket flags";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss = selector_register(selector, udp_server_ipv6, &config, OP_READ, config_ret_ipv6);
|
||||||
|
if (ss != SELECTOR_SUCCESS) {
|
||||||
|
err_msg = "Registering fd";
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(;!done;) {
|
for(;!done;) {
|
||||||
err_msg = NULL;
|
err_msg = NULL;
|
||||||
|
@ -249,15 +367,18 @@ int main(int argc, char **argv) {
|
||||||
err_msg = "Closing";
|
err_msg = "Closing";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < args->nusers; i++) {
|
int ret = 0;
|
||||||
|
finally:
|
||||||
|
for (unsigned int i = 0; i < args->nusers; i++) {
|
||||||
free(args->users[i].name);
|
free(args->users[i].name);
|
||||||
free(args->users[i].pass);
|
free(args->users[i].pass);
|
||||||
}
|
}
|
||||||
free(args);
|
free(args);
|
||||||
|
if (config_ret != NULL)
|
||||||
free(config_ret);
|
free(config_ret);
|
||||||
|
if (config_ret_ipv6 != NULL)
|
||||||
|
free(config_ret_ipv6);
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
finally:
|
|
||||||
if (ss != SELECTOR_SUCCESS) {
|
if (ss != SELECTOR_SUCCESS) {
|
||||||
fprintf(stderr, "%s: %s\n", (err_msg == NULL) ? "": err_msg, ss == SELECTOR_IO ? strerror(errno) : selector_error(ss));
|
fprintf(stderr, "%s: %s\n", (err_msg == NULL) ? "": err_msg, ss == SELECTOR_IO ? strerror(errno) : selector_error(ss));
|
||||||
ret = 2;
|
ret = 2;
|
||||||
|
@ -275,11 +396,20 @@ finally:
|
||||||
if (server >= 0) {
|
if (server >= 0) {
|
||||||
close(server);
|
close(server);
|
||||||
}
|
}
|
||||||
|
if (server_ipv6 >= 0) {
|
||||||
|
close(server_ipv6);
|
||||||
|
}
|
||||||
|
if (udp_server > 0) {
|
||||||
|
close(udp_server);
|
||||||
|
}
|
||||||
|
if (udp_server_ipv6 > 0) {
|
||||||
|
close(udp_server);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int findUser(char * username) {
|
int findUser(char * username) {
|
||||||
for (int i = 0; i < args->nusers; i++) {
|
for (unsigned int i = 0; i < args->nusers; i++) {
|
||||||
if (!strcmp(args->users[i].name, username))
|
if (!strcmp(args->users[i].name, username))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -290,36 +420,53 @@ int check_password(int idx, char * password) {
|
||||||
return !strcmp(args->users[idx].pass, password);
|
return !strcmp(args->users[idx].pass, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add_user(char * username, char * password) {
|
int add_user(char * username, char * password) {
|
||||||
|
if (findUser(username) == -1) {
|
||||||
if (args->nusers < MAX_USERS) {
|
if (args->nusers < MAX_USERS) {
|
||||||
user_t * user = malloc(sizeof(user_t));
|
int len = strlen(username) + 1;
|
||||||
user->name = malloc(strlen(username) + 1);
|
args->users[args->nusers].name = malloc(len);
|
||||||
strcpy(user->name, username);
|
if (args->users[args->nusers].name == NULL) {
|
||||||
user->pass = malloc(strlen(password) + 1);
|
return -1;
|
||||||
strcpy(user->pass, password);
|
|
||||||
args->users[args->nusers] = *user;
|
|
||||||
args->nusers++;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
strcpy(args->users[args->nusers].name, username);
|
||||||
|
args->users[args->nusers].pass = malloc(strlen(password) + 1);
|
||||||
|
if (args->users[args->nusers].pass == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strcpy(args->users[args->nusers].pass, password);
|
||||||
|
args->users[args->nusers].ulen = len;
|
||||||
|
args->nusers++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool modify_username(char * old_uname, char * new_uname) {
|
int modify_username(char * old_uname, char * new_uname) {
|
||||||
int idx = findUser(old_uname);
|
int idx = findUser(old_uname);
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
return false;
|
return 0;
|
||||||
args->users[idx].name = realloc(args->users[idx].name, strlen(new_uname) + 1);
|
int len = strlen(new_uname) + 1;
|
||||||
|
char * aux = realloc(args->users[idx].name, len);
|
||||||
|
if (aux == NULL)
|
||||||
|
return -1;
|
||||||
|
args->users[idx].name = aux;
|
||||||
strcpy(args->users[idx].name, new_uname);
|
strcpy(args->users[idx].name, new_uname);
|
||||||
return true;
|
args->users[idx].ulen = len;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool modify_password(char * uname, char * new_pwd) {
|
int modify_password(char * uname, char * new_pwd) {
|
||||||
int idx = findUser(uname);
|
int idx = findUser(uname);
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
return false;
|
return 0;
|
||||||
args->users[idx].pass = realloc(args->users[idx].pass, strlen(new_pwd) + 1);
|
char * aux = realloc(args->users[idx].pass, strlen(new_pwd) + 1);
|
||||||
|
if (aux == NULL)
|
||||||
|
return -1;
|
||||||
|
args->users[idx].pass = aux;
|
||||||
strcpy(args->users[idx].pass, new_pwd);
|
strcpy(args->users[idx].pass, new_pwd);
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delete_user(char * uname) {
|
bool delete_user(char * uname) {
|
||||||
|
@ -328,8 +475,38 @@ bool delete_user(char * uname) {
|
||||||
return false;
|
return false;
|
||||||
free(args->users[idx].name);
|
free(args->users[idx].name);
|
||||||
free(args->users[idx].pass);
|
free(args->users[idx].pass);
|
||||||
for (int i = idx; i < args->nusers; i++) {
|
for (unsigned int i = idx; i < args->nusers; i++) {
|
||||||
args->users[i] = args->users[i+1];
|
args->users[i] = args->users[i+1];
|
||||||
}
|
}
|
||||||
|
args->nusers--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_user_pages() {
|
||||||
|
return (args->nusers / PAGE_SIZE) + ((args->nusers % PAGE_SIZE != 0) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_users(char * buff, int page) {
|
||||||
|
size_t start = page * PAGE_SIZE, len = 0;
|
||||||
|
unsigned i = 0;
|
||||||
|
|
||||||
|
if (start >= args->nusers) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = start;
|
||||||
|
while (i < start + PAGE_SIZE && i < args->nusers) {
|
||||||
|
strcpy(buff + len, args->users[i].name);
|
||||||
|
len += args->users[i++].ulen;
|
||||||
|
buff[len - 1] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % PAGE_SIZE) {
|
||||||
|
buff[len] = '\n';
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t verify_token(uint64_t token) {
|
||||||
|
return token == config_token;
|
||||||
|
}
|
||||||
|
|
196
src/socks5nio.c
196
src/socks5nio.c
|
@ -24,10 +24,10 @@
|
||||||
#include "parser_utils.h"
|
#include "parser_utils.h"
|
||||||
|
|
||||||
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
#define N(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
#define BUFF_SIZE 4096 // TODO: decidir tamaño del buffer (2048 muy lento para archivos grandes!!!)
|
#define BUFF_SIZE 4096
|
||||||
#define POP3_COMMAND_ARG 249
|
#define POP3_COMMAND_ARG 249
|
||||||
|
#define USER_MAX_SIZE 249
|
||||||
|
|
||||||
// TODO: hacer que cambie con nuestro proto
|
|
||||||
bool auth_active = true;
|
bool auth_active = true;
|
||||||
bool pwd_dissector_active = false;
|
bool pwd_dissector_active = false;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ enum socks_v5state {
|
||||||
|
|
||||||
DONE,
|
DONE,
|
||||||
HELLO_ERROR,
|
HELLO_ERROR,
|
||||||
|
AUTH_ERROR,
|
||||||
REQUEST_ERROR,
|
REQUEST_ERROR,
|
||||||
ERROR,
|
ERROR,
|
||||||
};
|
};
|
||||||
|
@ -108,6 +109,7 @@ struct auth_st {
|
||||||
/** buffer utilizado para I/O */
|
/** buffer utilizado para I/O */
|
||||||
buffer *rb, *wb;
|
buffer *rb, *wb;
|
||||||
struct auth_parser parser;
|
struct auth_parser parser;
|
||||||
|
char * username;
|
||||||
uint8_t verified;
|
uint8_t verified;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,6 +195,7 @@ struct socks5 {
|
||||||
unsigned references;
|
unsigned references;
|
||||||
|
|
||||||
bool parser;
|
bool parser;
|
||||||
|
char * username;
|
||||||
|
|
||||||
struct socks5 * next;
|
struct socks5 * next;
|
||||||
};
|
};
|
||||||
|
@ -236,6 +239,7 @@ static struct socks5 * socks5_new(int client_fd) {
|
||||||
stm_init(&ret->stm);
|
stm_init(&ret->stm);
|
||||||
|
|
||||||
ret->parser = false;
|
ret->parser = false;
|
||||||
|
ret->username = NULL;
|
||||||
|
|
||||||
buffer_init(&ret->read_buffer, N(ret->raw_buff_a), ret->raw_buff_a);
|
buffer_init(&ret->read_buffer, N(ret->raw_buff_a), ret->raw_buff_a);
|
||||||
buffer_init(&ret->write_buffer, N(ret->raw_buff_b), ret->raw_buff_b);
|
buffer_init(&ret->write_buffer, N(ret->raw_buff_b), ret->raw_buff_b);
|
||||||
|
@ -270,6 +274,9 @@ socks5_destroy_(struct socks5 * s) {
|
||||||
freeaddrinfo(s->origin_resolution);
|
freeaddrinfo(s->origin_resolution);
|
||||||
s->origin_resolution = 0;
|
s->origin_resolution = 0;
|
||||||
}
|
}
|
||||||
|
if (s->username != NULL) {
|
||||||
|
free(s->username);
|
||||||
|
}
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +289,13 @@ socks5_destroy(struct socks5 * s) {
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
if (s->references == 1) {
|
if (s->references == 1) {
|
||||||
parsers_destroy(s);
|
parsers_destroy(s);
|
||||||
|
if (s->username != NULL) {
|
||||||
|
free(s->username);
|
||||||
|
}
|
||||||
|
if(s->origin_resolution != NULL) {
|
||||||
|
freeaddrinfo(s->origin_resolution);
|
||||||
|
s->origin_resolution = 0;
|
||||||
|
}
|
||||||
now_connect--;
|
now_connect--;
|
||||||
if(pool_size < max_pool) {
|
if(pool_size < max_pool) {
|
||||||
s->next = pool;
|
s->next = pool;
|
||||||
|
@ -432,8 +446,6 @@ static unsigned hello_read(struct selector_key * key) {
|
||||||
selector_set_interest_key(key, OP_WRITE);
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return error ? ERROR : ret;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,9 +517,11 @@ static void on_auth_username(struct auth_parser * p, char * username) {
|
||||||
/** callback del parser utilizado en `read_auth' */
|
/** callback del parser utilizado en `read_auth' */
|
||||||
static void on_auth_password(struct auth_parser * p, char * password) {
|
static void on_auth_password(struct auth_parser * p, char * password) {
|
||||||
uint8_t * verified = p->verified;
|
uint8_t * verified = p->verified;
|
||||||
|
if (p->user_pos >= 0) {
|
||||||
if (check_password(p->user_pos, password))
|
if (check_password(p->user_pos, password))
|
||||||
*verified = 1;
|
*verified = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** inicializa las variables de los estados HELLO_… */
|
/** inicializa las variables de los estados HELLO_… */
|
||||||
static void auth_read_init(const unsigned state, struct selector_key * key) {
|
static void auth_read_init(const unsigned state, struct selector_key * key) {
|
||||||
|
@ -518,6 +532,9 @@ static void auth_read_init(const unsigned state, struct selector_key * key) {
|
||||||
d->parser.verified = &d->verified;
|
d->parser.verified = &d->verified;
|
||||||
d->parser.on_username = on_auth_username;
|
d->parser.on_username = on_auth_username;
|
||||||
d->parser.on_password = on_auth_password;
|
d->parser.on_password = on_auth_password;
|
||||||
|
d->username = malloc(256);
|
||||||
|
ATTACHMENT(key)->username = d->username;
|
||||||
|
d->parser.username = d->username;
|
||||||
*d->parser.verified = 0;
|
*d->parser.verified = 0;
|
||||||
d->parser.idx = 0;
|
d->parser.idx = 0;
|
||||||
auth_parser_init(&d->parser);
|
auth_parser_init(&d->parser);
|
||||||
|
@ -552,7 +569,12 @@ static unsigned auth_read(struct selector_key * key) {
|
||||||
ret = ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return error ? ERROR : ret;
|
if (error) {
|
||||||
|
ret = AUTH_ERROR;
|
||||||
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** procesamiento del mensaje `auth' */
|
/** procesamiento del mensaje `auth' */
|
||||||
|
@ -564,6 +586,9 @@ static unsigned auth_process(const struct auth_st * d) {
|
||||||
if (auth_marshall(d->wb, (enum socks_response_status) r) == -1) {
|
if (auth_marshall(d->wb, (enum socks_response_status) r) == -1) {
|
||||||
ret = ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
|
if (!v) {
|
||||||
|
ret = AUTH_ERROR;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,6 +624,10 @@ static unsigned auth_write(struct selector_key * key) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned auth_write_error(struct selector_key * key) {
|
||||||
|
auth_write(key);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// REQUEST
|
// REQUEST
|
||||||
|
@ -651,7 +680,6 @@ static unsigned request_read(struct selector_key * key) {
|
||||||
selector_set_interest_key(key, OP_WRITE);
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return error ? ERROR : ret;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,7 +697,6 @@ static unsigned request_process(struct selector_key * key, struct request_st * d
|
||||||
ATTACHMENT(key)->origin_domain = AF_INET;
|
ATTACHMENT(key)->origin_domain = AF_INET;
|
||||||
d->request.dest_addr.ipv4.sin_port = d->request.dest_port;
|
d->request.dest_addr.ipv4.sin_port = d->request.dest_port;
|
||||||
ATTACHMENT(key)->origin_addr_len = sizeof(d->request.dest_addr.ipv4);
|
ATTACHMENT(key)->origin_addr_len = sizeof(d->request.dest_addr.ipv4);
|
||||||
// TODO: CAMBIAR, DA SUBDESBORDAMIENTO DE BÚFER :]
|
|
||||||
memcpy(&ATTACHMENT(key)->origin_addr, &d->request.dest_addr, sizeof(d->request.dest_addr.ipv4));
|
memcpy(&ATTACHMENT(key)->origin_addr, &d->request.dest_addr, sizeof(d->request.dest_addr.ipv4));
|
||||||
ret = request_connect(key, d);
|
ret = request_connect(key, d);
|
||||||
break;
|
break;
|
||||||
|
@ -677,20 +704,19 @@ static unsigned request_process(struct selector_key * key, struct request_st * d
|
||||||
ATTACHMENT(key)->origin_domain = AF_INET6;
|
ATTACHMENT(key)->origin_domain = AF_INET6;
|
||||||
d->request.dest_addr.ipv6.sin6_port = d->request.dest_port;
|
d->request.dest_addr.ipv6.sin6_port = d->request.dest_port;
|
||||||
ATTACHMENT(key)->origin_addr_len = sizeof(d->request.dest_addr.ipv6);
|
ATTACHMENT(key)->origin_addr_len = sizeof(d->request.dest_addr.ipv6);
|
||||||
// TODO: CAMBIAR, DA SUBDESBORDAMIENTO DE BÚFER :]
|
|
||||||
memcpy(&ATTACHMENT(key)->origin_addr, &d->request.dest_addr, sizeof(d->request.dest_addr.ipv6));
|
memcpy(&ATTACHMENT(key)->origin_addr, &d->request.dest_addr, sizeof(d->request.dest_addr.ipv6));
|
||||||
ret = request_connect(key, d);
|
ret = request_connect(key, d);
|
||||||
break;
|
break;
|
||||||
} case socks_req_addr_domain: {
|
} case socks_req_addr_domain: {
|
||||||
struct selector_key * k = malloc(sizeof(*key));
|
struct selector_key * k = malloc(sizeof(*key));
|
||||||
if (k == NULL) {
|
if (k == NULL) {
|
||||||
ret = REQUEST_WRITE;
|
ret = REQUEST_ERROR;
|
||||||
d->status = status_general_SOCKS_server_failure;
|
d->status = status_general_SOCKS_server_failure;
|
||||||
selector_set_interest_key(key, OP_WRITE);
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
} else {
|
} else {
|
||||||
memcpy(k, key, sizeof(*k));
|
memcpy(k, key, sizeof(*k));
|
||||||
if (-1 == pthread_create(&tid, 0, request_resolv_blocking, k)) {
|
if (-1 == pthread_create(&tid, 0, request_resolv_blocking, k)) {
|
||||||
ret = REQUEST_WRITE;
|
ret = REQUEST_ERROR;
|
||||||
d->status = status_general_SOCKS_server_failure;
|
d->status = status_general_SOCKS_server_failure;
|
||||||
selector_set_interest_key(key, OP_WRITE);
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -740,13 +766,17 @@ static void * request_resolv_blocking(void * data) {
|
||||||
char buff[7];
|
char buff[7];
|
||||||
snprintf(buff, sizeof(buff), "%d", ntohs(s->client.request.request.dest_port));
|
snprintf(buff, sizeof(buff), "%d", ntohs(s->client.request.request.dest_port));
|
||||||
int ret = getaddrinfo(s->client.request.request.dest_addr.fqdn, buff, &hints, &s->origin_resolution);
|
int ret = getaddrinfo(s->client.request.request.dest_addr.fqdn, buff, &hints, &s->origin_resolution);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case EAI_FAMILY:
|
case EAI_FAMILY:
|
||||||
s->client.request.status = status_address_type_not_supported;
|
s->client.request.status = status_address_type_not_supported;
|
||||||
|
break;
|
||||||
case EAI_FAIL:
|
case EAI_FAIL:
|
||||||
s->client.request.status = status_host_unreachable;
|
s->client.request.status = status_host_unreachable;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
s->client.request.status = status_network_unreachable;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,32 +791,16 @@ static unsigned request_resolv_done(struct selector_key * key) {
|
||||||
struct socks5 * s = ATTACHMENT(key);
|
struct socks5 * s = ATTACHMENT(key);
|
||||||
unsigned int st = REQUEST_CONNECTING;
|
unsigned int st = REQUEST_CONNECTING;
|
||||||
|
|
||||||
if (d->status == status_address_type_not_supported && d->status == status_host_unreachable)
|
if (d->status == status_address_type_not_supported || d->status == status_host_unreachable || d->status == status_network_unreachable) {
|
||||||
return st;
|
return request_connect(key, d);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->origin_resolution == 0) {
|
if (s->origin_resolution == 0) {
|
||||||
d->status = status_general_SOCKS_server_failure;
|
d->status = status_general_SOCKS_server_failure;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
struct addrinfo * addr = s->origin_resolution;
|
|
||||||
|
|
||||||
while (addr != NULL) {
|
s->origin_resolution_current = s->origin_resolution;
|
||||||
s->origin_domain = addr->ai_family;
|
|
||||||
s->origin_addr_len = addr->ai_addrlen;
|
|
||||||
memcpy(&s->origin_addr, addr->ai_addr, addr->ai_addrlen);
|
|
||||||
st = request_connect(key, d);
|
st = request_connect(key, d);
|
||||||
if (d->status == status_succeeded) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
errno = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = addr->ai_next;
|
|
||||||
}
|
|
||||||
freeaddrinfo(s->origin_resolution);
|
|
||||||
s->origin_resolution = 0;
|
|
||||||
}
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,6 +808,13 @@ static unsigned request_connect(struct selector_key * key, struct request_st * d
|
||||||
bool error = false;
|
bool error = false;
|
||||||
enum socks_response_status status = d->status;
|
enum socks_response_status status = d->status;
|
||||||
int *fd = d->origin_fd;
|
int *fd = d->origin_fd;
|
||||||
|
struct socks5 * s = ATTACHMENT(key);
|
||||||
|
|
||||||
|
if (s->origin_resolution_current != NULL) {
|
||||||
|
s->origin_domain = s->origin_resolution_current->ai_family;
|
||||||
|
s->origin_addr_len = s->origin_resolution_current->ai_addrlen;
|
||||||
|
memcpy(&s->origin_addr, s->origin_resolution_current->ai_addr, s->origin_resolution_current->ai_addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
*fd = socket(ATTACHMENT(key)->origin_domain, SOCK_STREAM, 0);
|
*fd = socket(ATTACHMENT(key)->origin_domain, SOCK_STREAM, 0);
|
||||||
if (*fd == -1) {
|
if (*fd == -1) {
|
||||||
|
@ -819,10 +840,12 @@ static unsigned request_connect(struct selector_key * key, struct request_st * d
|
||||||
}
|
}
|
||||||
ATTACHMENT(key)->references += 1;
|
ATTACHMENT(key)->references += 1;
|
||||||
} else {
|
} else {
|
||||||
|
if (s->origin_resolution_current == NULL || s->origin_resolution_current->ai_next == NULL) {
|
||||||
status = errno_to_socks(errno);
|
status = errno_to_socks(errno);
|
||||||
error = true;
|
error = true;
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -833,6 +856,10 @@ finally:
|
||||||
close(*fd);
|
close(*fd);
|
||||||
*fd = -1;
|
*fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request_marshall(d->wb, d->status);
|
||||||
|
selector_set_interest_key(key, OP_WRITE);
|
||||||
|
return REQUEST_ERROR;
|
||||||
}
|
}
|
||||||
d->status = status;
|
d->status = status;
|
||||||
|
|
||||||
|
@ -854,19 +881,21 @@ static void request_connecting_init(const unsigned state, struct selector_key *k
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned request_connecting(struct selector_key * key) {
|
static unsigned request_connecting(struct selector_key * key) {
|
||||||
int error;
|
int error = 0;
|
||||||
socklen_t len = sizeof(error);
|
socklen_t len = sizeof(error);
|
||||||
struct connecting * d = &ATTACHMENT(key)->orig.conn;
|
struct connecting * d = &ATTACHMENT(key)->orig.conn;
|
||||||
|
struct request_st * req = &ATTACHMENT(key)->client.request;
|
||||||
|
struct socks5 * sx = ATTACHMENT(key);
|
||||||
|
|
||||||
if (getsockopt(key->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
|
if (getsockopt(key->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
|
||||||
*d->status = status_general_SOCKS_server_failure;
|
if (sx->origin_resolution_current != NULL && sx->origin_resolution_current->ai_next != NULL) {
|
||||||
|
sx->origin_resolution_current = sx->origin_resolution_current->ai_next;
|
||||||
|
return request_connect(key, req);
|
||||||
|
}
|
||||||
|
*d->status = errno_to_socks(error);
|
||||||
} else {
|
} else {
|
||||||
if (error == 0) {
|
|
||||||
*d->status = status_succeeded;
|
*d->status = status_succeeded;
|
||||||
*d->origin_fd = key->fd;
|
*d->origin_fd = key->fd;
|
||||||
} else {
|
|
||||||
*d->status = errno_to_socks(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == request_marshall(d->wb, *d->status)) {
|
if (-1 == request_marshall(d->wb, *d->status)) {
|
||||||
|
@ -879,23 +908,77 @@ static unsigned request_connecting(struct selector_key * key) {
|
||||||
return SELECTOR_SUCCESS == s ? REQUEST_WRITE : ERROR;
|
return SELECTOR_SUCCESS == s ? REQUEST_WRITE : ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_request(enum socks_response_status status, const struct sockaddr * client_addr, const struct sockaddr * origin_addr) {
|
void log_request_access(enum socks_response_status status, const struct sockaddr * client_addr, const struct sockaddr * origin_addr, char * username) {
|
||||||
char cbuff[SOCKADDR_TO_HUMAN_MIN * 2 + 2 + 32] = {0};
|
char cbuff[SOCKADDR_TO_HUMAN_MIN * 2 + 2 + 32] = {0};
|
||||||
unsigned n = N(cbuff);
|
unsigned n = N(cbuff);
|
||||||
time_t now = 0;
|
time_t now = 0;
|
||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
strftime(cbuff, n, "%FT%TZ\t", gmtime(&now));
|
strftime(cbuff, n, "%FT%TZ ", gmtime(&now));
|
||||||
size_t len = strlen(cbuff);
|
size_t len = strlen(cbuff);
|
||||||
sockaddr_to_human(cbuff + len, N(cbuff) - len, client_addr);
|
sockaddr_to_human(cbuff + len, N(cbuff) - len, client_addr);
|
||||||
strncat(cbuff, "\t", n - 1);
|
strncat(cbuff, " ", n - 1);
|
||||||
cbuff[n - 1] = 0;
|
cbuff[n - 1] = 0;
|
||||||
len = strlen(cbuff);
|
len = strlen(cbuff);
|
||||||
sockaddr_to_human(cbuff + len, N(cbuff) - len, origin_addr);
|
sockaddr_to_human(cbuff + len, N(cbuff) - len, origin_addr);
|
||||||
|
|
||||||
fprintf(stdout, "%s\tstatus=%d\n", cbuff, status);
|
if (username != NULL) {
|
||||||
|
fprintf(stdout, "register=A user=%s %s status=%d\n", username, cbuff, status);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "register=A anon %s status=%d\n", cbuff, status);
|
||||||
|
}
|
||||||
|
|
||||||
FILE * file = fopen("access.log", "a");
|
FILE * file = fopen("access.log", "a");
|
||||||
fprintf(file, "%s\tstatus=%d\n", cbuff, status);
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
if (username != NULL) {
|
||||||
|
fprintf(file, "register=A user=%s %s status=%d\n", username, cbuff, status);
|
||||||
|
} else {
|
||||||
|
fprintf(file, "register=A %s status=%d\n", cbuff, status);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_request_password(const struct sockaddr * origin_addr, char * username, char * diss_name, char * diss_pass) {
|
||||||
|
char cbuff[SOCKADDR_TO_HUMAN_MIN * 2 + 2 + 32] = {0};
|
||||||
|
unsigned n = N(cbuff);
|
||||||
|
time_t now = 0;
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
strftime(cbuff, n, "%FT%TZ ", gmtime(&now));
|
||||||
|
size_t len = strlen(cbuff);
|
||||||
|
sockaddr_to_human(cbuff + len, N(cbuff) - len, origin_addr);
|
||||||
|
in_port_t port = 0;
|
||||||
|
switch(origin_addr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
port = ((struct sockaddr_in *) origin_addr)->sin_port;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
port = ((struct sockaddr_in6 *) origin_addr)->sin6_port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char * protocol;
|
||||||
|
if (port == 110) {
|
||||||
|
protocol = "POP3";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
protocol = "UNK(POP3)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username != NULL) {
|
||||||
|
fprintf(stdout, "register=P user=%s %s protocol=%s diss_user=%s diss_pass=%s\n", username, cbuff, protocol, diss_name, diss_pass);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "register=P anon %s protocol=%s diss_user=%s diss_pass=%s\n", cbuff, protocol, diss_name, diss_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE * file = fopen("passwords.log", "a");
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
if (username != NULL) {
|
||||||
|
fprintf(file, "register=P user=%s %s protocol=%s diss_user=%s diss_pass=%s\n", username, cbuff, protocol, diss_name, diss_pass);
|
||||||
|
} else {
|
||||||
|
fprintf(file, "register=P anon %s protocol=%s diss_user=%s diss_pass=%s\n", cbuff, protocol, diss_name, diss_pass);
|
||||||
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,7 +1013,7 @@ static unsigned request_write(struct selector_key * key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_request(d->status, (const struct sockaddr *) &ATTACHMENT(key)->client_addr, (const struct sockaddr *) &ATTACHMENT(key)->origin_addr);
|
log_request_access(d->status, (const struct sockaddr *) &ATTACHMENT(key)->client_addr, (const struct sockaddr *) &ATTACHMENT(key)->origin_addr, ATTACHMENT(key)->username);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,20 +1031,19 @@ static void copy_init(const unsigned state, struct selector_key * key) {
|
||||||
d->duplex = OP_READ | OP_WRITE;
|
d->duplex = OP_READ | OP_WRITE;
|
||||||
d->other = &ATTACHMENT(key)->orig.copy;
|
d->other = &ATTACHMENT(key)->orig.copy;
|
||||||
|
|
||||||
// struct parser_definition * user = parser_utils_strcmpi("user");
|
if (pwd_dissector_active) {
|
||||||
// d->parser_user = parser_init(parser_no_classes(), user);
|
|
||||||
// struct parser_definition * pass = parser_utils_strcmpi("pass");
|
|
||||||
// d->parser_pass = parser_init(parser_no_classes(), pass);
|
|
||||||
// d->user = malloc(249);
|
|
||||||
// d->pass = malloc(249);
|
|
||||||
d->user_done = false;
|
d->user_done = false;
|
||||||
d->pass_done = false;
|
d->pass_done = false;
|
||||||
d->parser_user = parser_init(parser_no_classes(), user);
|
d->parser_user = parser_init(parser_no_classes(), user);
|
||||||
d->parser_pass = parser_init(parser_no_classes(), pass);
|
d->parser_pass = parser_init(parser_no_classes(), pass);
|
||||||
d->user = malloc(249);
|
d->user = malloc(USER_MAX_SIZE);
|
||||||
d->pass = malloc(249);
|
d->pass = malloc(USER_MAX_SIZE);
|
||||||
|
|
||||||
ATTACHMENT(key)->parser = true;
|
ATTACHMENT(key)->parser = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d->parser_user = NULL;
|
||||||
|
d->parser_pass = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
d = &ATTACHMENT(key)->orig.copy;
|
d = &ATTACHMENT(key)->orig.copy;
|
||||||
d->fd = &ATTACHMENT(key)->origin_fd;
|
d->fd = &ATTACHMENT(key)->origin_fd;
|
||||||
|
@ -1046,12 +1128,7 @@ static unsigned copy_r(struct selector_key * key) {
|
||||||
if (*(ptr + i) == '\n') {
|
if (*(ptr + i) == '\n') {
|
||||||
d->pass_done = true;
|
d->pass_done = true;
|
||||||
d->pass[k - 1] = 0;
|
d->pass[k - 1] = 0;
|
||||||
char buff[SOCKADDR_TO_HUMAN_MIN + 2] = {0};
|
log_request_password((const struct sockaddr *) &ATTACHMENT(key)->origin_addr, ATTACHMENT(key)->username, d->user, d->pass);
|
||||||
sockaddr_to_human(buff, N(buff), (struct sockaddr *) &ATTACHMENT(key)->origin_addr);
|
|
||||||
fprintf(stdout, "%s -> USER: %s - PASS: %s\n", buff, d->user, d->pass);
|
|
||||||
FILE * file = fopen("passwords.log", "a");
|
|
||||||
fprintf(file, "%s -> USER: %s - PASS: %s\n", buff, d->user, d->pass);
|
|
||||||
fclose(file);
|
|
||||||
d->user_done = false;
|
d->user_done = false;
|
||||||
d->pass_done = false;
|
d->pass_done = false;
|
||||||
parser_reset(d->parser_user);
|
parser_reset(d->parser_user);
|
||||||
|
@ -1147,6 +1224,9 @@ static const struct state_definition client_statbl[] = {
|
||||||
}, {
|
}, {
|
||||||
.state = HELLO_ERROR,
|
.state = HELLO_ERROR,
|
||||||
.on_write_ready = hello_write_error,
|
.on_write_ready = hello_write_error,
|
||||||
|
}, {
|
||||||
|
.state = AUTH_ERROR,
|
||||||
|
.on_write_ready = auth_write_error,
|
||||||
}, {
|
}, {
|
||||||
.state = REQUEST_ERROR,
|
.state = REQUEST_ERROR,
|
||||||
.on_write_ready = request_write_error,
|
.on_write_ready = request_write_error,
|
||||||
|
|
Loading…
Reference in New Issue