Compare commits
7 Commits
master
...
remove-tls
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc66f47d0d | ||
|
|
d085e04168 | ||
|
|
65c6de9a06 | ||
|
|
b7f61fc435 | ||
|
|
b02185794d | ||
|
|
5ee345735d | ||
|
|
88e76c096d |
@@ -6,4 +6,3 @@ docker-compose.yml
|
|||||||
Dockerfile_*
|
Dockerfile_*
|
||||||
data
|
data
|
||||||
README*
|
README*
|
||||||
references_for_redisign
|
|
||||||
|
|||||||
33
.env.example
@@ -1,33 +0,0 @@
|
|||||||
# Default mode - intercept live traffic
|
|
||||||
PACKMATE_MODE=LIVE
|
|
||||||
# Alternative modes:
|
|
||||||
# Parse pcap file:
|
|
||||||
# PACKMATE_MODE=FILE
|
|
||||||
# Just show already captured streams:
|
|
||||||
# PACKMATE_MODE=VIEW
|
|
||||||
|
|
||||||
# Local IP on network interface or in pcap file to tell incoming packets from outgoing
|
|
||||||
PACKMATE_LOCAL_IP=192.168.137.147
|
|
||||||
# Username for the web interface
|
|
||||||
PACKMATE_WEB_LOGIN=SomeUser
|
|
||||||
# Password for the web interface
|
|
||||||
PACKMATE_WEB_PASSWORD=SomeSecurePassword
|
|
||||||
|
|
||||||
# Settings for PACKMATE_MODE=LIVE
|
|
||||||
# Interface to capture on:
|
|
||||||
PACKMATE_INTERFACE=eth0
|
|
||||||
|
|
||||||
# Settings for PACKMATE_MODE=FILE
|
|
||||||
# Name of the file in pcaps directory to parse:
|
|
||||||
# PACKMATE_PCAP_FILE=dump.pcap
|
|
||||||
|
|
||||||
# Delete old streams (except for those marked favorite). Recommended to keep enabled
|
|
||||||
PACKMATE_OLD_STREAMS_CLEANUP_ENABLED=true
|
|
||||||
# How often to do the cleanup (best to keep the interval low)
|
|
||||||
PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL=5
|
|
||||||
# Stream older than this value (in minutes) will be deleted
|
|
||||||
PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
|
|
||||||
|
|
||||||
# Optional settings:
|
|
||||||
# PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
|
|
||||||
# BUILD_TAG=latest
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
name: Build and push image
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docker-build:
|
|
||||||
runs-on: [self-hosted, linux, x64, docker]
|
|
||||||
env:
|
|
||||||
IMAGE_NAME: cr.danosito.com/0xb00b5/0xb00b5-packmate
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Login to registry
|
|
||||||
run: |
|
|
||||||
echo "${{ vars.REGISTRY_PASSWORD }}" | docker login cr.danosito.com \
|
|
||||||
-u "${{ vars.REGISTRY_USER }}" --password-stdin
|
|
||||||
|
|
||||||
|
|
||||||
- name: Build image
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ gitea.sha }}
|
|
||||||
run: |
|
|
||||||
docker build \
|
|
||||||
-f docker/Dockerfile_app \
|
|
||||||
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
|
|
||||||
-t "${IMAGE_NAME}:latest" \
|
|
||||||
.
|
|
||||||
|
|
||||||
- name: Push image
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ gitea.sha }}
|
|
||||||
run: |
|
|
||||||
docker push "${IMAGE_NAME}:${IMAGE_TAG}"
|
|
||||||
docker push "${IMAGE_NAME}:latest"
|
|
||||||
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
references_for_redisign
|
src/main/resources/static/*
|
||||||
*.pcap
|
*.pcap
|
||||||
data
|
data
|
||||||
|
|
||||||
|
|||||||
24
.gitlab-ci.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
docker-build:
|
||||||
|
image: docker:latest
|
||||||
|
stage: build
|
||||||
|
variables:
|
||||||
|
GIT_SUBMODULE_STRATEGY: normal
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
before_script:
|
||||||
|
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
||||||
|
script:
|
||||||
|
- touch .env
|
||||||
|
- |
|
||||||
|
if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then # master
|
||||||
|
export BUILD_TAG=latest
|
||||||
|
echo "Running on default branch '$CI_DEFAULT_BRANCH'"
|
||||||
|
else # tag
|
||||||
|
export BUILD_TAG="$CI_COMMIT_TAG"
|
||||||
|
echo "Running on tag = $BUILD_TAG"
|
||||||
|
fi
|
||||||
|
- docker compose build
|
||||||
|
- docker compose push
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- tags
|
||||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "frontend"]
|
||||||
|
path = frontend
|
||||||
|
url = https://gitlab.com/packmate/packmate-frontend.git
|
||||||
23
README.md
@@ -1,10 +1,10 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
# 0xb00b5 team Packmate
|
# Packmate
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### [[EN](README_EN.md) | RU]
|
### [[EN](README_EN.md) | RU]
|
||||||
Утилита перехвата и анализа трафика для CTF, переосмысленная в пиксельном неоне.
|
Утилита перехвата и анализа трафика для CTF.
|
||||||
|
|
||||||
#### Фичи:
|
#### Фичи:
|
||||||
* Поддерживает перехват живого трафика и обработку pcap файлов
|
* Поддерживает перехват живого трафика и обработку pcap файлов
|
||||||
@@ -22,32 +22,27 @@
|
|||||||
* Автоматически проводит urldecode
|
* Автоматически проводит urldecode
|
||||||
* Разархивирует GZIP в HTTP на лету
|
* Разархивирует GZIP в HTTP на лету
|
||||||
* Разархивирует сжатые WebSockets
|
* Разархивирует сжатые WebSockets
|
||||||
* Расшифровывает TLS на RSA при наличии приватного ключа
|
|
||||||
* Обманка для входа `admin:admin` с режимами `fun` и `fake_packets`, чтобы любопытные так и не добрались до настоящих пакетов
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Обманка admin:admin
|
|
||||||
Для входа с кредами `admin:admin` добавлена обманка (включена по умолчанию). Управляется через переменные `PACKMATE_FAKE_ADMIN_ENABLED` и `PACKMATE_FAKE_ADMIN_MODE` (`fun` или `fake_packets`) и не дает добраться до настоящего интерфейса.
|
|
||||||
|
|
||||||
## Быстрый запуск
|
## Быстрый запуск
|
||||||
Для быстрого запуска 0xb00b5 team Packmate следует использовать [этот стартер](https://gitlab.com/packmate/starter/-/blob/master/README.md).
|
Для быстрого запуска Packmate следует использовать [этот стартер](https://gitlab.com/packmate/starter/-/blob/master/README.md).
|
||||||
|
|
||||||
## Полный запуск
|
## Полный запуск
|
||||||
Ниже следует инструкция для тех, кто хочет собрать 0xb00b5 team Packmate самостоятельно.
|
Ниже следует инструкция для тех, кто хочет собрать Packmate самостоятельно.
|
||||||
|
|
||||||
### Клонирование
|
### Клонирование
|
||||||
Поскольку этот репозиторий содержит фронтенд как git submodule, его необходимо клонировать так:
|
Поскольку этот репозиторий содержит фронтенд как git submodule, его необходимо клонировать так:
|
||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://git.danosito.com/0xb00b5/0xb00b5-packmate.git
|
git clone --recurse-submodules https://gitlab.com/packmate/Packmate.git
|
||||||
|
|
||||||
# Или, на старых версиях git
|
# Или, на старых версиях git
|
||||||
git clone --recursive https://git.danosito.com/0xb00b5/0xb00b5-packmate.git
|
git clone --recursive https://gitlab.com/packmate/Packmate.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Если репозиторий уже был склонирован без подмодулей, необходимо выполнить:
|
Если репозиторий уже был склонирован без подмодулей, необходимо выполнить:
|
||||||
```bash
|
```bash
|
||||||
git pull # Забираем свежую версию мастер-репы
|
git pull # Забираем свежую версию мастер-репы из gitlab
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -60,7 +55,7 @@ git submodule update --init --recursive
|
|||||||
sudo docker compose up --build -d
|
sudo docker compose up --build -d
|
||||||
```
|
```
|
||||||
|
|
||||||
При успешном запуске 0xb00b5 team Packmate будет видно с любого хоста на порту `65000`.
|
При успешном запуске Packmate будет видно с любого хоста на порту `65000`.
|
||||||
БД будет слушать на порту 65001, но будет разрешать подключения только с localhost.
|
БД будет слушать на порту 65001, но будет разрешать подключения только с localhost.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
@@ -68,5 +63,5 @@ sudo docker compose up --build -d
|
|||||||
|
|
||||||
<div align="right">
|
<div align="right">
|
||||||
|
|
||||||
*@danosito*
|
*desu~*
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
19
README_EN.md
@@ -1,10 +1,10 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
# 0xb00b5 team Packmate
|
# Packmate
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### [EN | [RU](README.md)]
|
### [EN | [RU](README.md)]
|
||||||
Advanced network traffic flow analyzer for A/D CTFs with a pixel-neon twist.
|
Advanced network traffic flow analyzer for A/D CTFs.
|
||||||
|
|
||||||
#### Features:
|
#### Features:
|
||||||
* Can monitor live traffic or analyze pcap files
|
* Can monitor live traffic or analyze pcap files
|
||||||
@@ -22,27 +22,22 @@ Advanced network traffic flow analyzer for A/D CTFs with a pixel-neon twist.
|
|||||||
* Can urldecode text automatically
|
* Can urldecode text automatically
|
||||||
* Can automatically decompress GZIPed HTTP
|
* Can automatically decompress GZIPed HTTP
|
||||||
* Can automatically deflate WebSockets with permessages-deflate extension
|
* Can automatically deflate WebSockets with permessages-deflate extension
|
||||||
* Can automatically decrypt TLS with RSA using given private key (like Wireshark)
|
|
||||||
* Decoy login for `admin:admin` with `fun` and `fake_packets` modes so snoopers never see the real data
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Admin:admin decoy
|
|
||||||
The admin:admin credentials now trigger a decoy (enabled by default). Configure it via `PACKMATE_FAKE_ADMIN_ENABLED` and `PACKMATE_FAKE_ADMIN_MODE` (`fun` or `fake_packets`) to keep everyone away from the real interface.
|
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
To quickly start using 0xb00b5 team Packmate, use [this starter](https://gitlab.com/packmate/starter/-/blob/master/README_EN.md).
|
To quickly start using Packmate, use [this starter](https://gitlab.com/packmate/starter/-/blob/master/README_EN.md).
|
||||||
|
|
||||||
## Full Build
|
## Full Build
|
||||||
Below are the instructions for those who want to build 0xb00b5 team Packmate on their own.
|
Below are the instructions for those who want to build Packmate on their own.
|
||||||
|
|
||||||
### Cloning
|
### Cloning
|
||||||
As this repository contains frontend part as a git submodule, it has to be cloned like this:
|
As this repository contains frontend part as a git submodule, it has to be cloned like this:
|
||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://git.danosito.com/0xb00b5/0xb00b5-packmate.git
|
git clone --recurse-submodules https://gitlab.com/packmate/Packmate.git
|
||||||
|
|
||||||
# Or if you have older git
|
# Or if you have older git
|
||||||
git clone --recursive https://git.danosito.com/0xb00b5/0xb00b5-packmate.git
|
git clone --recursive https://gitlab.com/packmate/Packmate.git
|
||||||
```
|
```
|
||||||
|
|
||||||
If the repository was already cloned without submodule, just run:
|
If the repository was already cloned without submodule, just run:
|
||||||
@@ -60,7 +55,7 @@ After filling in env file you can launch the app:
|
|||||||
sudo docker-compose up --build -d
|
sudo docker-compose up --build -d
|
||||||
```
|
```
|
||||||
|
|
||||||
If everything went fine, 0xb00b5 team Packmate will be available on port `65000` from any host.
|
If everything went fine, Packmate will be available on port `65000` from any host.
|
||||||
Database with listen on port 65001, but will only accept connections from localhost.
|
Database with listen on port 65001, but will only accept connections from localhost.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -6,28 +6,21 @@ services:
|
|||||||
LOCAL_IP: ${PACKMATE_LOCAL_IP}
|
LOCAL_IP: ${PACKMATE_LOCAL_IP}
|
||||||
MODE: ${PACKMATE_MODE:-LIVE}
|
MODE: ${PACKMATE_MODE:-LIVE}
|
||||||
PCAP_FILE: ${PACKMATE_PCAP_FILE:-}
|
PCAP_FILE: ${PACKMATE_PCAP_FILE:-}
|
||||||
WEB_LOGIN: ${PACKMATE_WEB_LOGIN:-0xb00b5}
|
WEB_LOGIN: ${PACKMATE_WEB_LOGIN:-BinaryBears}
|
||||||
WEB_PASSWORD: ${PACKMATE_WEB_PASSWORD:-87654321}
|
WEB_PASSWORD: ${PACKMATE_WEB_PASSWORD:-123456}
|
||||||
FAKE_ADMIN_AUTH_ENABLED: ${PACKMATE_FAKE_ADMIN_ENABLED:-true}
|
|
||||||
FAKE_ADMIN_MODE: ${PACKMATE_FAKE_ADMIN_MODE:-fun}
|
|
||||||
OLD_STREAMS_CLEANUP_ENABLED: ${PACKMATE_OLD_STREAMS_CLEANUP_ENABLED:-false}
|
OLD_STREAMS_CLEANUP_ENABLED: ${PACKMATE_OLD_STREAMS_CLEANUP_ENABLED:-false}
|
||||||
OLD_STREAMS_CLEANUP_INTERVAL: ${PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL:-5}
|
OLD_STREAMS_CLEANUP_INTERVAL: ${PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL:-5}
|
||||||
OLD_STREAMS_CLEANUP_THRESHOLD: ${PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD:-240}
|
OLD_STREAMS_CLEANUP_THRESHOLD: ${PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD:-240}
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
- NET_RAW
|
|
||||||
privileged: true
|
|
||||||
container_name: packmate-app
|
container_name: packmate-app
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile_app
|
dockerfile: docker/Dockerfile_app
|
||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
image: cr.danosito.com/0xb00b5/0xb00b5-packmate:${BUILD_TAG:-latest}
|
image: registry.gitlab.com/packmate/packmate:${BUILD_TAG:-latest}
|
||||||
volumes:
|
volumes:
|
||||||
- "./pcaps/:/app/pcaps/:ro"
|
- "./pcaps/:/app/pcaps/:ro"
|
||||||
- "./rsa_keys/:/app/rsa_keys/:ro"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
FROM node:19-alpine
|
FROM node:19-alpine
|
||||||
WORKDIR /tmp/build/
|
WORKDIR /tmp/build/
|
||||||
RUN apk add --no-cache python3 make g++
|
|
||||||
COPY ./frontend/ .
|
COPY ./frontend/ .
|
||||||
RUN export NODE_OPTIONS=--openssl-legacy-provider && npm install && npm run build
|
RUN export NODE_OPTIONS=--openssl-legacy-provider && npm install && npm run build
|
||||||
|
|
||||||
@@ -21,8 +20,6 @@ CMD [ "java", "-Djava.net.preferIPv4Stack=true", "-Djava.net.preferIPv4Addresses
|
|||||||
"--packmate.capture-mode=${MODE}", "--packmate.pcap-file=${PCAP_FILE}", \
|
"--packmate.capture-mode=${MODE}", "--packmate.pcap-file=${PCAP_FILE}", \
|
||||||
"--packmate.interface-name=${INTERFACE}", "--packmate.local-ip=${LOCAL_IP}", \
|
"--packmate.interface-name=${INTERFACE}", "--packmate.local-ip=${LOCAL_IP}", \
|
||||||
"--packmate.web.account-login=${WEB_LOGIN}", "--packmate.web.account-password=${WEB_PASSWORD}", \
|
"--packmate.web.account-login=${WEB_LOGIN}", "--packmate.web.account-password=${WEB_PASSWORD}", \
|
||||||
"--packmate.web.fake-admin.enabled=${FAKE_ADMIN_AUTH_ENABLED}", \
|
|
||||||
"--packmate.web.fake-admin.mode=${FAKE_ADMIN_MODE}", \
|
|
||||||
"--packmate.cleanup.enabled=${OLD_STREAMS_CLEANUP_ENABLED}", \
|
"--packmate.cleanup.enabled=${OLD_STREAMS_CLEANUP_ENABLED}", \
|
||||||
"--packmate.cleanup.interval=${OLD_STREAMS_CLEANUP_INTERVAL}", \
|
"--packmate.cleanup.interval=${OLD_STREAMS_CLEANUP_INTERVAL}", \
|
||||||
"--packmate.cleanup.threshold=${OLD_STREAMS_CLEANUP_THRESHOLD}", \
|
"--packmate.cleanup.threshold=${OLD_STREAMS_CLEANUP_THRESHOLD}", \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## Настройка
|
## Настройка
|
||||||
|
|
||||||
0xb00b5 team Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
|
Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
|
||||||
|
|
||||||
### Основные настройки
|
### Основные настройки
|
||||||
```dotenv
|
```dotenv
|
||||||
@@ -10,17 +10,13 @@ PACKMATE_LOCAL_IP=10.20.1.1
|
|||||||
PACKMATE_WEB_LOGIN=SomeUser
|
PACKMATE_WEB_LOGIN=SomeUser
|
||||||
# Пароль для web-авторизации
|
# Пароль для web-авторизации
|
||||||
PACKMATE_WEB_PASSWORD=SomeSecurePassword
|
PACKMATE_WEB_PASSWORD=SomeSecurePassword
|
||||||
# Включает обманку при вводе admin:admin
|
|
||||||
PACKMATE_FAKE_ADMIN_ENABLED=true
|
|
||||||
# fun или fake_packets - варианты обманки
|
|
||||||
PACKMATE_FAKE_ADMIN_MODE=fun
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Режим работы
|
### Режим работы
|
||||||
0xb00b5 team Packmate поддерживает три основных режима работы: `LIVE`, `FILE` и `VIEW`.
|
Packmate поддерживает три основных режима работы: `LIVE`, `FILE` и `VIEW`.
|
||||||
1. `LIVE` - это основной режим работы во время CTF. 0xb00b5 team Packmate обрабатывает живой трафик и сразу выводит результаты.
|
1. `LIVE` - это основной режим работы во время CTF. Packmate обрабатывает живой трафик и сразу выводит результаты.
|
||||||
2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен 0xb00b5 team Packmate, или тех, где невозможно запустить его на вулнбоксе.
|
2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен Packmate, или тех, где невозможно запустить его на вулнбоксе.
|
||||||
3. `VIEW` - 0xb00b5 team Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
|
3. `VIEW` - Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Настройка LIVE</summary>
|
<summary>Настройка LIVE</summary>
|
||||||
@@ -56,7 +52,7 @@ PACKMATE_PCAP_FILE=dump.pcap
|
|||||||
<details>
|
<details>
|
||||||
<summary>Настройка VIEW</summary>
|
<summary>Настройка VIEW</summary>
|
||||||
|
|
||||||
В этом режиме 0xb00b5 team Packmate просто показывает уже имеющиеся данные.
|
В этом режиме Packmate просто показывает уже имеющиеся данные.
|
||||||
|
|
||||||
```dotenv
|
```dotenv
|
||||||
# Режим работы - просмотр
|
# Режим работы - просмотр
|
||||||
@@ -66,7 +62,7 @@ PACKMATE_MODE=VIEW
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Очистка БД
|
### Очистка БД
|
||||||
На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу 0xb00b5 team Packmate и занимает много места на диске.
|
На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу Packmate и занимает много места на диске.
|
||||||
|
|
||||||
Для оптимизации работы, рекомендуется включить регулярную очистку БД от старых стримов. Это будет работать только в режиме `LIVE`.
|
Для оптимизации работы, рекомендуется включить регулярную очистку БД от старых стримов. Это будет работать только в режиме `LIVE`.
|
||||||
```dotenv
|
```dotenv
|
||||||
@@ -83,7 +79,7 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
|
|||||||
```dotenv
|
```dotenv
|
||||||
# Пароль от БД. Из-за того, что БД принимает подключения только с localhost, менять его необязательно, но можно, для дополнительной безопасности.
|
# Пароль от БД. Из-за того, что БД принимает подключения только с localhost, менять его необязательно, но можно, для дополнительной безопасности.
|
||||||
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
|
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
|
||||||
# Версия 0xb00b5 team Packmate. Можно изменить, если нужен другой тег образа из cr.danosito.com/danosito/0xb00b5-packmate.
|
# Версия Packmate. Можно изменить, если нужно использовать другой образ из docker registry.
|
||||||
BUILD_TAG=latest
|
BUILD_TAG=latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
0xb00b5 team Packmate uses properties from the `.env` file (in the same directory as `docker-compose.yml`)
|
Packmate uses properties from the `.env` file (in the same directory as `docker-compose.yml`)
|
||||||
|
|
||||||
### Primary settings
|
### Primary settings
|
||||||
```dotenv
|
```dotenv
|
||||||
@@ -10,17 +10,13 @@ PACKMATE_LOCAL_IP=10.20.1.1
|
|||||||
PACKMATE_WEB_LOGIN=SomeUser
|
PACKMATE_WEB_LOGIN=SomeUser
|
||||||
# Password for the web interface
|
# Password for the web interface
|
||||||
PACKMATE_WEB_PASSWORD=SomeSecurePassword
|
PACKMATE_WEB_PASSWORD=SomeSecurePassword
|
||||||
# Enable decoy flow for admin:admin login
|
|
||||||
PACKMATE_FAKE_ADMIN_ENABLED=true
|
|
||||||
# fun or fake_packets - pick the decoy flavor
|
|
||||||
PACKMATE_FAKE_ADMIN_MODE=fun
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Modes of operation
|
### Modes of operation
|
||||||
0xb00b5 team Packmate supports 3 modes of operation: `LIVE`, `FILE` и `VIEW`.
|
Packmate supports 3 modes of operation: `LIVE`, `FILE` и `VIEW`.
|
||||||
1. `LIVE` - the usual mode during a CTF. 0xb00b5 team Packmate processes live traffic and instantly displays the results.
|
1. `LIVE` - the usual mode during a CTF. Packmate processes live traffic and instantly displays the results.
|
||||||
2. `FILE` - processes traffic from pcap files. Useful to analyze traffic from past CTFs where 0xb00b5 team Packmate wasn't launched, or CTFs where it's impossible to use it on the vulnbox.
|
2. `FILE` - processes traffic from pcap files. Useful to analyze traffic from past CTFs where Packmate wasn't launched, or CTFs where it's impossible to use it on the vulnbox.
|
||||||
3. `VIEW` - 0xb00b5 team Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
|
3. `VIEW` - Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>LIVE setup</summary>
|
<summary>LIVE setup</summary>
|
||||||
@@ -56,7 +52,7 @@ PACKMATE_PCAP_FILE=dump.pcap
|
|||||||
<details>
|
<details>
|
||||||
<summary>VIEW setup</summary>
|
<summary>VIEW setup</summary>
|
||||||
|
|
||||||
In that mode, 0xb00b5 team Packmate simply shows already existing data.
|
In that mode, Packmate simply shows already existing data.
|
||||||
|
|
||||||
```dotenv
|
```dotenv
|
||||||
# Mode: viewing the data
|
# Mode: viewing the data
|
||||||
@@ -66,7 +62,7 @@ PACKMATE_MODE=VIEW
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Database cleanup
|
### Database cleanup
|
||||||
On large CTFsб after some time a lot of traffic will pile up. This can slow 0xb00b5 team Packmate down and take a lot of drive space.
|
On large CTFsб after some time a lot of traffic will pile up. This can slow Packmate down and take a lot of drive space.
|
||||||
|
|
||||||
To optimize the workflow, it is recommended to enable periodical database cleanup of old streams. It will only work in the `LIVE` mode.
|
To optimize the workflow, it is recommended to enable periodical database cleanup of old streams. It will only work in the `LIVE` mode.
|
||||||
```dotenv
|
```dotenv
|
||||||
@@ -83,7 +79,7 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
|
|||||||
```dotenv
|
```dotenv
|
||||||
# Database password. Considering it only listens on localhost, it's not mandatory to change it, but you can do it for additional security.
|
# Database password. Considering it only listens on localhost, it's not mandatory to change it, but you can do it for additional security.
|
||||||
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
|
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
|
||||||
# 0xb00b5 team Packmate version. Change it if you want to use a different tag from cr.danosito.com/danosito/0xb00b5-packmate.
|
# Packmate version. Change it if you want to use a different version from the docker registry.
|
||||||
BUILD_TAG=latest
|
BUILD_TAG=latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
1
frontend
Submodule
86
frontend/.gitignore
vendored
@@ -1,86 +0,0 @@
|
|||||||
.idea
|
|
||||||
cmake-build-debug/
|
|
||||||
cmake-build-release/
|
|
||||||
*.iws
|
|
||||||
out/
|
|
||||||
.idea_modules/
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
*.bak
|
|
||||||
/.tgitconfig
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
lib-cov
|
|
||||||
coverage
|
|
||||||
.nyc_output
|
|
||||||
.grunt
|
|
||||||
bower_components
|
|
||||||
.lock-wscript
|
|
||||||
build/Release
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
typings/
|
|
||||||
.npm
|
|
||||||
.eslintcache
|
|
||||||
.node_repl_history
|
|
||||||
*.tgz
|
|
||||||
.yarn-integrity
|
|
||||||
.env
|
|
||||||
.next
|
|
||||||
Thumbs.db
|
|
||||||
ehthumbs.db
|
|
||||||
ehthumbs_vista.db
|
|
||||||
*.stackdump
|
|
||||||
[Dd]esktop.ini
|
|
||||||
$RECYCLE.BIN/
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msix
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
*.lnk
|
|
||||||
[._]*.s[a-v][a-z]
|
|
||||||
[._]*.sw[a-p]
|
|
||||||
[._]s[a-v][a-z]
|
|
||||||
[._]sw[a-p]
|
|
||||||
Session.vim
|
|
||||||
.netrwhist
|
|
||||||
*~
|
|
||||||
tags
|
|
||||||
[._]*.un~
|
|
||||||
\#*\#
|
|
||||||
/.emacs.desktop
|
|
||||||
/.emacs.desktop.lock
|
|
||||||
*.elc
|
|
||||||
auto-save-list
|
|
||||||
tramp
|
|
||||||
.\#*
|
|
||||||
.org-id-locations
|
|
||||||
*_archive
|
|
||||||
*_flymake.*
|
|
||||||
/eshell/history
|
|
||||||
/eshell/lastdir
|
|
||||||
/elpa/
|
|
||||||
*.rel
|
|
||||||
/auto/
|
|
||||||
.cask/
|
|
||||||
dist/
|
|
||||||
flycheck_*.el
|
|
||||||
/server/
|
|
||||||
.projectile
|
|
||||||
.dir-locals.el
|
|
||||||
.fuse_hidden*
|
|
||||||
.directory
|
|
||||||
.Trash-*
|
|
||||||
.nfs*
|
|
||||||
$*$
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# packmate-frontend
|
|
||||||
|
|
||||||
## Project setup
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
|
||||||
```
|
|
||||||
npm run serve
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
|
||||||
```
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run your tests
|
|
||||||
```
|
|
||||||
npm run test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lints and fixes files
|
|
||||||
```
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/app',
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
'@babel/plugin-proposal-optional-chaining',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
31852
frontend/package-lock.json
generated
@@ -1,78 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "packmate-frontend",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"serve": "vue-cli-service serve",
|
|
||||||
"build": "vue-cli-service build",
|
|
||||||
"lint": "vue-cli-service lint"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^1.4.0",
|
|
||||||
"bootstrap": "^4.6.2",
|
|
||||||
"bootstrap-darkmode": "^0.9.1",
|
|
||||||
"bootstrap-vue": "^2.23.1",
|
|
||||||
"core-js": "^3.26.1",
|
|
||||||
"idb": "^5.0.8",
|
|
||||||
"sockjs-client": "^1.6.1",
|
|
||||||
"vue": "^2.6.14",
|
|
||||||
"vue-infinite-loading": "^2.4.5",
|
|
||||||
"vue-router": "^3.6.5",
|
|
||||||
"vuex": "^3.6.2",
|
|
||||||
"vuex-persistedstate": "^3.2.1",
|
|
||||||
"vuex-shared-mutations": "^1.0.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.18.9",
|
|
||||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
|
||||||
"@vue/cli-plugin-babel": "^4.5.19",
|
|
||||||
"@vue/cli-plugin-eslint": "^4.5.19",
|
|
||||||
"@vue/cli-service": "^4.3.0",
|
|
||||||
"babel-eslint": "^10.1.0",
|
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
|
||||||
"node-sass": "^8.0.0",
|
|
||||||
"sass-loader": "^10.4.1",
|
|
||||||
"vue-template-compiler": "^2.7.14"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:vue/essential",
|
|
||||||
"eslint:recommended"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"indent": [
|
|
||||||
"off"
|
|
||||||
],
|
|
||||||
"no-mixed-spaces-and-tabs": "off",
|
|
||||||
"comma-dangle": [
|
|
||||||
"warn",
|
|
||||||
{
|
|
||||||
"arrays": "always",
|
|
||||||
"objects": "always",
|
|
||||||
"imports": "always",
|
|
||||||
"exports": "always",
|
|
||||||
"functions": "never"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-console": "off"
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"parser": "babel-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postcss": {
|
|
||||||
"plugins": {
|
|
||||||
"autoprefixer": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions",
|
|
||||||
"not ie <= 8"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<browserconfig>
|
|
||||||
<msapplication>
|
|
||||||
<tile>
|
|
||||||
<square150x150logo src="/mstile-150x150.png"/>
|
|
||||||
<TileColor>#afd9f0</TileColor>
|
|
||||||
</tile>
|
|
||||||
</msapplication>
|
|
||||||
</browserconfig>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,20 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
|
||||||
<title>0xb00b5 team Packmate</title>
|
|
||||||
|
|
||||||
<meta name="author" content="@danosito">
|
|
||||||
|
|
||||||
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
|
||||||
<!--suppress HtmlUnknownTarget -->
|
|
||||||
<link href="<%= BASE_URL %>favicon.ico" rel="icon">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<strong>Please enable JavaScript to continue!!</strong>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,135 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
|
||||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="1453.000000pt" height="1453.000000pt" viewBox="0 0 1453.000000 1453.000000"
|
|
||||||
preserveAspectRatio="xMidYMid meet">
|
|
||||||
<metadata>
|
|
||||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
|
||||||
</metadata>
|
|
||||||
<g transform="translate(0.000000,1453.000000) scale(0.100000,-0.100000)"
|
|
||||||
fill="#000000" stroke="none">
|
|
||||||
<path d="M7065 14523 c-1372 -40 -2685 -458 -3825 -1216 -157 -105 -420 -294
|
|
||||||
-420 -303 0 -2 17 3 38 11 20 8 84 26 142 40 58 14 148 39 200 54 127 39 219
|
|
||||||
58 314 66 44 4 100 13 124 20 25 8 81 17 126 21 44 3 89 11 99 16 95 49 332
|
|
||||||
73 722 73 306 -1 463 -10 636 -40 167 -28 298 -56 404 -85 44 -12 103 -27 130
|
|
||||||
-34 60 -16 250 -77 320 -104 28 -11 86 -33 130 -50 175 -66 550 -246 619 -296
|
|
||||||
17 -13 67 -44 111 -70 44 -26 102 -61 129 -78 l49 -32 47 17 c88 31 191 13
|
|
||||||
245 -43 l28 -29 51 46 c69 62 286 203 366 238 36 16 70 32 75 36 10 7 190 82
|
|
||||||
290 121 108 42 410 138 433 138 8 0 28 6 45 14 74 32 376 88 657 120 368 43
|
|
||||||
516 44 1020 6 413 -30 709 -73 915 -133 100 -28 208 -97 265 -170 45 -55 45
|
|
||||||
-64 11 -142 -10 -22 -30 -69 -44 -105 -67 -171 -218 -472 -339 -680 -99 -168
|
|
||||||
-127 -225 -128 -254 0 -10 30 -52 68 -94 117 -130 132 -147 132 -154 0 -5 -30
|
|
||||||
-56 -66 -115 -37 -60 -80 -133 -97 -163 l-29 -54 13 -106 c17 -136 15 -322 -4
|
|
||||||
-430 -18 -94 -51 -233 -61 -248 -3 -5 -12 -57 -21 -115 -11 -82 -22 -122 -50
|
|
||||||
-176 -40 -81 -39 -76 -22 -93 12 -12 35 -47 179 -269 59 -90 124 -186 228
|
|
||||||
-337 24 -34 64 -86 89 -115 25 -29 69 -80 96 -112 67 -79 238 -252 298 -299
|
|
||||||
104 -84 198 -144 317 -205 126 -63 185 -100 177 -108 -5 -4 -168 10 -302 27
|
|
||||||
-174 21 -383 102 -532 206 -37 26 -81 57 -98 68 -51 36 -118 98 -163 150 -59
|
|
||||||
71 -58 69 -75 102 -14 25 -16 26 -17 8 0 -12 5 -46 11 -75 6 -30 17 -88 24
|
|
||||||
-129 7 -41 23 -127 35 -190 25 -135 46 -281 60 -435 6 -60 17 -171 25 -245 8
|
|
||||||
-74 17 -227 20 -340 3 -113 10 -234 15 -270 5 -36 12 -361 16 -723 6 -514 4
|
|
||||||
-679 -6 -755 -15 -117 -5 -231 36 -387 14 -55 30 -122 35 -150 5 -27 14 -59
|
|
||||||
19 -70 5 -11 21 -55 35 -97 57 -171 195 -440 297 -582 15 -21 30 -55 34 -75 3
|
|
||||||
-20 19 -49 34 -66 37 -39 59 -94 49 -120 -7 -18 -8 -18 -8 -2 -2 36 -77 134
|
|
||||||
-206 268 -121 125 -211 233 -277 334 -114 176 -160 253 -217 370 -76 158 -129
|
|
||||||
292 -157 400 -6 22 -10 -1 -15 -85 -11 -185 -39 -500 -49 -560 -6 -30 -14 -84
|
|
||||||
-19 -120 -20 -141 -42 -266 -51 -290 -5 -14 -12 -45 -16 -70 -3 -24 -10 -51
|
|
||||||
-14 -60 -4 -8 -15 -40 -24 -70 -8 -30 -24 -72 -35 -93 l-19 -38 59 -112 c32
|
|
||||||
-62 66 -126 74 -144 34 -73 147 -194 252 -270 29 -21 54 -43 56 -48 3 -7 -48
|
|
||||||
-9 -147 -7 -125 3 -164 7 -227 27 -75 23 -179 73 -210 101 -8 8 -20 14 -26 14
|
|
||||||
-24 0 -203 227 -203 258 0 6 -4 12 -8 12 -4 0 -14 16 -21 35 -15 44 -27 45
|
|
||||||
-34 3 -3 -18 -13 -67 -21 -108 -8 -41 -19 -97 -25 -125 -9 -47 -40 -144 -61
|
|
||||||
-190 -49 -111 -60 -139 -60 -151 0 -8 -4 -14 -10 -14 -5 0 -10 -5 -10 -11 0
|
|
||||||
-14 -72 -124 -134 -204 -79 -103 -216 -211 -346 -275 -36 -17 -73 -35 -82 -41
|
|
||||||
-10 -5 -24 -9 -31 -9 -7 0 -29 -11 -47 -25 -20 -15 -36 -21 -38 -15 -4 11 56
|
|
||||||
118 111 199 29 43 161 298 184 356 22 57 113 322 113 331 0 3 -28 -15 -62 -39
|
|
||||||
-93 -66 -223 -138 -308 -171 -41 -15 -84 -32 -95 -37 -18 -7 -178 -49 -189
|
|
||||||
-49 -7 0 -98 -158 -119 -205 -23 -53 -38 -164 -25 -188 5 -10 8 -20 6 -22 -14
|
|
||||||
-14 -74 70 -99 137 -41 111 -64 391 -39 477 5 19 7 37 5 40 -3 2 -59 -51 -126
|
|
||||||
-119 -117 -120 -180 -209 -249 -350 -12 -25 -26 -53 -31 -63 -5 -9 -12 -37
|
|
||||||
-15 -61 l-6 -43 88 -5 c107 -6 186 -41 249 -109 22 -24 80 -88 129 -142 139
|
|
||||||
-152 297 -276 471 -367 44 -23 99 -55 123 -71 24 -16 47 -29 53 -29 5 0 14
|
|
||||||
-11 20 -24 9 -18 26 -28 78 -41 36 -9 104 -28 151 -42 162 -48 179 -52 287
|
|
||||||
-56 153 -6 377 -46 513 -91 54 -17 75 -20 125 -13 108 15 388 22 510 14 66 -4
|
|
||||||
206 -11 310 -15 189 -8 190 -8 260 -42 125 -60 200 -115 256 -187 29 -38 56
|
|
||||||
-72 61 -78 10 -11 305 279 472 465 1000 1111 1631 2489 1815 3965 111 884 56
|
|
||||||
1797 -159 2654 -293 1167 -851 2216 -1656 3111 -124 138 -431 444 -564 561
|
|
||||||
-775 687 -1713 1214 -2692 1514 -605 185 -1213 288 -1858 315 -135 5 -276 9
|
|
||||||
-315 8 -38 -1 -110 -3 -160 -5z"/>
|
|
||||||
<path d="M2499 12743 c-148 -127 -480 -454 -623 -613 -1067 -1189 -1702 -2650
|
|
||||||
-1846 -4242 -43 -480 -29 -1086 35 -1568 198 -1471 822 -2821 1811 -3920 137
|
|
||||||
-152 430 -443 579 -574 106 -94 110 -96 119 -74 21 50 111 196 156 253 42 52
|
|
||||||
61 67 138 104 50 23 114 50 144 59 68 20 327 28 418 11 36 -6 94 -15 130 -20
|
|
||||||
36 -4 124 -18 195 -29 72 -12 158 -25 193 -30 54 -8 152 -34 204 -55 13 -5 21
|
|
||||||
0 29 18 6 14 21 28 33 32 18 5 569 26 764 29 46 1 72 5 72 12 0 7 15 23 33 36
|
|
||||||
54 41 222 138 239 138 8 0 22 7 29 16 7 9 40 37 74 62 58 45 485 466 555 548
|
|
||||||
19 23 67 78 105 124 39 45 80 86 93 91 31 12 84 11 116 -1 23 -8 26 -7 26 14
|
|
||||||
0 19 -27 65 -50 86 -9 8 -72 90 -98 128 -14 21 -42 70 -63 111 l-37 73 -7 -33
|
|
||||||
c-9 -46 -46 -158 -62 -189 -7 -14 -13 -29 -13 -35 0 -18 -44 -98 -93 -172 -81
|
|
||||||
-121 -197 -214 -197 -157 0 13 -67 149 -85 172 -92 115 -132 161 -139 161 -5
|
|
||||||
1 -37 27 -71 58 -35 32 -69 63 -76 68 -24 18 -86 55 -93 55 -7 0 46 -114 57
|
|
||||||
-118 4 -2 7 -8 7 -14 0 -5 17 -40 39 -76 105 -182 127 -232 101 -232 -5 0 -10
|
|
||||||
4 -10 8 0 5 -10 14 -22 19 -62 29 -319 251 -360 310 -16 24 -37 51 -47 61 -21
|
|
||||||
21 -66 79 -113 147 -28 42 -103 193 -145 295 -8 21 -11 14 -16 -48 -8 -79 -45
|
|
||||||
-261 -57 -277 -4 -5 -11 -26 -15 -45 -4 -19 -11 -39 -15 -45 -4 -5 -13 -28
|
|
||||||
-20 -50 -35 -108 -220 -355 -266 -355 -13 0 -26 -4 -29 -10 -3 -5 -34 -26 -68
|
|
||||||
-46 -70 -41 -77 -48 -77 -87 0 -16 -4 -26 -10 -22 -15 9 -12 73 3 82 40 24
|
|
||||||
110 216 126 343 6 41 15 106 21 143 10 58 9 71 -3 85 -18 20 -127 181 -127
|
|
||||||
187 0 2 -13 23 -29 47 -16 24 -42 66 -57 94 -16 28 -60 104 -99 168 -111 186
|
|
||||||
-308 565 -330 636 -4 14 -10 27 -14 30 -3 3 -14 21 -23 40 l-17 35 0 -60 c0
|
|
||||||
-107 60 -452 88 -505 5 -9 12 -31 16 -50 4 -19 11 -39 15 -45 4 -5 11 -26 15
|
|
||||||
-45 19 -90 158 -362 271 -530 48 -71 85 -132 83 -135 -6 -5 -145 86 -241 158
|
|
||||||
-128 97 -297 286 -298 335 0 6 -3 12 -8 12 -7 0 -38 56 -65 120 -9 19 -25 57
|
|
||||||
-36 83 -11 26 -23 63 -27 83 -3 19 -10 36 -14 39 -5 3 -11 24 -15 48 -4 23
|
|
||||||
-11 47 -16 53 -4 5 -13 44 -19 85 -6 40 -17 83 -23 94 -16 28 -22 822 -7 965
|
|
||||||
6 58 16 164 21 235 6 72 17 153 24 180 20 73 28 132 17 120 -5 -5 -23 -35 -39
|
|
||||||
-65 -50 -92 -58 -105 -70 -113 -7 -4 -13 -12 -13 -18 0 -13 -41 -72 -58 -82
|
|
||||||
-6 -4 -12 -14 -12 -20 0 -17 -188 -217 -204 -217 -7 0 -24 -10 -37 -21 -45
|
|
||||||
-41 -214 -145 -259 -161 -25 -9 -76 -19 -114 -22 -38 -4 -82 -14 -98 -22 -16
|
|
||||||
-8 -33 -12 -38 -9 -15 9 16 36 74 66 70 35 96 51 118 72 10 9 23 17 28 17 6 0
|
|
||||||
10 5 10 11 0 7 11 22 24 34 42 39 114 152 167 263 65 137 63 131 95 237 15 50
|
|
||||||
30 95 35 100 4 6 10 28 14 50 4 22 13 46 19 54 14 18 13 241 -2 250 -5 3 -13
|
|
||||||
38 -17 76 -3 39 -10 79 -15 90 -5 11 -14 67 -20 125 -6 58 -15 140 -20 183
|
|
||||||
-45 362 -43 1174 4 1477 8 52 18 124 22 160 3 35 10 71 15 80 4 8 12 44 18 80
|
|
||||||
12 83 66 302 80 330 5 9 12 31 16 50 4 19 13 46 21 60 7 14 31 70 54 125 22
|
|
||||||
55 45 108 50 117 19 34 9 36 -47 8 -117 -57 -191 -86 -263 -101 -25 -6 -54
|
|
||||||
-14 -65 -20 -58 -27 -335 -42 -460 -24 -80 11 -194 72 -302 163 -80 66 -71 73
|
|
||||||
47 42 56 -15 316 -8 333 9 6 6 24 11 40 11 16 0 43 6 60 14 18 8 61 27 97 42
|
|
||||||
36 16 83 39 105 51 22 13 51 28 65 35 14 7 27 15 30 18 3 3 16 11 30 18 48 24
|
|
||||||
70 39 126 83 31 24 90 71 132 104 43 33 82 64 89 70 6 5 28 21 47 35 42 29 42
|
|
||||||
45 3 113 -42 75 -57 115 -76 212 -34 173 -2 389 109 725 27 82 60 213 60 237
|
|
||||||
0 6 -20 35 -44 63 -48 56 -58 90 -44 156 11 48 32 11 -207 359 -126 183 -363
|
|
||||||
575 -408 675 -13 30 -36 80 -50 110 -60 129 -66 151 -52 198 7 23 12 42 10 42
|
|
||||||
-1 0 -54 -44 -116 -97z"/>
|
|
||||||
<path d="M6445 1929 c-5 -7 -25 -8 -56 -4 -29 4 -49 3 -49 -3 0 -5 -35 -12
|
|
||||||
-77 -16 -80 -6 -212 -31 -248 -46 -11 -4 -36 -14 -55 -21 -19 -7 -53 -24 -75
|
|
||||||
-39 -46 -30 -58 -37 -142 -86 -35 -19 -65 -40 -69 -45 -3 -5 13 -48 36 -97 62
|
|
||||||
-131 68 -143 90 -200 11 -29 20 -62 20 -73 0 -11 16 -47 35 -80 19 -33 38 -72
|
|
||||||
41 -87 4 -15 10 -31 14 -37 14 -18 32 -174 28 -240 -3 -54 -1 -65 12 -65 15 0
|
|
||||||
145 40 190 58 14 6 59 20 100 32 41 12 84 25 95 30 51 20 248 80 266 80 11 0
|
|
||||||
52 14 91 30 107 46 113 40 38 -35 -27 -28 -50 -54 -50 -58 0 -4 -46 -54 -102
|
|
||||||
-110 -104 -103 -238 -259 -238 -276 0 -5 -3 -11 -8 -13 -7 -3 -27 -30 -133
|
|
||||||
-177 -18 -24 -49 -76 -69 -115 -20 -39 -44 -84 -54 -99 -10 -15 -17 -29 -15
|
|
||||||
-32 13 -13 474 -67 765 -89 l70 -6 11 68 c15 90 43 205 54 216 5 6 9 17 9 26
|
|
||||||
0 23 103 221 159 305 25 38 61 99 79 135 18 35 40 74 50 85 29 35 132 252 132
|
|
||||||
279 0 9 4 16 9 16 5 0 14 21 20 46 10 40 74 126 84 113 10 -12 27 -70 32 -109
|
|
||||||
7 -46 38 -152 60 -205 7 -16 16 -41 20 -55 3 -14 12 -38 20 -55 7 -16 18 -41
|
|
||||||
23 -55 24 -55 75 -158 105 -211 35 -62 137 -221 147 -229 3 -3 20 -34 37 -70
|
|
||||||
18 -36 48 -88 67 -117 19 -29 37 -65 41 -81 3 -17 14 -37 24 -46 17 -15 29
|
|
||||||
-15 167 4 182 25 536 89 547 100 7 7 -67 111 -85 118 -4 2 -8 8 -8 14 0 11
|
|
||||||
-88 121 -101 126 -5 2 -9 8 -9 13 0 5 -19 33 -42 62 -24 29 -54 68 -68 86 -14
|
|
||||||
18 -34 45 -46 59 -32 41 -124 171 -124 176 0 3 -19 33 -43 68 -24 35 -53 82
|
|
||||||
-65 106 l-22 42 28 0 c15 -1 54 -7 87 -15 33 -8 83 -19 110 -25 28 -6 57 -15
|
|
||||||
66 -20 9 -5 33 -12 53 -15 20 -4 53 -16 73 -26 21 -11 48 -19 60 -19 13 0 23
|
|
||||||
-4 23 -9 0 -5 13 -11 29 -14 16 -4 56 -19 89 -35 l60 -28 6 60 c3 32 6 85 6
|
|
||||||
117 0 33 4 59 9 59 4 0 11 25 14 56 3 31 11 62 16 67 6 6 11 19 11 29 0 10 4
|
|
||||||
18 8 18 4 0 15 28 25 63 10 34 49 124 87 199 72 141 83 184 53 195 -10 4 -37
|
|
||||||
19 -60 35 -23 15 -45 28 -49 28 -8 0 -22 6 -169 75 -44 21 -100 40 -125 43
|
|
||||||
-25 2 -50 8 -55 13 -6 4 -51 13 -100 19 -50 7 -100 17 -113 23 -26 12 -340 -5
|
|
||||||
-407 -23 -100 -26 -153 -44 -194 -62 -38 -18 -55 -20 -146 -14 -56 3 -127 13
|
|
||||||
-157 21 -30 7 -74 12 -99 10 -99 -8 -216 -28 -246 -42 -29 -13 -37 -13 -75 0
|
|
||||||
-64 22 -148 45 -193 53 -22 3 -51 13 -64 21 -14 9 -59 18 -108 21 -46 3 -86 9
|
|
||||||
-89 13 -8 13 -192 11 -199 -2z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 9.3 KiB |
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Packmate",
|
|
||||||
"short_name": "Packmate",
|
|
||||||
"start_url": ".",
|
|
||||||
"description": "Packet monitoring tool for CTFs.",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "/android-chrome-192x192.png",
|
|
||||||
"sizes": "192x192",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/android-chrome-512x512.png",
|
|
||||||
"sizes": "512x512",
|
|
||||||
"type": "image/png"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"theme_color": "#afd9f0",
|
|
||||||
"background_color": "#ffffff",
|
|
||||||
"display": "standalone"
|
|
||||||
}
|
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app">
|
|
||||||
<div class="bg-lines"></div>
|
|
||||||
<Navbar/>
|
|
||||||
<div class="container-fluid app-frame">
|
|
||||||
<div class="row">
|
|
||||||
<transition name="fade" mode="out-in">
|
|
||||||
<router-view name="sidebar" ref="sidebar"/>
|
|
||||||
</transition>
|
|
||||||
<main role="main" class="col-sm-9 ml-sm-auto px-4 app-main">
|
|
||||||
<transition name="fade" mode="out-in">
|
|
||||||
<router-view name="content"/>
|
|
||||||
</transition>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Settings/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--suppress JSUnresolvedVariable -->
|
|
||||||
<script>
|
|
||||||
export const DB_OBJSTORE_COUNTERS_HISTORY = 'countersHistory';
|
|
||||||
|
|
||||||
import Navbar from './components/Navbar';
|
|
||||||
import Settings from './views/Settings';
|
|
||||||
import SockJS from 'sockjs-client';
|
|
||||||
import {openDB,} from 'idb';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
websocket: null,
|
|
||||||
db: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.connectWs();
|
|
||||||
openDB('packmate', 1, {
|
|
||||||
upgrade(db, oldVersion, newVersion) {
|
|
||||||
console.info('[IDB] Creating new database! Old rev %d, new rev %d',
|
|
||||||
oldVersion, newVersion);
|
|
||||||
db.createObjectStore(DB_OBJSTORE_COUNTERS_HISTORY, {
|
|
||||||
autoIncrement: false,
|
|
||||||
keyPath: null,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(db => {
|
|
||||||
this.db = db;
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
console.error('[IDB] Failed to open DB!', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.websocket?.close();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
connectWs() {
|
|
||||||
if (this.websocket !== null) return;
|
|
||||||
this.websocket = new SockJS(this.$http.defaults.baseURL + '/ws');
|
|
||||||
this.websocket.onopen = () => {
|
|
||||||
console.info('[WS] Connected');
|
|
||||||
};
|
|
||||||
this.websocket.onclose = (ev) => {
|
|
||||||
console.info('[WS] Disconnected', ev.code, ev.reason);
|
|
||||||
this.websocket = null;
|
|
||||||
if (ev.code === 1008) {
|
|
||||||
console.info('[WS] Security timeout, reconnecting...');
|
|
||||||
this.connectWs();
|
|
||||||
}
|
|
||||||
if (ev.code !== 1000) { // Normal closure
|
|
||||||
setTimeout(this.connectWs, 3000);
|
|
||||||
console.info('[WS] Reconnecting...');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.websocket.onmessage = (ev) => {
|
|
||||||
const parsed = JSON.parse(ev.data);
|
|
||||||
|
|
||||||
switch (parsed.type) {
|
|
||||||
case 'NEW_STREAM': {
|
|
||||||
this.$refs.sidebar.addStreamFromWs(parsed.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SAVE_SERVICE': {
|
|
||||||
this.addServiceFromWs(parsed.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'DELETE_SERVICE': {
|
|
||||||
this.deleteServiceFromWs(parsed.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SAVE_PATTERN': {
|
|
||||||
this.addPatternFromWs(parsed.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'COUNTERS_UPDATE': {
|
|
||||||
const data = parsed.value;
|
|
||||||
this.$store.commit('setCurrentPacketsCount', data.totalPackets);
|
|
||||||
this.$store.commit('setCurrentStreamsCount', data.totalStreams);
|
|
||||||
this.$store.commit('setCurrentServicesPacketsCount', data.servicesPackets);
|
|
||||||
this.$store.commit('setCurrentServicesStreamsCount', data.servicesStreams);
|
|
||||||
|
|
||||||
console.debug('Adding new counters to DB', parsed.value);
|
|
||||||
const tx = this.db.transaction(DB_OBJSTORE_COUNTERS_HISTORY, 'readwrite');
|
|
||||||
tx.store.add({
|
|
||||||
newPacketsCount: data.totalPackets,
|
|
||||||
newStreamsCount: data.totalStreams,
|
|
||||||
servicesPackets: data.servicesPackets,
|
|
||||||
servicesStreams: data.servicesStreams,
|
|
||||||
}, Date.now()).then(() => {
|
|
||||||
console.debug('[IDB] Added entry');
|
|
||||||
}).catch(e => {
|
|
||||||
console.error('[IDB] Failed to add entry!', e);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ENABLE_PATTERN': {
|
|
||||||
this.togglePatternFromWs(parsed.value, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'DISABLE_PATTERN': {
|
|
||||||
this.togglePatternFromWs(parsed.value, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'PCAP_STARTED': {
|
|
||||||
this.$store.commit('startPcap');
|
|
||||||
this.$bvToast.toast(`Pcap file processing started`, {
|
|
||||||
title: 'Notification',
|
|
||||||
variant: 'info',
|
|
||||||
autoHideDelay: 5000,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'PCAP_STOPPED': {
|
|
||||||
this.$bvToast.toast(`All streams processed`, {
|
|
||||||
title: 'Notification',
|
|
||||||
variant: 'success',
|
|
||||||
autoHideDelay: 5000,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'FINISH_LOOKBACK': {
|
|
||||||
console.debug('Lookback completed');
|
|
||||||
this.$bvToast.toast(`Lookback completed`, {
|
|
||||||
title: 'Notification',
|
|
||||||
variant: 'success',
|
|
||||||
autoHideDelay: 5000,
|
|
||||||
});
|
|
||||||
this.$refs.sidebar.streams = [];
|
|
||||||
this.$refs.sidebar.$refs.infiniteLoader.stateChanger.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.error('[WS] Event is not implemented!', parsed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.websocket.onerror = (ev) => {
|
|
||||||
console.warn('[WS] Error', ev);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
addPatternFromWs(pattern) {
|
|
||||||
const foundIndex = this.$store.state.patterns.findIndex(el => el.id === pattern.id);
|
|
||||||
if (foundIndex === -1) {
|
|
||||||
this.$store.commit('addPattern', pattern);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newPatterns = this.$store.state.patterns.slice();
|
|
||||||
newPatterns.splice(foundIndex, 1, pattern);
|
|
||||||
this.$store.commit('setPatterns', newPatterns);
|
|
||||||
},
|
|
||||||
togglePatternFromWs(id, enabled) {
|
|
||||||
this.$store.state.patterns.forEach(pattern => {
|
|
||||||
if (pattern.id === id) {
|
|
||||||
pattern.enabled = enabled;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addServiceFromWs(service) {
|
|
||||||
const foundIndex = this.$store.state.services.findIndex(el => el.port === service.port);
|
|
||||||
if (foundIndex === -1) {
|
|
||||||
this.$store.commit('addService', service);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newServices = this.$store.state.services.slice();
|
|
||||||
newServices.splice(foundIndex, 1, service);
|
|
||||||
this.$store.commit('setServices', newServices);
|
|
||||||
},
|
|
||||||
deleteServiceFromWs(port) {
|
|
||||||
this.$store.commit('setServices', this.$store.state.services.filter(o => o.port !== port));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Settings,
|
|
||||||
Navbar,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* cyrillic-ext */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFWJ0bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cyrillic */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFUZ0bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* greek-ext */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFWZ0bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+1F00-1FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* greek */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFVp0bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+0370-03FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vietnamese */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFWp0bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* latin-ext */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFW50bbck.woff2) format('woff2');
|
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Open Sans';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v16/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
html * {
|
|
||||||
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
font-size: .875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*noinspection CssUnusedSymbol*/
|
|
||||||
.fade-enter-active, .fade-leave-active {
|
|
||||||
transition: opacity .3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*noinspection CssUnusedSymbol*/
|
|
||||||
.fade-enter, .fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Patterns dropdown fix */
|
|
||||||
/*noinspection CssUnusedSymbol*/
|
|
||||||
.dropdown-menu.show {
|
|
||||||
position: fixed !important;
|
|
||||||
/*transform: translate3d(15px, 38px, 0) !important;*/
|
|
||||||
transform: none !important;
|
|
||||||
left: 15px !important;
|
|
||||||
top: 38px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role="main"] {
|
|
||||||
padding-top: 55px; /* Space for fixed navbar */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,309 +0,0 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@400;600&display=swap');
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--bg: #05030a;
|
|
||||||
--bg-2: #0a0a18;
|
|
||||||
--panel: rgba(9, 7, 18, 0.9);
|
|
||||||
--panel-strong: rgba(14, 10, 24, 0.95);
|
|
||||||
--accent: #c66bff;
|
|
||||||
--accent-2: #7a1dff;
|
|
||||||
--text: #e6e0ff;
|
|
||||||
--muted: #9b90c8;
|
|
||||||
--mono-font: 'JetBrains Mono', 'Ubuntu Mono', monospace;
|
|
||||||
--pixel-font: 'Press Start 2P', 'JetBrains Mono', monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="light"] {
|
|
||||||
--bg: #f0eaff;
|
|
||||||
--bg-2: #e6ddff;
|
|
||||||
--panel: rgba(245, 240, 255, 0.9);
|
|
||||||
--panel-strong: rgba(235, 227, 255, 0.95);
|
|
||||||
--text: #1a1233;
|
|
||||||
--muted: #5d4d80;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background:
|
|
||||||
radial-gradient(circle at 18% 24%, rgba(198, 107, 255, 0.18), transparent 25%),
|
|
||||||
radial-gradient(circle at 82% 12%, rgba(122, 29, 255, 0.12), transparent 25%),
|
|
||||||
linear-gradient(135deg, #020107 0%, #0a0820 50%, #03010b 100%);
|
|
||||||
color: var(--text);
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
letter-spacing: 0.6px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-theme="light"] {
|
|
||||||
background: linear-gradient(135deg, #f0eaff 0%, #e6ddff 40%, #f6f1ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-lines {
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
background-image: linear-gradient(rgba(122, 29, 255, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(198, 107, 255, 0.12) 1px, transparent 1px);
|
|
||||||
background-size: 120px 120px;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-fluid.app-frame {
|
|
||||||
padding-top: 84px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.neon-navbar {
|
|
||||||
background: var(--panel-strong) !important;
|
|
||||||
border-bottom: 1px solid rgba(122, 29, 255, 0.45);
|
|
||||||
box-shadow: 0 10px 35px rgba(0, 0, 0, 0.55), 0 0 28px rgba(122, 29, 255, 0.35);
|
|
||||||
padding: 12px 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-brand {
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
letter-spacing: 1px;
|
|
||||||
color: var(--accent) !important;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-brand .brand-dot {
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
||||||
box-shadow: 0 0 10px rgba(122, 29, 255, 0.65);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-sub {
|
|
||||||
font-size: 10px;
|
|
||||||
color: var(--muted);
|
|
||||||
margin-left: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-metrics {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-chip {
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.28);
|
|
||||||
color: var(--text);
|
|
||||||
padding: 8px 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
column-gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 11px;
|
|
||||||
box-shadow: 0 0 14px rgba(122, 29, 255, 0.24);
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-chip .label {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-chip .value {
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav .nav-link,
|
|
||||||
.neon-tab {
|
|
||||||
color: var(--text) !important;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 8px 10px;
|
|
||||||
margin: 4px 4px;
|
|
||||||
transition: all .2s ease;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav .nav-link:hover,
|
|
||||||
.navbar-nav .nav-item.active > .nav-link,
|
|
||||||
.neon-tab:hover {
|
|
||||||
background: rgba(122, 29, 255, 0.24);
|
|
||||||
box-shadow: 0 0 16px rgba(122, 29, 255, 0.28);
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-cogs > i {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-cogs > i:hover {
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-main {
|
|
||||||
background: var(--panel);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.35);
|
|
||||||
box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.45), 0 0 38px rgba(122, 29, 255, 0.18);
|
|
||||||
border-radius: 18px;
|
|
||||||
padding: 28px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
min-height: calc(100vh - 120px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
background: var(--panel);
|
|
||||||
border-right: 1px solid rgba(122, 29, 255, 0.25);
|
|
||||||
box-shadow: inset -10px 0 24px rgba(0, 0, 0, 0.35);
|
|
||||||
min-height: calc(100vh - 84px);
|
|
||||||
padding-top: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .btn {
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
letter-spacing: 0.6px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border-color: rgba(122, 29, 255, 0.35);
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .btn-outline-primary,
|
|
||||||
.sidebar .btn-outline-info,
|
|
||||||
.sidebar .btn-outline-success,
|
|
||||||
.sidebar .btn-outline-warning {
|
|
||||||
background: rgba(255, 255, 255, 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .btn:hover {
|
|
||||||
box-shadow: 0 0 12px rgba(122, 29, 255, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-sticky {
|
|
||||||
padding: 8px 6px 14px;
|
|
||||||
max-height: calc(100vh - 180px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-item {
|
|
||||||
margin: 8px 0;
|
|
||||||
border-radius: 14px;
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.25);
|
|
||||||
background: linear-gradient(125deg, rgba(122, 29, 255, 0.12), rgba(7, 4, 15, 0.9));
|
|
||||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-item .nav-link {
|
|
||||||
color: var(--text) !important;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-item .nav-link:hover {
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight {
|
|
||||||
border-color: rgba(122, 29, 255, 0.55);
|
|
||||||
box-shadow: 0 0 12px rgba(122, 29, 255, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.legend-bar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
gap: 14px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.legend-pill {
|
|
||||||
padding: 8px 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.35);
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
box-shadow: 0 0 12px rgba(122, 29, 255, 0.2);
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-outgoing, .packet-incoming {
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 14px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.28);
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-incoming {
|
|
||||||
background: radial-gradient(circle at 18% 20%, rgba(122, 29, 255, 0.16), rgba(9, 7, 18, 0.92));
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-outgoing {
|
|
||||||
background: radial-gradient(circle at 18% 20%, rgba(255, 106, 213, 0.12), rgba(10, 17, 40, 0.9));
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-incoming div,
|
|
||||||
.packet-outgoing div {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--muted);
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-incoming button,
|
|
||||||
.packet-outgoing button {
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-incoming p,
|
|
||||||
.packet-outgoing p {
|
|
||||||
font-family: var(--mono-font);
|
|
||||||
font-size: 13px;
|
|
||||||
background: rgba(0, 0, 0, 0.22);
|
|
||||||
padding: 12px;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: var(--text);
|
|
||||||
box-shadow: inset 0 0 12px rgba(0,0,0,0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn, .form-control, .custom-select, .page-link {
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
background: var(--panel);
|
|
||||||
color: var(--text);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.35);
|
|
||||||
box-shadow: 0 0 24px rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu {
|
|
||||||
background: var(--panel);
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-item {
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-item:hover {
|
|
||||||
background: rgba(122, 29, 255, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast {
|
|
||||||
background: var(--panel-strong);
|
|
||||||
color: var(--text);
|
|
||||||
border: 1px solid rgba(255, 106, 213, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
<template>
|
|
||||||
<nav class="navbar navbar-dark navbar-expand fixed-top bg-dark flex-md-nowrap p-0 shadow neon-navbar">
|
|
||||||
<div class="d-flex align-items-center pl-3">
|
|
||||||
<span class="navbar-brand mb-0 ml-2">
|
|
||||||
<span class="brand-dot"></span>
|
|
||||||
0xb00b5 PM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-metrics">
|
|
||||||
<span class="metric-chip">
|
|
||||||
<span class="label">SPM</span>
|
|
||||||
<span class="value">{{ this.$store.state.currentStreamsCount }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="metric-chip">
|
|
||||||
<span class="label">PPS</span>
|
|
||||||
<span class="value">{{ packetsPerStream }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PatternsDropdown ref="patternsDropdown"/>
|
|
||||||
|
|
||||||
<span v-if="this.$route.query.pattern" class="navbar-text navbar-nowrap">
|
|
||||||
{{ selectedPatternText }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class="navbar-collapse collapse">
|
|
||||||
<ul class="navbar-nav px-1 mr-auto">
|
|
||||||
<li class="nav-item text-nowrap">
|
|
||||||
<router-link class="nav-link" :to="{name:'stream', params: {}, query: $route.query}" exact>All</router-link>
|
|
||||||
</li>
|
|
||||||
<template v-for="service in this.$store.state.services">
|
|
||||||
<router-link :key="service.port" tag="li" class="nav-item text-nowrap edit-button"
|
|
||||||
:to="{name:'stream', params: {servicePort: service.port}, query: $route.query}">
|
|
||||||
<a class="nav-link">
|
|
||||||
{{service.name}} #{{service.port}}
|
|
||||||
({{ getSpmForService(service.port) }}
|
|
||||||
<u title="Streams per minute">SPM</u>)
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="nav-link pl-0" style="cursor: pointer" @click.stop.prevent="editService(service)">
|
|
||||||
<i class="fas fa-pencil-alt"/>
|
|
||||||
</a>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
<li class="nav-item text-nowrap" style="padding-left: 1em;">
|
|
||||||
<div class="my-2 mr-3 navbar-cogs" style="cursor: pointer;"
|
|
||||||
@click.stop.prevent="showAddService">
|
|
||||||
<i class="fas fa-plus-circle"/>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="my-2 my-lg-0 mr-3 navbar-cogs" style="cursor: pointer;"
|
|
||||||
@click.stop.prevent="showSettings">
|
|
||||||
<i class="fas fa-cogs"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ServiceModal :creating="serviceModalIsCreating" :initial-service="serviceModalEditingService"
|
|
||||||
@service-update-needed="updateServices"/>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PatternsDropdown from './PatternsDropdown';
|
|
||||||
import ServiceModal from '../views/ServiceModal';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Navbar',
|
|
||||||
computed: {
|
|
||||||
packetsPerStream: function() {
|
|
||||||
let streams = this.$store.state.currentStreamsCount;
|
|
||||||
let packets = this.$store.state.currentPacketsCount;
|
|
||||||
|
|
||||||
if (streams === 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
let pps = packets / streams;
|
|
||||||
return Math.round((pps + Number.EPSILON) * 10) / 10;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectedPatternText: function () {
|
|
||||||
let selected = this.$route.query.pattern;
|
|
||||||
if (typeof selected === 'string') {
|
|
||||||
selected = parseInt(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
let pattern = this.$store.state.patterns.find(o => o.id === selected);
|
|
||||||
if (pattern) {
|
|
||||||
return `[Selected: ${pattern.name}]`;
|
|
||||||
} else {
|
|
||||||
return '[Invalid pattern]';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
serviceModalIsCreating: true,
|
|
||||||
serviceModalEditingService: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.updateServices();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getSpmForService(port) {
|
|
||||||
return this.$store.state.currentServicesStreamsCount[port] ?? 0;
|
|
||||||
},
|
|
||||||
editService(service) {
|
|
||||||
this.serviceModalIsCreating = false;
|
|
||||||
this.serviceModalEditingService = {};
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.serviceModalEditingService = service;
|
|
||||||
this.$bvModal.show('serviceModal');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showSettings() {
|
|
||||||
this.$bvModal.show('settingsModal');
|
|
||||||
console.debug('Showing settings...');
|
|
||||||
},
|
|
||||||
showAddService() {
|
|
||||||
this.serviceModalIsCreating = true;
|
|
||||||
this.serviceModalEditingService = {};
|
|
||||||
this.$bvModal.show('serviceModal');
|
|
||||||
console.debug('Showing addService...');
|
|
||||||
},
|
|
||||||
updateServices() {
|
|
||||||
this.$http.get('service/')
|
|
||||||
.then(r => this.$store.commit('setServices', r.data))
|
|
||||||
.catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to load services: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to load services:', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
ServiceModal,
|
|
||||||
PatternsDropdown,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.nav-link {
|
|
||||||
transition: all .3s;
|
|
||||||
color: var(--text) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-button {
|
|
||||||
display: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-cogs > i {
|
|
||||||
transition: all .3s;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-cogs > i:hover {
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nowrap {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
overflow-x: auto;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
u {
|
|
||||||
text-underline-position: under;
|
|
||||||
text-decoration-style: dotted;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav::-webkit-scrollbar {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :class="{'packet-incoming': packet.incoming, 'packet-outgoing': !packet.incoming}">
|
|
||||||
<div>#{{ packet.id }} at {{ dateToText(packet.timestamp) }}
|
|
||||||
<template v-if="offset !== null"> (+{{ offset }} ms)</template>
|
|
||||||
{{ printPacketFlags(packet) }}
|
|
||||||
<button @click.prevent="copyRaw" class="btn btn-link copy-btn">Copy HEX</button>
|
|
||||||
<button @click.prevent="copyText" class="btn btn-link copy-btn">Copy text</button>
|
|
||||||
<button @click.prevent="copyPythonBytes" class="btn btn-link copy-btn">Copy as Python bytes</button>
|
|
||||||
</div>
|
|
||||||
<p v-if="!this.$store.state.hexdumpMode"
|
|
||||||
class="pt-2 pb-2 mb-3"
|
|
||||||
v-html="stringdata"/>
|
|
||||||
<p v-else
|
|
||||||
class="pt-2 pb-2 mb-3"
|
|
||||||
v-html="hexdata"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--suppress JSUnresolvedVariable, JSDeprecatedSymbols -->
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'Packet',
|
|
||||||
props: {
|
|
||||||
packet: {
|
|
||||||
id: Number(),
|
|
||||||
matches: Array(),
|
|
||||||
timestamp: Number(),
|
|
||||||
incoming: Boolean(),
|
|
||||||
ungzipped: Boolean(),
|
|
||||||
webSocketParsed: Boolean(),
|
|
||||||
tlsDecrypted: Boolean(),
|
|
||||||
content: String(),
|
|
||||||
},
|
|
||||||
offset: Number(),
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hexdata() {
|
|
||||||
const dataString = this.atou(this.packet.content);
|
|
||||||
const dump = this.hexdump(dataString, this.$store.state.hexdumpBlockSize, this.$store.state.hexdumpLineNumberBase);
|
|
||||||
return this.escapeHtml(dump)
|
|
||||||
.split('\n')
|
|
||||||
.join('<br>'); // Replace all \n to <br>
|
|
||||||
},
|
|
||||||
stringdata() {
|
|
||||||
const dataString = this.atou(this.packet.content);
|
|
||||||
const dump = this.highlightPatterns(dataString);
|
|
||||||
return this.escapeHtml(dump)
|
|
||||||
.split('\n')
|
|
||||||
.join('<br>');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
atou(b64) {
|
|
||||||
const text = atob(b64);
|
|
||||||
const length = text.length;
|
|
||||||
const bytes = new Uint8Array(length);
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
bytes[i] = text.charCodeAt(i);
|
|
||||||
}
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
return decoder.decode(bytes);
|
|
||||||
},
|
|
||||||
printPacketFlags(packet) {
|
|
||||||
let flags = [];
|
|
||||||
|
|
||||||
if (packet.ungzipped) {
|
|
||||||
flags.push('GZIP');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.webSocketParsed) {
|
|
||||||
flags.push('WS');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.tlsDecrypted) {
|
|
||||||
flags.push('TLS');
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags.join(' ');
|
|
||||||
},
|
|
||||||
hexdump(buffer, blockSize, lineNumberBase) {
|
|
||||||
blockSize = parseInt(blockSize, 10) || 16;
|
|
||||||
lineNumberBase = parseInt(lineNumberBase, 10) || 10;
|
|
||||||
let lines = [];
|
|
||||||
const hex = '0123456789ABCDEF';
|
|
||||||
for (let b = 0; b < buffer.length; b += blockSize) {
|
|
||||||
const block = buffer.slice(b, Math.min(b + blockSize, buffer.length));
|
|
||||||
const addr = ('0000000000' + b.toString(lineNumberBase)).slice(-10);
|
|
||||||
let codes = block.split('').map(ch => {
|
|
||||||
const code = ch.charCodeAt(0);
|
|
||||||
return ' ' + hex[(0xF0 & code) >> 4] + hex[0x0F & code];
|
|
||||||
}).join('');
|
|
||||||
codes += ' ..'.repeat(blockSize - block.length);
|
|
||||||
// eslint-disable-next-line no-control-regex
|
|
||||||
let chars = block.replace(/[\x00-\x1F]/g, '.');
|
|
||||||
chars += ' '.repeat(blockSize - block.length);
|
|
||||||
lines.push(addr + ':' + codes + ' |' + chars + '|');
|
|
||||||
}
|
|
||||||
return lines.join('\n');
|
|
||||||
},
|
|
||||||
dateToText(unixTimestamp) {
|
|
||||||
return new Date(unixTimestamp).toLocaleDateString('ru-RU', {
|
|
||||||
month: '2-digit',
|
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
escapeHtml(in_) {
|
|
||||||
return in_.replace(/(<span style="background-color: #(?:[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})">|<\/span>)|[&<>"'/]/g, ($0, $1) => {
|
|
||||||
const entityMap = {
|
|
||||||
'&': '&',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>',
|
|
||||||
'"': '"',
|
|
||||||
'\'': ''',
|
|
||||||
'/': '/',
|
|
||||||
};
|
|
||||||
|
|
||||||
return $1 ? $1 : entityMap[$0];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
highlightPatterns(raw) {
|
|
||||||
const patterns = this.$store.state.patterns.reduce((obj, item) => {
|
|
||||||
obj[item.id] = item;
|
|
||||||
return obj;
|
|
||||||
}, {}); // Array to object
|
|
||||||
let offset = 0;
|
|
||||||
this.packet.matches
|
|
||||||
.filter(match => !patterns[match.patternId].deleted)
|
|
||||||
.sort((a, b) => a.startPosition - b.startPosition)
|
|
||||||
.forEach(match => {
|
|
||||||
const pattern = patterns[match.patternId];
|
|
||||||
if (!pattern) {
|
|
||||||
console.info(`Pattern #${match.patternId} does not exist`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const firstTag = `<span style="background-color: ${pattern.color}">`;
|
|
||||||
const secondTag = '</span>';
|
|
||||||
|
|
||||||
const positionStart = match.startPosition + offset;
|
|
||||||
raw = raw.substring(0, positionStart) + firstTag + raw.substring(positionStart);
|
|
||||||
offset += firstTag.length;
|
|
||||||
|
|
||||||
const positionEnd = match.endPosition + offset + 1;
|
|
||||||
raw = raw.substring(0, positionEnd) + secondTag + raw.substring(positionEnd);
|
|
||||||
offset += secondTag.length;
|
|
||||||
});
|
|
||||||
return raw;
|
|
||||||
},
|
|
||||||
|
|
||||||
copyPythonBytes() {
|
|
||||||
const data = 'b\'' + atob(this.packet.content)
|
|
||||||
.split('')
|
|
||||||
.map((aChar) => {
|
|
||||||
return '\\x' + ('0' + aChar.charCodeAt(0).toString(16)).slice(-2);
|
|
||||||
})
|
|
||||||
.join('') + '\'';
|
|
||||||
this.copyContent(data);
|
|
||||||
},
|
|
||||||
copyRaw() {
|
|
||||||
this.copyContent(Buffer.from(this.packet.content, 'base64').toString('hex'));
|
|
||||||
},
|
|
||||||
copyText() {
|
|
||||||
this.copyContent(atob(this.packet.content));
|
|
||||||
},
|
|
||||||
copyContent(data) {
|
|
||||||
const tempEl = document.createElement('textarea');
|
|
||||||
tempEl.value = data; // Chrome
|
|
||||||
tempEl.textContent = data; // Firefox
|
|
||||||
document.body.appendChild(tempEl);
|
|
||||||
tempEl.select();
|
|
||||||
const result = document.execCommand('copy');
|
|
||||||
document.body.removeChild(tempEl);
|
|
||||||
console.debug('Copy result is', result);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.copy-btn {
|
|
||||||
margin-left: 10px;
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
font-size: 10px;
|
|
||||||
letter-spacing: 0.4px;
|
|
||||||
padding-left: 6px;
|
|
||||||
padding-right: 6px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.packet-outgoing {
|
|
||||||
background: linear-gradient(135deg, rgba(255, 106, 213, 0.12), rgba(14, 18, 40, 0.85));
|
|
||||||
border: 1px solid rgba(255, 106, 213, 0.35);
|
|
||||||
box-shadow: 0 0 14px rgba(255, 106, 213, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-incoming {
|
|
||||||
background: linear-gradient(135deg, rgba(94, 242, 255, 0.16), rgba(14, 18, 40, 0.85));
|
|
||||||
border: 1px solid rgba(94, 242, 255, 0.35);
|
|
||||||
box-shadow: 0 0 14px rgba(94, 242, 255, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--muted);
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-family: var(--mono-font);
|
|
||||||
font-size: 13px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 10px 12px;
|
|
||||||
word-break: break-word;
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
border-radius: 10px;
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 0;
|
|
||||||
top: -0.1em;
|
|
||||||
position: relative;
|
|
||||||
margin-left: 5px;
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
<template>
|
|
||||||
<b-dropdown no-flip text="Patterns" variant="dark" class="patterns-dropdown">
|
|
||||||
<li role="presentation" style="padding-left: 0.5em; padding-right: 0.5em;">
|
|
||||||
<button role="menuitem" type="button" class="btn btn-sm btn-primary btn-block"
|
|
||||||
@click.stop.prevent="showAddPattern">
|
|
||||||
<i class="fas fa-plus"/>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<b-dropdown-divider/>
|
|
||||||
<b-dropdown-item-button @click.stop.prevent="resetPatternSelection">
|
|
||||||
<strong>All streams</strong>
|
|
||||||
</b-dropdown-item-button>
|
|
||||||
<b-dropdown-item-button v-for="pattern in existingPatterns"
|
|
||||||
:key="pattern.id" @click.stop.prevent="openPattern(pattern)"
|
|
||||||
:class="{ 'ignore-pattern' : pattern.actionType === 'IGNORE' }">
|
|
||||||
|
|
||||||
<strong v-if="pattern.enabled" :style="getPatternColor">{{ pattern.name }}</strong>
|
|
||||||
<s v-else :style="`color: ${pattern.color};`">{{ pattern.name }}</s>:
|
|
||||||
|
|
||||||
<code>{{ getSearchTypeValue(pattern.searchType, pattern.value) }}</code>;
|
|
||||||
|
|
||||||
<template v-if="pattern.actionType === 'FIND'">search </template>
|
|
||||||
<template v-else>ignore </template>
|
|
||||||
|
|
||||||
<template v-if="pattern.directionType === 'BOTH'">anywhere </template>
|
|
||||||
<template v-else-if="pattern.directionType === 'INPUT'">in request </template>
|
|
||||||
<template v-else>in response </template>
|
|
||||||
|
|
||||||
<template v-if="pattern.serviceId === null">of any service</template>
|
|
||||||
<template v-else>of service {{ getServiceName(pattern.serviceId) }} #{{ pattern.serviceId }}</template>
|
|
||||||
|
|
||||||
<div class="float-right" style="margin-left: 2em;">
|
|
||||||
<button type="button" class="btn btn-outline-info btn-sm mr-1"
|
|
||||||
@click.stop.prevent="showEditPattern(pattern)"
|
|
||||||
title="Edit pattern">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button v-if="pattern.actionType === 'FIND'" type="button" class="btn btn-outline-warning btn-sm mr-1"
|
|
||||||
@click.stop.prevent="showLookBack(pattern)"
|
|
||||||
title="Apply pattern to older streams">
|
|
||||||
<i class="fas fa-backward"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button v-if="pattern.enabled" type="button" class="btn btn-outline-danger btn-sm mr-1"
|
|
||||||
@click.stop.prevent="togglePattern(pattern)"
|
|
||||||
title="Stop matching streams with this pattern">
|
|
||||||
<i class="fas fa-pause"></i>
|
|
||||||
</button>
|
|
||||||
<button v-else type="button" class="btn btn-outline-success btn-sm mr-1"
|
|
||||||
@click.stop.prevent="togglePattern(pattern)"
|
|
||||||
title="Start matching streams with this pattern again">
|
|
||||||
<i class="fas fa-play"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-danger btn-sm"
|
|
||||||
@click.stop.prevent="deletePattern(pattern)"
|
|
||||||
title="Permanently delete this pattern">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</b-dropdown-item-button>
|
|
||||||
|
|
||||||
<PatternModal :creating="patternModalIsCreating" :initial-pattern="patternModalEditingPattern" />
|
|
||||||
<LookBack :pattern-id="patternIdForLookback" />
|
|
||||||
</b-dropdown>
|
|
||||||
</template>
|
|
||||||
<!--suppress JSUnresolvedReference -->
|
|
||||||
<script>
|
|
||||||
import PatternModal from '@/views/PatternModal.vue';
|
|
||||||
import LookBack from '@/views/LookBack.vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PatternsDropdown',
|
|
||||||
components: {LookBack, PatternModal, },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
patternModalIsCreating: true,
|
|
||||||
patternModalEditingPattern: {},
|
|
||||||
patternIdForLookback: 0,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.updatePatterns();
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
existingPatterns: function () {
|
|
||||||
return this.$store.state.patterns.filter(p => !p.deleted)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getSearchTypeValue(searchType, value) {
|
|
||||||
if (searchType === 'REGEX') return `/${value}/`;
|
|
||||||
else if (searchType === 'SUBSTRING') return `'${value}'`;
|
|
||||||
else return `0x${value}`;
|
|
||||||
},
|
|
||||||
getPatternColor(pattern) {
|
|
||||||
if (pattern.actionType === 'FIND') {
|
|
||||||
return `color: ${pattern.color};`;
|
|
||||||
} else {
|
|
||||||
return `color: inherit;`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getServiceName(port) {
|
|
||||||
return this.$store.state.services.find(o => o.port === port)?.name ?? '<Deleted service>'
|
|
||||||
},
|
|
||||||
showAddPattern() {
|
|
||||||
this.patternModalIsCreating = true;
|
|
||||||
this.patternModalEditingPattern = {};
|
|
||||||
this.$bvModal.show('patternModal');
|
|
||||||
console.debug('Showing patternModal (create)');
|
|
||||||
},
|
|
||||||
showEditPattern(pattern) {
|
|
||||||
this.patternModalIsCreating = false;
|
|
||||||
this.patternModalEditingPattern = {};
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.patternModalEditingPattern = pattern;
|
|
||||||
this.$bvModal.show('patternModal');
|
|
||||||
console.debug('Showing patternModal (edit)');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showLookBack(pattern) {
|
|
||||||
this.patternIdForLookback = pattern.id;
|
|
||||||
this.$bvModal.show('lookBackModal');
|
|
||||||
},
|
|
||||||
updatePatterns() {
|
|
||||||
this.$http.get('pattern/')
|
|
||||||
.then(r => this.$store.commit('setPatterns', r.data))
|
|
||||||
.catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to load patterns: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to load patterns:', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
openPattern(pattern) {
|
|
||||||
if (pattern.actionType === 'IGNORE') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('Opening pattern w/ id', pattern.id);
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: this.$route.params,
|
|
||||||
query: {pattern: pattern.id,},
|
|
||||||
}, () => {});
|
|
||||||
},
|
|
||||||
resetPatternSelection() {
|
|
||||||
console.debug('Resetting pattern selection');
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: this.$route.params,
|
|
||||||
}, () => {});
|
|
||||||
},
|
|
||||||
togglePattern(pattern) {
|
|
||||||
const enabled = !pattern.enabled;
|
|
||||||
console.debug('Toggling pattern', pattern);
|
|
||||||
this.$http.post(`pattern/${pattern.id}/enable`, null, {
|
|
||||||
params: {
|
|
||||||
enabled,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
console.debug('Done toggling pattern', data);
|
|
||||||
this.$emit('patternAddComplete');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to toggle pattern: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to toggle pattern', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deletePattern(pattern) {
|
|
||||||
console.debug('Deleting pattern', pattern);
|
|
||||||
|
|
||||||
this.$http.delete(`pattern/${pattern.id}`, null)
|
|
||||||
.then(() => {
|
|
||||||
console.debug('Done deleting pattern');
|
|
||||||
this.$emit('patternAddComplete');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to delete pattern: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to delete pattern', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
code {
|
|
||||||
font-family: "Ubuntu Mono", "Lucida Console", monospace;
|
|
||||||
font-size: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.patterns-dropdown {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 128px !important;
|
|
||||||
min-width: 128px !important;
|
|
||||||
max-width: 128px !important;
|
|
||||||
flex: 0 0 128px !important;
|
|
||||||
flex-shrink: 0 !important;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.patterns-dropdown > .btn {
|
|
||||||
display: inline-flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 9.8px;
|
|
||||||
letter-spacing: 0.05px;
|
|
||||||
min-width: 128px !important;
|
|
||||||
width: 128px !important;
|
|
||||||
max-width: 128px !important;
|
|
||||||
flex: 0 0 128px !important;
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-right: 8px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style>
|
|
||||||
.ignore-pattern button {
|
|
||||||
cursor: default !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
<template>
|
|
||||||
<nav class="col-sm-3 d-none d-sm-block sidebar">
|
|
||||||
<div class="m-2 d-flex flex-wrap align-items-center" style="gap: 6px;">
|
|
||||||
<button type="button" class="btn btn-sm"
|
|
||||||
:title="this.$store.state.pause ? 'Continue' : 'Pause new streams'"
|
|
||||||
:class="this.$store.state.pause ? 'btn-danger' : 'btn-outline-success'"
|
|
||||||
@click.stop.prevent="togglePause">
|
|
||||||
<i :class="this.$store.state.pause ? 'fas fa-play' : 'fas fa-pause'"/>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm ml-1"
|
|
||||||
:title="this.$store.state.displayFavoritesOnly ? 'Show all streams' : 'Show only favorite streams'"
|
|
||||||
:class="this.$store.state.displayFavoritesOnly ? 'btn-danger' : 'btn-outline-danger'"
|
|
||||||
@click.stop.prevent="toggleFavorites">
|
|
||||||
<i class="fas fa-star"/>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm ml-1"
|
|
||||||
:title="this.$store.state.hexdumpMode ? 'Switch to text view' : 'Switch to hexdump view'"
|
|
||||||
@click.stop.prevent="toggleHexdump">
|
|
||||||
<i :class="this.$store.state.hexdumpMode ? 'far fa-file-code' : 'fas fa-align-left'"/>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-warning ml-1" v-if="!this.$store.state.pcapStarted"
|
|
||||||
title="Start pcap file processing"
|
|
||||||
@click.stop.prevent="startPcap">
|
|
||||||
<i class="fas fa-arrow-circle-down"/>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-info" style="float: right;"
|
|
||||||
title="Scroll to top"
|
|
||||||
@click.stop.prevent="scrollUp">
|
|
||||||
<i class="fas fa-angle-double-up"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-sticky">
|
|
||||||
<ul class="nav flex-column">
|
|
||||||
<SidebarStream v-for="stream in streams"
|
|
||||||
:key="stream.id"
|
|
||||||
:stream="stream"/>
|
|
||||||
<infinite-loading @infinite="infiniteLoadingHandler" ref="infiniteLoader"/>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import SidebarStream from './SidebarStream';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Sidebar',
|
|
||||||
props: ['servicePort', 'streamId',],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
streams: [],
|
|
||||||
navigationKeysCallback: (e) => {
|
|
||||||
if (!e.ctrlKey) return;
|
|
||||||
if (e.key === 'ArrowUp') {
|
|
||||||
e.preventDefault();
|
|
||||||
const index = this.streams.findIndex(e => e.id === this.$route.params.streamId);
|
|
||||||
const newStream = this.streams[index - 1];
|
|
||||||
if (!newStream) return;
|
|
||||||
const newId = newStream.id;
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: {servicePort: this.$route.params.servicePort, streamId: newId,},
|
|
||||||
query: this.$route.query,
|
|
||||||
});
|
|
||||||
document.getElementById(`stream-${newId}`).scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'center',
|
|
||||||
inline: 'center',
|
|
||||||
});
|
|
||||||
} else if (e.key === 'ArrowDown') {
|
|
||||||
e.preventDefault();
|
|
||||||
const index = this.streams.findIndex(e => e.id === this.$route.params.streamId);
|
|
||||||
const newStream = this.streams[index + 1];
|
|
||||||
if (!newStream) return;
|
|
||||||
const newId = newStream.id;
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: {servicePort: this.$route.params.servicePort, streamId: newId,},
|
|
||||||
query: this.$route.query,
|
|
||||||
});
|
|
||||||
document.getElementById(`stream-${newId}`).scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'center',
|
|
||||||
inline: 'center',
|
|
||||||
});
|
|
||||||
} else if (e.key === 'Home') {
|
|
||||||
const newStream = this.streams[0];
|
|
||||||
if (!newStream) return;
|
|
||||||
const newId = newStream.id;
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: {servicePort: this.$route.params.servicePort, streamId: newId,},
|
|
||||||
query: this.$route.query,
|
|
||||||
});
|
|
||||||
document.getElementById(`stream-${newId}`).scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'center',
|
|
||||||
inline: 'center',
|
|
||||||
});
|
|
||||||
} else if (e.key === 'End') {
|
|
||||||
const newStream = this.streams[this.streams.length - 1];
|
|
||||||
if (!newStream) return;
|
|
||||||
const newId = newStream.id;
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: {servicePort: this.$route.params.servicePort, streamId: newId,},
|
|
||||||
query: this.$route.query,
|
|
||||||
});
|
|
||||||
document.getElementById(`stream-${newId}`).scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'center',
|
|
||||||
inline: 'center',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'$route.params.servicePort': function () {
|
|
||||||
console.debug('Port reselected');
|
|
||||||
this.streams = [];
|
|
||||||
this.$refs.infiniteLoader.stateChanger.reset();
|
|
||||||
},
|
|
||||||
'$route.query.pattern': function () {
|
|
||||||
console.debug('Pattern selected');
|
|
||||||
this.streams = [];
|
|
||||||
this.$refs.infiniteLoader.stateChanger.reset();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
infiniteLoadingHandler($state) {
|
|
||||||
const ourStreams = this.streams;
|
|
||||||
const pageSize = this.$store.state.pageSize;
|
|
||||||
|
|
||||||
let startsFrom;
|
|
||||||
if (ourStreams?.length && ourStreams[ourStreams.length - 1]) {
|
|
||||||
startsFrom = ourStreams[ourStreams.length - 1].id;
|
|
||||||
} else {
|
|
||||||
startsFrom = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$http.post(`/stream/${this.$route?.params?.servicePort || 'all'}`, {
|
|
||||||
startingFrom: startsFrom,
|
|
||||||
pageSize: pageSize,
|
|
||||||
pattern: this.$route.query.pattern ? {id: this.$route.query.pattern,} : null,
|
|
||||||
favorites: this.$store.state.displayFavoritesOnly,
|
|
||||||
}).then(r => {
|
|
||||||
const data = r.data;
|
|
||||||
if (data?.length === 0) {
|
|
||||||
console.log('Finished loading streams (empty page)');
|
|
||||||
return $state.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[0]?.id === this.streams[0]?.id) {
|
|
||||||
console.log('Finished loading streams (overlap detected)');
|
|
||||||
return $state.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.streams.push(...data);
|
|
||||||
|
|
||||||
if (data.length < pageSize) {
|
|
||||||
// this was the last page
|
|
||||||
console.log('Finished loading streams (last page was not full)');
|
|
||||||
$state.complete();
|
|
||||||
} else {
|
|
||||||
console.log('Loaded another page of streams');
|
|
||||||
$state.loaded()
|
|
||||||
}
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to load portion of streams: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to load portion of streams:', e);
|
|
||||||
return $state.error();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
toggleFavorites() {
|
|
||||||
this.$store.commit('toggleDisplayFavoritesOnly');
|
|
||||||
this.streams = [];
|
|
||||||
this.$refs.infiniteLoader.stateChanger.reset();
|
|
||||||
},
|
|
||||||
togglePause() {
|
|
||||||
this.$store.commit('togglePause');
|
|
||||||
},
|
|
||||||
toggleHexdump() {
|
|
||||||
this.$store.commit('toggleHexdumpMode');
|
|
||||||
},
|
|
||||||
startPcap() {
|
|
||||||
this.$http.post('pcap/start')
|
|
||||||
.then(() => {
|
|
||||||
this.$store.commit('startPcap');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to start pcap: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to start pcap', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addStreamFromWs(stream) {
|
|
||||||
const currentPort = parseInt(this.$route?.params?.servicePort, 10);
|
|
||||||
if (currentPort && currentPort !== stream.service) return;
|
|
||||||
if (this.$store.state.displayFavoritesOnly || this.$store.state.pause) return;
|
|
||||||
if (this.$route.query.pattern && !stream.foundPatterns.some(e => e.id === this.$route.query.pattern)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.streams.unshift(stream);
|
|
||||||
},
|
|
||||||
scrollUp() {
|
|
||||||
const newStream = this.streams[0];
|
|
||||||
if (!newStream) return;
|
|
||||||
const newId = newStream.id;
|
|
||||||
this.$router.push({
|
|
||||||
name: 'stream',
|
|
||||||
params: {servicePort: this.$route.params.servicePort, streamId: newId,},
|
|
||||||
query: this.$route.query,
|
|
||||||
});
|
|
||||||
document.getElementById(`stream-${newId}`).scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'center',
|
|
||||||
inline: 'center',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.addEventListener('keydown', this.navigationKeysCallback);
|
|
||||||
|
|
||||||
this.$http.get('pcap/started')
|
|
||||||
.then(r => this.$store.state.pcapStarted = r.data)
|
|
||||||
.catch(e => {
|
|
||||||
console.error('Failed to get pcap status, defaulting to true:', e);
|
|
||||||
this.$store.state.pcapStarted = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
document.removeEventListener('keydown', this.navigationKeysCallback);
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
SidebarStream,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 100; /* Behind the navbar */
|
|
||||||
padding: 40px 0 0; /* Height of navbar */
|
|
||||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-sticky {
|
|
||||||
position: relative;
|
|
||||||
top: 0;
|
|
||||||
height: calc(100vh - 85px);
|
|
||||||
/*padding-top: .5rem;*/
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
|
||||||
}
|
|
||||||
|
|
||||||
@supports (position: sticky) {
|
|
||||||
.sidebar-sticky {
|
|
||||||
position: sticky;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
<template>
|
|
||||||
<li :id="`stream-${stream.id}`" class="nav-item stream-item" :class="{highlight: favorite0}">
|
|
||||||
<router-link class="nav-link"
|
|
||||||
:to="{name: 'stream', params: {servicePort: this.stream.service, streamId: this.stream.id}, query: this.$route.query}">
|
|
||||||
<a @click.stop.prevent="toggleFavorite">
|
|
||||||
<i class="fa-star" style="color: #DC3545" :class="favorite0 ? 'fas' : 'far'"/>
|
|
||||||
</a>
|
|
||||||
{{ stream.id }} {{ stream.protocol }}
|
|
||||||
<template v-if="stream.ttl">TTL {{ stream.ttl }}</template>
|
|
||||||
<template v-if="shouldShowServiceName"><br/>{{ getServiceName(stream.service) }} #{{stream.service}}</template>
|
|
||||||
<br/>
|
|
||||||
{{ dateToText(stream.startTimestamp) }}
|
|
||||||
<template v-if="!dateMatches(stream.startTimestamp, stream.endTimestamp)">
|
|
||||||
- {{ dateToText(stream.endTimestamp, dayMatches(stream.startTimestamp, stream.endTimestamp)) }}
|
|
||||||
</template>
|
|
||||||
<template v-if="stream.userAgentHash"><br/>UA: {{ stream.userAgentHash }}</template>
|
|
||||||
<br/>
|
|
||||||
{{ stream.sizeBytes }} bytes in {{ stream.packetsCount }} packets
|
|
||||||
<br/>
|
|
||||||
<span v-for="pattern in notDeletedFoundPatterns"
|
|
||||||
:key="pattern.id"
|
|
||||||
:style="`color: ${pattern.color};`">
|
|
||||||
{{ pattern.name }}
|
|
||||||
</span>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'SidebarStream',
|
|
||||||
props: {
|
|
||||||
stream: {
|
|
||||||
id: Number(),
|
|
||||||
protocol: String(),
|
|
||||||
service: Number(),
|
|
||||||
startTimestamp: Number(),
|
|
||||||
endTimestamp: Number(),
|
|
||||||
foundPatternsIds: Array(),
|
|
||||||
favorite: Boolean(),
|
|
||||||
ttl: Number(),
|
|
||||||
userAgentHash: String(),
|
|
||||||
sizeBytes: Number(),
|
|
||||||
packetsCount: Number(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
shouldShowServiceName: function () {
|
|
||||||
return this.$route?.params?.servicePort === undefined;
|
|
||||||
},
|
|
||||||
foundPatterns: function () {
|
|
||||||
return this.$store.state.patterns.filter(p => this.stream.foundPatternsIds.includes(p.id));
|
|
||||||
},
|
|
||||||
notDeletedFoundPatterns: function () {
|
|
||||||
return this.foundPatterns.filter(p => !p.deleted);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
favorite0: this.stream.favorite,
|
|
||||||
getServiceName: function (port) {
|
|
||||||
return this.$store.state.services.find(o => o.port === port)?.name ?? '<Deleted service>'
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
dateToText(unixTimestamp, short = false) {
|
|
||||||
const date = new Date(unixTimestamp);
|
|
||||||
const options = {
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit',
|
|
||||||
};
|
|
||||||
if (!short && !this.isToday(date)) {
|
|
||||||
options.month = '2-digit';
|
|
||||||
options.day = '2-digit';
|
|
||||||
return date.toLocaleDateString('ru-RU', options);
|
|
||||||
}
|
|
||||||
return date.toLocaleTimeString('ru-RU', options);
|
|
||||||
},
|
|
||||||
|
|
||||||
isToday(someDate) {
|
|
||||||
const today = new Date();
|
|
||||||
return someDate.getDate() === today.getDate() &&
|
|
||||||
someDate.getMonth() === today.getMonth() &&
|
|
||||||
someDate.getFullYear() === today.getFullYear();
|
|
||||||
},
|
|
||||||
|
|
||||||
dayMatches(rFirst, rSecond) {
|
|
||||||
const first = new Date(rFirst);
|
|
||||||
const second = new Date(rSecond);
|
|
||||||
|
|
||||||
return first.getDate() === second.getDate() &&
|
|
||||||
first.getMonth() === second.getMonth() &&
|
|
||||||
first.getFullYear() === second.getFullYear();
|
|
||||||
},
|
|
||||||
|
|
||||||
dateMatches(rFirst, rSecond) {
|
|
||||||
const first = new Date(rFirst);
|
|
||||||
const second = new Date(rSecond);
|
|
||||||
return first.getDate() === second.getDate() &&
|
|
||||||
first.getMonth() === second.getMonth() &&
|
|
||||||
first.getFullYear() === second.getFullYear() &&
|
|
||||||
first.getHours() === second.getHours() &&
|
|
||||||
first.getMinutes() === second.getMinutes() &&
|
|
||||||
first.getSeconds() === second.getSeconds();
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleFavorite() {
|
|
||||||
this.$http.post(`stream/${this.stream.id}/${this.favorite0 ? 'unfavorite' : 'favorite'}`)
|
|
||||||
.then(() => this.favorite0 = !this.favorite0)
|
|
||||||
.catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to fav service: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to fav service', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.nav-link {
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text);
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.35;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*noinspection CssUnusedSymbol*/
|
|
||||||
.nav-link.active {
|
|
||||||
color: var(--accent);
|
|
||||||
text-shadow: 0 0 10px rgba(94, 242, 255, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight {
|
|
||||||
background: rgba(255, 106, 213, 0.18);
|
|
||||||
box-shadow: 0 0 12px rgba(255, 106, 213, 0.28);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-item {
|
|
||||||
transition: all .3s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
@change="toggleTheme"
|
|
||||||
id="checkbox"
|
|
||||||
type="checkbox"
|
|
||||||
class="switch-checkbox"
|
|
||||||
/>
|
|
||||||
<label for="checkbox" class="switch-label">
|
|
||||||
<span class="checkbox-emoji">🌙</span>
|
|
||||||
<span class="checkbox-emoji">☀️</span>
|
|
||||||
<div
|
|
||||||
class="switch-toggle"
|
|
||||||
:class="{ 'switch-toggle-checked': chosenTheme === 'dark' }"
|
|
||||||
></div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mounted() {
|
|
||||||
this.initTheme();
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
chosenTheme: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.theme || this.detectTheme();
|
|
||||||
},
|
|
||||||
|
|
||||||
set(theme) {
|
|
||||||
this.$store.commit('setTheme', theme);
|
|
||||||
this.displayTheme(theme);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
toggleTheme() {
|
|
||||||
const activeTheme = this.chosenTheme;
|
|
||||||
|
|
||||||
if (activeTheme === "light") {
|
|
||||||
this.chosenTheme = 'dark';
|
|
||||||
} else {
|
|
||||||
this.chosenTheme = 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('Toggling theme from ', activeTheme, ' to ', this.chosenTheme);
|
|
||||||
},
|
|
||||||
|
|
||||||
initTheme() {
|
|
||||||
this.displayTheme(this.chosenTheme);
|
|
||||||
},
|
|
||||||
|
|
||||||
detectTheme() {
|
|
||||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
||||||
},
|
|
||||||
|
|
||||||
displayTheme(theme) {
|
|
||||||
document.body.setAttribute('data-theme', theme);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.switch-checkbox {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-label {
|
|
||||||
align-items: center;
|
|
||||||
background: var(--button-text-primary-color);
|
|
||||||
border: calc(var(--button-element-size) * 0.025) solid var(--button-accent-color);
|
|
||||||
border-radius: var(--button-element-size);
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
font-size: calc(var(--button-element-size) * 0.3);
|
|
||||||
height: calc(var(--button-element-size) * 0.35);
|
|
||||||
position: relative;
|
|
||||||
padding: calc(var(--button-element-size) * 0.1);
|
|
||||||
transition: background 0.5s ease;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: var(--button-element-size);
|
|
||||||
z-index: 1;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-toggle {
|
|
||||||
position: absolute;
|
|
||||||
background-color: var(--button-background-color-primary);
|
|
||||||
border-radius: 50%;
|
|
||||||
top: calc(var(--button-element-size) * 0.07);
|
|
||||||
left: calc(var(--button-element-size) * 0.07);
|
|
||||||
height: calc(var(--button-element-size) * 0.4);
|
|
||||||
width: calc(var(--button-element-size) * 0.4);
|
|
||||||
transform: translateX(0);
|
|
||||||
transition: transform 0.3s ease, background-color 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-toggle-checked {
|
|
||||||
transform: translateX(calc(var(--button-element-size) * 0.6)) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-emoji {
|
|
||||||
color: transparent;
|
|
||||||
text-shadow: 0 0 0 var(--button-background-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
>>> {
|
|
||||||
--button-element-size: 3rem;
|
|
||||||
|
|
||||||
--button-background-color-primary: var(--panel);
|
|
||||||
--button-background-color-secondary: var(--bg-2);
|
|
||||||
--button-accent-color: var(--accent-2);
|
|
||||||
--button-text-primary-color: var(--text);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme=light] * {
|
|
||||||
--button-background-color-primary: #f0f4ff;
|
|
||||||
--button-background-color-secondary: #e4ebff;
|
|
||||||
--button-accent-color: var(--accent);
|
|
||||||
--button-text-primary-color: #0d1b2f;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
import BootstrapVue from 'bootstrap-vue';
|
|
||||||
import Axios from 'axios';
|
|
||||||
import InfiniteLoading from 'vue-infinite-loading';
|
|
||||||
import App from './App.vue';
|
|
||||||
import router from './router';
|
|
||||||
|
|
||||||
import store from './store';
|
|
||||||
import 'bootstrap/dist/css/bootstrap.css';
|
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css';
|
|
||||||
import '@fortawesome/fontawesome-free/css/all.css';
|
|
||||||
import "bootstrap-darkmode/scss/darktheme.scss";
|
|
||||||
import './assets/neon.css';
|
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
|
||||||
Vue.use(BootstrapVue);
|
|
||||||
Vue.use(InfiniteLoading, {
|
|
||||||
slots: {
|
|
||||||
noResults: 'No results...',
|
|
||||||
noMore: 'No more data',
|
|
||||||
error: 'An error has occurred!',
|
|
||||||
errorBtnText: 'Retry',
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
spinner: 'waveDots',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const axiosInstance = Axios.create({
|
|
||||||
baseURL: '/api', // TO!DO: edit for release!
|
|
||||||
// baseURL: 'http://192.168.79.131:65000/api',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
timeout: 5000,
|
|
||||||
withCredentials: true,
|
|
||||||
maxContentLength: 20000,
|
|
||||||
});
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
Vue.prototype.$http = axiosInstance;
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
new Vue({
|
|
||||||
router,
|
|
||||||
store,
|
|
||||||
render: h => h(App),
|
|
||||||
}).$mount('#app');
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// https://github.com/saikojosh/Object-Assign-Deep/blob/master/objectAssignDeep.js
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A unified way of returning a string that describes the type of the given variable.
|
|
||||||
*/
|
|
||||||
function getTypeOf(input) {
|
|
||||||
|
|
||||||
if (input === null) {
|
|
||||||
return 'null';
|
|
||||||
} else if (typeof input === 'undefined') {
|
|
||||||
return 'undefined';
|
|
||||||
} else if (typeof input === 'object') {
|
|
||||||
return (Array.isArray(input) ? 'array' : 'object');
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeof input;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Branching logic which calls the correct function to clone the given value base on its type.
|
|
||||||
*/
|
|
||||||
function cloneValue(value) {
|
|
||||||
|
|
||||||
// The value is an object so let's clone it.
|
|
||||||
if (getTypeOf(value) === 'object') {
|
|
||||||
return quickCloneObject(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The value is an array so let's clone it.
|
|
||||||
else if (getTypeOf(value) === 'array') {
|
|
||||||
return quickCloneArray(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any other value can just be copied.
|
|
||||||
return value;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerates the given array and returns a new array, with each of its values cloned (i.e. references broken).
|
|
||||||
*/
|
|
||||||
function quickCloneArray(input) {
|
|
||||||
return input.map(cloneValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerates the properties of the given object (ignoring the prototype chain) and returns a new object, with each of
|
|
||||||
* its values cloned (i.e. references broken).
|
|
||||||
*/
|
|
||||||
function quickCloneObject(input) {
|
|
||||||
|
|
||||||
const output = {};
|
|
||||||
|
|
||||||
for (const key in input) {
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(input, key)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
output[key] = cloneValue(input[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does the actual deep merging.
|
|
||||||
*/
|
|
||||||
function executeDeepMerge(target, _objects = [], _options = {}) {
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
arrayBehaviour: _options.arrayBehaviour || 'replace', // Can be "merge" or "replace".
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure we have actual objects for each.
|
|
||||||
const objects = _objects.map(object => object || {});
|
|
||||||
const output = target || {};
|
|
||||||
|
|
||||||
// Enumerate the objects and their keys.
|
|
||||||
for (let oindex = 0; oindex < objects.length; oindex++) {
|
|
||||||
const object = objects[oindex];
|
|
||||||
const keys = Object.keys(object);
|
|
||||||
|
|
||||||
for (let kindex = 0; kindex < keys.length; kindex++) {
|
|
||||||
const key = keys[kindex];
|
|
||||||
const value = object[key];
|
|
||||||
const type = getTypeOf(value);
|
|
||||||
const existingValueType = getTypeOf(output[key]);
|
|
||||||
|
|
||||||
if (type === 'object') {
|
|
||||||
if (existingValueType !== 'undefined') {
|
|
||||||
const existingValue = (existingValueType === 'object' ? output[key] : {});
|
|
||||||
output[key] = executeDeepMerge({}, [existingValue, quickCloneObject(value),], options);
|
|
||||||
} else {
|
|
||||||
output[key] = quickCloneObject(value);
|
|
||||||
}
|
|
||||||
} else if (type === 'array') {
|
|
||||||
if (existingValueType === 'array') {
|
|
||||||
const newValue = quickCloneArray(value);
|
|
||||||
output[key] = (options.arrayBehaviour === 'merge' ? output[key].concat(newValue) : newValue);
|
|
||||||
} else {
|
|
||||||
output[key] = quickCloneArray(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function objectAssignDeep(target, ...objects) {
|
|
||||||
return executeDeepMerge(target, objects);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
import Router from 'vue-router';
|
|
||||||
import ContentStream from './views/ContentStream';
|
|
||||||
import Sidebar from './components/Sidebar';
|
|
||||||
|
|
||||||
Vue.use(Router);
|
|
||||||
|
|
||||||
export default new Router({
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: '/:servicePort?/:streamId?',
|
|
||||||
name: 'stream',
|
|
||||||
props: true,
|
|
||||||
components: {
|
|
||||||
sidebar: Sidebar,
|
|
||||||
content: ContentStream,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
linkActiveClass: 'active',
|
|
||||||
});
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
import Vuex from 'vuex';
|
|
||||||
import createMutationsSharer from 'vuex-shared-mutations';
|
|
||||||
import createPersistedState from 'vuex-persistedstate';
|
|
||||||
|
|
||||||
Vue.use(Vuex);
|
|
||||||
|
|
||||||
// noinspection JSUnusedLocalSymbols,JSUnusedGlobalSymbols
|
|
||||||
export default new Vuex.Store({
|
|
||||||
state: {
|
|
||||||
theme: null,
|
|
||||||
|
|
||||||
hexdumpBlockSize: 16,
|
|
||||||
hexdumpLineNumberBase: 10,
|
|
||||||
pageSize: 25,
|
|
||||||
displayFavoritesOnly: false,
|
|
||||||
pause: false,
|
|
||||||
pcapStarted: true,
|
|
||||||
|
|
||||||
hexdumpMode: false,
|
|
||||||
|
|
||||||
serviceModalName: '',
|
|
||||||
serviceModalId: 0,
|
|
||||||
|
|
||||||
patterns: [],
|
|
||||||
services: [],
|
|
||||||
|
|
||||||
currentPacketsCount: 0,
|
|
||||||
currentStreamsCount: 0,
|
|
||||||
currentServicesPacketsCount: {},
|
|
||||||
currentServicesStreamsCount: {},
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setTheme: (s, p) => s.theme = p,
|
|
||||||
setHexdumpBlockSize: (s, p) => s.hexdumpBlockSize = p,
|
|
||||||
setHexdumpLineNumberBase: (s, p) => s.hexdumpLineNumberBase = p,
|
|
||||||
setPageSize: (s, p) => s.pageSize = p,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
toggleDisplayFavoritesOnly: (s, p) => s.displayFavoritesOnly = !s.displayFavoritesOnly,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
togglePause: (s, p) => s.pause = !s.pause,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
startPcap: (s, p) => s.pcapStarted = true,
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
toggleHexdumpMode: (s, p) => s.hexdumpMode = !s.hexdumpMode,
|
|
||||||
|
|
||||||
setServiceModalName: (s, p) => s.serviceModalName = p,
|
|
||||||
setServiceModalId: (s, p) => s.serviceModalId = p,
|
|
||||||
|
|
||||||
setPatterns: (s, p) => s.patterns = p,
|
|
||||||
addPattern: (s, p) => s.patterns.push(p),
|
|
||||||
|
|
||||||
setServices: (s, p) => s.services = p,
|
|
||||||
addService: (s, p) => s.services.push(p),
|
|
||||||
|
|
||||||
setCurrentPacketsCount: (s, p) => s.currentPacketsCount = p,
|
|
||||||
setCurrentStreamsCount: (s, p) => s.currentStreamsCount = p,
|
|
||||||
setCurrentServicesPacketsCount: (s, p) => s.currentServicesPacketsCount = p,
|
|
||||||
setCurrentServicesStreamsCount: (s, p) => s.currentServicesStreamsCount = p,
|
|
||||||
},
|
|
||||||
actions: {},
|
|
||||||
plugins: [
|
|
||||||
createPersistedState(),
|
|
||||||
createMutationsSharer({
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
predicate: (mutation, state) => {
|
|
||||||
console.debug('Got mutation:', mutation);
|
|
||||||
const mName = mutation?.type;
|
|
||||||
const process = mName !== 'toggleDisplayFavoritesOnly'
|
|
||||||
&& mName !== 'setTheme'
|
|
||||||
&& mName !== 'setServiceModalName'
|
|
||||||
&& mName !== 'setServiceModalId'
|
|
||||||
&& mName !== 'togglePause'
|
|
||||||
&& mName !== 'startPcap'
|
|
||||||
&& mName !== 'toggleHexdumpMode'
|
|
||||||
&& mName !== 'setPatterns'
|
|
||||||
&& mName !== 'addPattern'
|
|
||||||
&& mName !== 'setServices'
|
|
||||||
&& mName !== 'addService'
|
|
||||||
&& mName !== 'setCurrentPacketsCount'
|
|
||||||
&& mName !== 'setCurrentStreamsCount'
|
|
||||||
&& mName !== 'setCurrentServicesPacketsCount'
|
|
||||||
&& mName !== 'setCurrentServicesStreamsCount';
|
|
||||||
console.debug('Processing?', process);
|
|
||||||
return process;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="legend-bar">
|
|
||||||
<div class="d-flex align-items-center" style="gap: 10px;">
|
|
||||||
<span class="legend-pill request-pill">Request</span>
|
|
||||||
<span class="legend-pill response-pill">Response</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Packet v-for="packetWithOffset in packetsWithOffsets"
|
|
||||||
:key="packetWithOffset.packet.id"
|
|
||||||
:packet="packetWithOffset.packet"
|
|
||||||
:offset="packetWithOffset.offset" />
|
|
||||||
<infinite-loading @infinite="infiniteLoadingHandler" ref="infiniteLoader">
|
|
||||||
<span slot="no-results"></span>
|
|
||||||
</infinite-loading>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Packet from '../components/Packet';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ContentStream',
|
|
||||||
props: ['servicePort', 'streamId',],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
packets: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
packetsWithOffsets: function() {
|
|
||||||
return this.packets.map((el, i) => {
|
|
||||||
let offset = null;
|
|
||||||
|
|
||||||
if (i !== 0) {
|
|
||||||
offset = el.timestamp - this.packets[i - 1].timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {packet: el, offset: offset,}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'$route.params.streamId': function () {
|
|
||||||
this.packets = [];
|
|
||||||
this.$refs.infiniteLoader.stateChanger.reset();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
infiniteLoadingHandler($state) {
|
|
||||||
if (!this.$route.params.streamId) return $state.complete();
|
|
||||||
|
|
||||||
const packets = this.packets;
|
|
||||||
const pageSize = this.$store.state.pageSize;
|
|
||||||
let startsFrom;
|
|
||||||
if (packets && packets.length && packets[packets.length - 1]) {
|
|
||||||
startsFrom = packets[packets.length - 1].id;
|
|
||||||
} else {
|
|
||||||
startsFrom = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$http.post(`packet/${this.$route.params.streamId}`, {
|
|
||||||
startingFrom: startsFrom,
|
|
||||||
pageSize: pageSize,
|
|
||||||
}).then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
if (data.length === 0) {
|
|
||||||
console.log('Finished loading packets (empty page)');
|
|
||||||
return $state.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[0] && this.packets[0] && data[0].id === this.packets[0].id) {
|
|
||||||
console.log('Finished loading packets (overlap detected)');
|
|
||||||
return $state.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.packets.push(...data);
|
|
||||||
|
|
||||||
if (data.length < pageSize) {
|
|
||||||
// this was the last page
|
|
||||||
console.log('Finished loading packets (last page was not full)');
|
|
||||||
$state.complete();
|
|
||||||
} else {
|
|
||||||
console.log('Loaded another page of packets');
|
|
||||||
$state.loaded();
|
|
||||||
}
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to load portion of packets: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to load portion of packets:', e);
|
|
||||||
return $state.error();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Packet,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--response-packet-color: rgba(255, 106, 213, 0.16);
|
|
||||||
--request-packet-color: rgba(94, 242, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root [data-theme=dark] {
|
|
||||||
color-scheme: dark;
|
|
||||||
--response-packet-color: rgba(255, 106, 213, 0.16);
|
|
||||||
--request-packet-color: rgba(94, 242, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-pill {
|
|
||||||
border-color: rgba(94, 242, 255, 0.45);
|
|
||||||
color: #c9f8ff;
|
|
||||||
background: rgba(94, 242, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-pill {
|
|
||||||
border-color: rgba(255, 106, 213, 0.45);
|
|
||||||
color: #ffd6f6;
|
|
||||||
background: rgba(255, 106, 213, 0.1);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
<template>
|
|
||||||
<b-modal @ok="lookBack" id="lookBackModal"
|
|
||||||
title="Search into the past"
|
|
||||||
cancel-title="Cancel"
|
|
||||||
centered scrollable>
|
|
||||||
<form ref="lookBackForm">
|
|
||||||
<b-form-group
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Minutes"
|
|
||||||
description="How far into the past do we want to look"
|
|
||||||
label-for="lookback-minutes">
|
|
||||||
<b-form-input @keydown.native.enter="lookBack" id="lookback-minutes" required v-model="minutes"/>
|
|
||||||
</b-form-group>
|
|
||||||
</form>
|
|
||||||
</b-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'LookBack',
|
|
||||||
props: {
|
|
||||||
patternId: Number,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
minutes: 5,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
checkValidity() {
|
|
||||||
return this.$refs.lookBackForm.reportValidity();
|
|
||||||
},
|
|
||||||
|
|
||||||
lookBack(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
if (!this.checkValidity()) {
|
|
||||||
console.debug('Form is invalid');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.debug(`Looking back with pattern ${this.patternId}`);
|
|
||||||
|
|
||||||
this.$http.post(`pattern/${this.patternId}/lookback`, this.minutes)
|
|
||||||
.then(() => {
|
|
||||||
console.debug('Lookback started');
|
|
||||||
this.$bvModal.hide('lookBackModal');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to start lookback: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to start lookback', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
<template>
|
|
||||||
<b-modal @ok="addPattern" @cancel="reset" id="patternModal"
|
|
||||||
:title="creating ? 'Creating pattern' : 'Editing pattern'"
|
|
||||||
cancel-title="Cancel"
|
|
||||||
centered scrollable>
|
|
||||||
<form ref="addPatternForm">
|
|
||||||
<b-form-group
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Name"
|
|
||||||
description="It is displayed in the list and highlighted in the packet contents"
|
|
||||||
label-for="pattern-name">
|
|
||||||
<b-form-input @keydown.native.enter="addPattern" id="pattern-name" required v-model="newPattern.name"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Pattern"
|
|
||||||
description="Substring, RegEx or bytes"
|
|
||||||
label-for="pattern-value">
|
|
||||||
<b-form-input @keydown.native.enter="addPattern" @keydown="validateKey"
|
|
||||||
id="pattern-value" required v-model="newPattern.value"
|
|
||||||
:placeholder="getPlaceholder()"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Search action"
|
|
||||||
description="What to do with matching streams"
|
|
||||||
label-for="pattern-actionType">
|
|
||||||
<b-form-select id="pattern-actionType" required v-model="newPattern.actionType">
|
|
||||||
<option value="FIND" selected>Highlight found pattern</option>
|
|
||||||
<option value="IGNORE">Ignore matching streams</option>
|
|
||||||
</b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group v-if="newPattern.actionType === 'FIND'"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Color"
|
|
||||||
description="The highlight color of the pattern in the packets and streams"
|
|
||||||
label-for="pattern-color">
|
|
||||||
<b-form-input id="pattern-color" required type="color" v-model="newPattern.color"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Search method"
|
|
||||||
description="The way to search for patterns in packets"
|
|
||||||
label-for="pattern-searchType">
|
|
||||||
<b-form-select id="pattern-searchType" required v-model="newPattern.searchType">
|
|
||||||
<option value="REGEX" selected>Regular expression</option>
|
|
||||||
<option value="SUBSTRING">Substring</option>
|
|
||||||
<option value="SUBBYTES">Bytes</option>
|
|
||||||
</b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Search type"
|
|
||||||
description="In which packets to search for a pattern"
|
|
||||||
label-for="pattern-type">
|
|
||||||
<b-form-select id="pattern-type" required v-model="newPattern.directionType">
|
|
||||||
<option value="INPUT">Request</option>
|
|
||||||
<option value="OUTPUT">Response</option>
|
|
||||||
<option value="BOTH" selected>Anywhere</option>
|
|
||||||
</b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
label="Service"
|
|
||||||
description="Apply this pattern only to the specific service"
|
|
||||||
label-for="pattern-service">
|
|
||||||
<b-form-select id="pattern-service" :options="serviceOptions"
|
|
||||||
v-model="newPattern.serviceId"></b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
</form>
|
|
||||||
</b-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
const hexRegex = /[0-9A-Fa-f ]/;
|
|
||||||
const defaultPattern = {
|
|
||||||
name: '',
|
|
||||||
value: '',
|
|
||||||
color: '#FF7474',
|
|
||||||
searchType: 'SUBSTRING',
|
|
||||||
directionType: 'BOTH',
|
|
||||||
actionType: 'FIND',
|
|
||||||
serviceId: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PatternModal',
|
|
||||||
props: {
|
|
||||||
creating: Boolean,
|
|
||||||
|
|
||||||
initialPattern: {
|
|
||||||
name: String,
|
|
||||||
value: String,
|
|
||||||
color: String,
|
|
||||||
searchType: String,
|
|
||||||
directionType: String,
|
|
||||||
actionType: String,
|
|
||||||
serviceId: Number,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
newPattern: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
initialPattern() {
|
|
||||||
console.debug('initialService changed, reassigning...', this.initialPattern);
|
|
||||||
this.newPattern = {...defaultPattern, ...this.initialPattern,};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
serviceOptions: function () {
|
|
||||||
let services = this.$store.state.services;
|
|
||||||
let options = services.map(service => {
|
|
||||||
return {
|
|
||||||
value: service.port,
|
|
||||||
text: `${service.name} #${service.port}`,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return [
|
|
||||||
{ value: null, text: 'Any service', },
|
|
||||||
...options,
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getPlaceholder() {
|
|
||||||
if (this.newPattern.searchType === 'REGEX') return '[A-Z0-9]{31}=';
|
|
||||||
else if (this.newPattern.searchType === 'SUBSTRING') return 'HTTP/2';
|
|
||||||
else return 'DEAD BEEF 1337';
|
|
||||||
},
|
|
||||||
validateKey(e) {
|
|
||||||
console.log('', e);
|
|
||||||
if (this.newPattern.searchType !== 'SUBBYTES') return;
|
|
||||||
if (!hexRegex.test(e?.key)) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
checkValidity() {
|
|
||||||
return this.$refs.addPatternForm.reportValidity();
|
|
||||||
},
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.newPattern = {...defaultPattern,};
|
|
||||||
},
|
|
||||||
|
|
||||||
addPattern(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
if (!this.checkValidity()) {
|
|
||||||
console.debug('Form is invalid');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.debug('Adding/editing pattern...', this.newPattern);
|
|
||||||
|
|
||||||
if (this.newPattern.searchType === 'SUBBYTES') {
|
|
||||||
this.newPattern.value = this.newPattern.value.replace(/\s+/g, '').toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
let url;
|
|
||||||
if (this.creating) {
|
|
||||||
url = 'pattern/'
|
|
||||||
} else {
|
|
||||||
url = 'pattern/' + this.newPattern.id
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$http.post(url, this.newPattern)
|
|
||||||
.then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
console.debug('Done adding/editing pattern', data);
|
|
||||||
this.$emit('patternAddComplete');
|
|
||||||
this.reset();
|
|
||||||
this.$bvModal.hide('patternModal');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to add pattern: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to add pattern', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
<template>
|
|
||||||
<b-modal id="serviceModal" size="lg"
|
|
||||||
:title="creating ? 'Creating service' : 'Editing service'"
|
|
||||||
centered scrollable @ok.prevent="submit">
|
|
||||||
<b-form ref="serviceForm">
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Name"
|
|
||||||
label-for="service-name">
|
|
||||||
<b-form-input id="service-name" required v-model="service.name"
|
|
||||||
@keyup.enter.stop.prevent="submit"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group v-if="creating"
|
|
||||||
label-cols-sm="4"
|
|
||||||
label="Port"
|
|
||||||
label-for="service-port">
|
|
||||||
<b-form-input id="service-port" required
|
|
||||||
type="number" min="1" max="65535" v-model.number="service.port"
|
|
||||||
@keyup.enter.stop.prevent="submit"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Is an HTTP service"
|
|
||||||
label-for="service-is-http">
|
|
||||||
<b-form-checkbox id="service-is-http" required
|
|
||||||
v-model="service.http" />
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Apply urldecode"
|
|
||||||
label-for="service-urldecode">
|
|
||||||
<b-form-checkbox id="service-urldecode" required
|
|
||||||
v-model="service.urldecodeHttpRequests"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Merge adjacent packets"
|
|
||||||
label-for="service-mergeAdjacent">
|
|
||||||
<b-form-checkbox id="service-mergeAdjacent" required
|
|
||||||
v-model="service.mergeAdjacentPackets"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Inflate WebSockets"
|
|
||||||
label-for="service-inflateWS">
|
|
||||||
<b-form-checkbox id="service-inflateWS" required
|
|
||||||
v-model="service.parseWebSockets"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-form-group label-cols-sm="4"
|
|
||||||
label="Decrypt TLS (TLS_RSA_WITH_AES only)"
|
|
||||||
label-for="service-decryptTls">
|
|
||||||
<b-form-checkbox id="service-decryptTls" required
|
|
||||||
v-model="service.decryptTls"/>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-button v-if="!creating" variant="danger" @click="deleteService">Delete</b-button>
|
|
||||||
</b-form>
|
|
||||||
</b-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {objectAssignDeep,} from '@/objectAssignDeep';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ServiceModal',
|
|
||||||
props: {
|
|
||||||
creating: Boolean,
|
|
||||||
|
|
||||||
initialService: {
|
|
||||||
name: String,
|
|
||||||
port: Number,
|
|
||||||
http: Boolean,
|
|
||||||
urldecodeHttpRequests: Boolean,
|
|
||||||
mergeAdjacentPackets: Boolean,
|
|
||||||
parseWebSockets: Boolean,
|
|
||||||
decryptTls: Boolean,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
service: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
initialService() {
|
|
||||||
console.debug('initialService changed, reassigning...', this.initialService);
|
|
||||||
this.service = objectAssignDeep({}, this.initialService);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
submit() {
|
|
||||||
if (!this.$refs.serviceForm.reportValidity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.debug('Submitting service...', this.service, this.creating);
|
|
||||||
|
|
||||||
let url;
|
|
||||||
|
|
||||||
if (this.creating) {
|
|
||||||
url = 'service/';
|
|
||||||
} else {
|
|
||||||
url = 'service/' + this.initialService.port
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$http.post(url, this.service)
|
|
||||||
.then(response => {
|
|
||||||
console.info('Done editing/creating service', response.data);
|
|
||||||
this.$emit('service-update-needed');
|
|
||||||
this.$bvModal.hide('serviceModal');
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to ${this.creating ? 'create' : 'edit'} service: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to edit/create service', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteService() {
|
|
||||||
this.$http.delete(`service/${this.service.port}`)
|
|
||||||
.then(() => {
|
|
||||||
console.info('Done deleting service', this.service);
|
|
||||||
this.$emit('service-update-needed');
|
|
||||||
this.$bvModal.hide('serviceModal');
|
|
||||||
}).catch(e => {
|
|
||||||
this.$bvToast.toast(`Failed to delete service: ${e}`, {
|
|
||||||
title: 'Error',
|
|
||||||
variant: 'danger',
|
|
||||||
});
|
|
||||||
console.error('Failed to delete service', e);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.form-control {
|
|
||||||
background: rgba(122, 29, 255, 0.06);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.5);
|
|
||||||
color: var(--accent);
|
|
||||||
font-family: var(--pixel-font);
|
|
||||||
font-size: 11px;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control:focus {
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
border-color: rgba(198, 107, 255, 0.9);
|
|
||||||
color: var(--text);
|
|
||||||
box-shadow: 0 0 12px rgba(198, 107, 255, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .custom-control-input:focus ~ .custom-control-label::before {
|
|
||||||
box-shadow: 0 0 8px rgba(198, 107, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .custom-checkbox .custom-control-label::before {
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.7);
|
|
||||||
background: rgba(122, 29, 255, 0.08);
|
|
||||||
box-shadow: inset 0 0 0 1px rgba(198, 107, 255, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .custom-control-label::after {
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {
|
|
||||||
background: rgba(122, 29, 255, 0.25);
|
|
||||||
border-color: rgba(198, 107, 255, 0.9);
|
|
||||||
box-shadow: 0 0 10px rgba(198, 107, 255, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {
|
|
||||||
background: transparent;
|
|
||||||
content: "";
|
|
||||||
left: -1.3rem;
|
|
||||||
top: 0.2rem;
|
|
||||||
width: 1rem;
|
|
||||||
height: 1rem;
|
|
||||||
opacity: 1;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' shape-rendering='crispEdges'%3E%3Crect x='2' y='8' width='2' height='2' fill='%23c66bff'/%3E%3Crect x='4' y='10' width='2' height='2' fill='%23c66bff'/%3E%3Crect x='6' y='8' width='2' height='2' fill='%23c66bff'/%3E%3Crect x='8' y='6' width='2' height='2' fill='%23c66bff'/%3E%3Crect x='10' y='4' width='2' height='2' fill='%23c66bff'/%3E%3C/svg%3E");
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<template>
|
|
||||||
<b-modal id="settingsModal" title="Settings" centered scrollable ok-only>
|
|
||||||
<b-form-group
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
description="The number of bytes to display in the binary representation of the packet"
|
|
||||||
label="HEX block width"
|
|
||||||
label-for="settings-hexdumpBlockSize">
|
|
||||||
<b-form-input type="number" id="settings-hexdumpBlockSize" v-model.number="hexdumpBlockSize"/>
|
|
||||||
</b-form-group>
|
|
||||||
<b-form-group
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
description="The number system used in line numbers of a binary representation of a packet"
|
|
||||||
label="Line numbering"
|
|
||||||
label-for="settings-hexdumpLineNumberBase">
|
|
||||||
<b-form-select id="settings-hexdumpLineNumberBase" v-model="hexdumpLineNumberBase">
|
|
||||||
<option :value="10" selected>Decimal</option>
|
|
||||||
<option :value="16">Hexadecimal</option>
|
|
||||||
</b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
<b-form-group
|
|
||||||
label-cols-sm="4"
|
|
||||||
label-cols-lg="3"
|
|
||||||
description="The number of streams to download at a time"
|
|
||||||
label="Page size"
|
|
||||||
label-for="settings-pageSize">
|
|
||||||
<b-form-input type="number" id="settings-pageSize" v-model.number="pageSize"/>
|
|
||||||
</b-form-group>
|
|
||||||
</b-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'Settings',
|
|
||||||
computed: {
|
|
||||||
hexdumpBlockSize: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.hexdumpBlockSize;
|
|
||||||
},
|
|
||||||
set(v) {
|
|
||||||
this.$store.commit('setHexdumpBlockSize', v);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hexdumpLineNumberBase: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.hexdumpLineNumberBase;
|
|
||||||
},
|
|
||||||
set(v) {
|
|
||||||
this.$store.commit('setHexdumpLineNumberBase', v);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pageSize: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.pageSize;
|
|
||||||
},
|
|
||||||
set(v) {
|
|
||||||
this.$store.commit('setPageSize', v);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
lintOnSave: false,
|
|
||||||
};
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDWJO65om/5LMA0
|
|
||||||
8w9Uk36h4ukQ7Qt8nbpbeHzxorl4lGwWBASEAEmDYNUcGO0CxglOE93F9BPNGn6q
|
|
||||||
Vj8Ypp3kcTGOzsXcFrd0wRpXbSwbynnmqTCYigiLzIidasfUrGul4s1fVZFdkQZS
|
|
||||||
p2Y5pEUxq1GKcAgCVwjMyWC1dhGqvTcA5ps0JoSRoA+Nzs/BeTHlTm8UvT9eD9ER
|
|
||||||
8RmYVOi1edcJ/eztj1CVydq5X27QNmwLuqsAwq38I27nlq1NU5ShqDQ16bg8IY/c
|
|
||||||
Ll4QJB7SVbrLf3dJ7KY5i7DNEoYUiJGRwDJZt+wcZLtFSzj0cn0BuEU6M0PYglUI
|
|
||||||
uQTeosUZAgMBAAECggEAehq7CJyHzoPm4QpLDoW/qh1RmfYgG6FwVqHgVIPdz9SJ
|
|
||||||
wQ/vZzkmscPwIEJSOsejHKMVTL983vGhkgz1k1/GHjEw+eYLShCl8Ov+0iUNBpew
|
|
||||||
ZIbKj9/9OYGZ0HDHmwvpocAuLJME/V4pRc3v6yQw1D6EkzSITJVGDkcxXqcBMeIA
|
|
||||||
uNVr+pwLH9vO7ybva+e3T4ROWxlecHrcB94THops4fy5+SGVILwvKaP4cRhjLfD4
|
|
||||||
2XV4O5N0imdPAYsNNHyHbAzjvZPoCOsuH3B/tWmRHq3oOa4ZcFUNTDmO9GgfbtY/
|
|
||||||
PHEFV34XxMjy3bK0vLxHqS9CEj1cvfq8e1NqkDTugQKBgQD6CEezGf9OFb3byBui
|
|
||||||
X3OzXWdWQ5jnodOTPb/P+y9DrORJPy1/0BcXh/cHF58kNDZvzVwTFcAjfx6bxS41
|
|
||||||
JAddFRZjNuHXEOtFRkD3Wp4W7Atrv/yeKbpE9PCaNYtUDasL8RKcdJiHNFpN4xRl
|
|
||||||
jpQtIiQ9pikrjUXLgW0S88zzyQKBgQDbQV+DMxGS2Cee6nfMmUcGjgQd8D0cXLjk
|
|
||||||
OZSmEnk4FCvV8ZdysjirqmuitFTE+PYmOJzhlQl8lubEs4Kc7L9CfEwbK9mNN0ZG
|
|
||||||
BNdT21nFuJp7YoZzZDTHuwF0nBjQFYcdaWDW+qFqrqs9mKbmCQ5vSzql6al+pzdX
|
|
||||||
X/YS0QTO0QKBgDUMprHQdUPLByJnnb1gxTqsOa2q3/ldc3eNJXJqWAfi2fjUh8HT
|
|
||||||
k+KxPW9qyqAy1832429FMSQW55ajSn+J6moMfFiGn3ozI8fp9QTGXD5+zJmK/X1N
|
|
||||||
WzEgSyBc9ffago0hFBLQBkDBkdtur7gwfS3qTYgrBhcwfTuFdXAM/FJJAoGABIQ2
|
|
||||||
OXel1waI2mcuDJLjuajXQN6gA6ONU3Y0L6+Vu6f+tyuA2SX+sNqT2Qgp7tzKBUOJ
|
|
||||||
R8RQK7bYDhk8iYr+7Zmt36lpk9Udp3eWD+4mzUHePMhsyJe51pttjj9g63hmDh8L
|
|
||||||
laIYDSCH+n7YgUiSeYxtKtnDWg6Lv0sEwKJ5nOECgYBsF5PoHRE4Q/Vs18qbI4t/
|
|
||||||
zPwWWNP0sb3PYRlWLTKMBowQdDOxnXAF12txoLNhpOn9DjZdNEb2EMsqlzdNjphN
|
|
||||||
uUWZq89d5kDwKfj4ji087elcjsW79R5oqwrN8a0NimftZ4eBPbcn8Y0r5psPcSzE
|
|
||||||
36iKGM2euQYD8Ub+aDOSLQ==
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
|
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 229 KiB After Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 222 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 13 KiB |
@@ -7,20 +7,13 @@ import org.springframework.context.event.EventListener;
|
|||||||
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
|
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
|
||||||
import ru.serega6531.packmate.properties.PackmateProperties;
|
import ru.serega6531.packmate.properties.PackmateProperties;
|
||||||
import ru.serega6531.packmate.security.FakeAdminAuthFilter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@@ -29,46 +22,31 @@ public class SecurityConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public InMemoryUserDetailsManager userDetailsService(PackmateProperties properties, PasswordEncoder passwordEncoder) {
|
public InMemoryUserDetailsManager userDetailsService(PackmateProperties properties, PasswordEncoder passwordEncoder) {
|
||||||
List<UserDetails> users = new ArrayList<>();
|
UserDetails user = User.builder()
|
||||||
|
|
||||||
users.add(User.builder()
|
|
||||||
.username(properties.web().accountLogin())
|
.username(properties.web().accountLogin())
|
||||||
.password(passwordEncoder.encode(properties.web().accountPassword()))
|
.password(passwordEncoder.encode(properties.web().accountPassword()))
|
||||||
.roles("USER")
|
.roles("USER")
|
||||||
.build());
|
.build();
|
||||||
|
|
||||||
Optional.ofNullable(properties.web().fakeAdmin())
|
return new InMemoryUserDetailsManager(user);
|
||||||
.filter(PackmateProperties.FakeAdminProperties::enabled)
|
|
||||||
.ifPresent(fakeAdmin -> users.add(User.builder()
|
|
||||||
.username("admin")
|
|
||||||
.password(passwordEncoder.encode("admin"))
|
|
||||||
.roles("FAKE")
|
|
||||||
.build()));
|
|
||||||
|
|
||||||
return new InMemoryUserDetailsManager(users);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http, FakeAdminAuthFilter fakeAdminAuthFilter) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
return http.csrf()
|
return http.csrf()
|
||||||
.disable()
|
.disable()
|
||||||
.authorizeHttpRequests((auth) ->
|
.authorizeHttpRequests((auth) ->
|
||||||
auth.requestMatchers("/site.webmanifest", "/fake-admin/**", "/fake/**", "/api/fake/**")
|
auth.requestMatchers("/site.webmanifest")
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.requestMatchers("/api/**", "/ws/**")
|
|
||||||
.hasRole("USER")
|
|
||||||
.anyRequest()
|
.anyRequest()
|
||||||
.authenticated()
|
.authenticated()
|
||||||
)
|
)
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
|
||||||
.and()
|
|
||||||
.httpBasic()
|
.httpBasic()
|
||||||
.and()
|
.and()
|
||||||
.headers()
|
.headers()
|
||||||
.frameOptions()
|
.frameOptions()
|
||||||
.sameOrigin()
|
.sameOrigin()
|
||||||
.and()
|
.and()
|
||||||
.addFilterAfter(fakeAdminAuthFilter, BasicAuthenticationFilter.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
package ru.serega6531.packmate.controller;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.serega6531.packmate.security.FakeAdminResponder;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/fake-admin")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class FakeAdminController {
|
|
||||||
|
|
||||||
private final FakeAdminResponder responder;
|
|
||||||
|
|
||||||
@GetMapping(value = "/fun", produces = MediaType.TEXT_HTML_VALUE)
|
|
||||||
public ResponseEntity<String> fun() {
|
|
||||||
return ResponseEntity.ok(responder.funPageHtml());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(value = "/packets", produces = MediaType.TEXT_HTML_VALUE)
|
|
||||||
public ResponseEntity<String> fakePackets() {
|
|
||||||
return ResponseEntity.ok(responder.fakePacketsHtml());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package ru.serega6531.packmate.controller;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.serega6531.packmate.model.pojo.FakeServiceDto;
|
|
||||||
import ru.serega6531.packmate.service.ServicesService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/fake/")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class FakeFacadeController {
|
|
||||||
|
|
||||||
private final ServicesService servicesService;
|
|
||||||
|
|
||||||
@GetMapping("services")
|
|
||||||
public List<FakeServiceDto> getServices() {
|
|
||||||
return servicesService.findAllForFakeFacade();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,8 +23,6 @@ public class CtfService {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private boolean decryptTls;
|
|
||||||
|
|
||||||
private boolean http;
|
private boolean http;
|
||||||
|
|
||||||
private boolean urldecodeHttpRequests;
|
private boolean urldecodeHttpRequests;
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ public class Packet {
|
|||||||
|
|
||||||
private boolean webSocketParsed = false;
|
private boolean webSocketParsed = false;
|
||||||
|
|
||||||
private boolean tlsDecrypted = false;
|
|
||||||
|
|
||||||
private boolean hasHttpBody = false;
|
private boolean hasHttpBody = false;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package ru.serega6531.packmate.model.enums;
|
|
||||||
|
|
||||||
public enum FakeAdminMode {
|
|
||||||
FUN,
|
|
||||||
FAKE_PACKETS
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package ru.serega6531.packmate.model.pojo;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Value;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
@Builder
|
|
||||||
public class FakeServiceDto {
|
|
||||||
int port;
|
|
||||||
String name;
|
|
||||||
String packetKind;
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ public class PacketDto {
|
|||||||
private boolean incoming;
|
private boolean incoming;
|
||||||
private boolean ungzipped;
|
private boolean ungzipped;
|
||||||
private boolean webSocketParsed;
|
private boolean webSocketParsed;
|
||||||
private boolean tlsDecrypted;
|
|
||||||
private boolean hasHttpBody;
|
private boolean hasHttpBody;
|
||||||
private byte[] content;
|
private byte[] content;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ public class ServiceCreateDto {
|
|||||||
|
|
||||||
private int port;
|
private int port;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean decryptTls;
|
|
||||||
private boolean http;
|
private boolean http;
|
||||||
private boolean urldecodeHttpRequests;
|
private boolean urldecodeHttpRequests;
|
||||||
private boolean mergeAdjacentPackets;
|
private boolean mergeAdjacentPackets;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ public class ServiceDto {
|
|||||||
|
|
||||||
private int port;
|
private int port;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean decryptTls;
|
|
||||||
private boolean http;
|
private boolean http;
|
||||||
private boolean urldecodeHttpRequests;
|
private boolean urldecodeHttpRequests;
|
||||||
private boolean mergeAdjacentPackets;
|
private boolean mergeAdjacentPackets;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ public class ServiceUpdateDto {
|
|||||||
|
|
||||||
private int port;
|
private int port;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean decryptTls;
|
|
||||||
private boolean http;
|
private boolean http;
|
||||||
private boolean urldecodeHttpRequests;
|
private boolean urldecodeHttpRequests;
|
||||||
private boolean mergeAdjacentPackets;
|
private boolean mergeAdjacentPackets;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package ru.serega6531.packmate.properties;
|
|||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import ru.serega6531.packmate.model.enums.CaptureMode;
|
import ru.serega6531.packmate.model.enums.CaptureMode;
|
||||||
import ru.serega6531.packmate.model.enums.FakeAdminMode;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
||||||
@@ -21,13 +20,7 @@ public record PackmateProperties(
|
|||||||
|
|
||||||
public record WebProperties(
|
public record WebProperties(
|
||||||
String accountLogin,
|
String accountLogin,
|
||||||
String accountPassword,
|
String accountPassword
|
||||||
FakeAdminProperties fakeAdmin
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public record FakeAdminProperties(
|
|
||||||
boolean enabled,
|
|
||||||
FakeAdminMode mode
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public record TimeoutProperties(
|
public record TimeoutProperties(
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package ru.serega6531.packmate.security;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
import ru.serega6531.packmate.model.enums.FakeAdminMode;
|
|
||||||
import ru.serega6531.packmate.properties.PackmateProperties;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Component
|
|
||||||
public class FakeAdminAuthFilter extends OncePerRequestFilter {
|
|
||||||
|
|
||||||
private final PackmateProperties properties;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
|
||||||
if (!isFakeEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String path = request.getRequestURI();
|
|
||||||
return path.startsWith("/fake-admin")
|
|
||||||
|| path.startsWith("/api/fake")
|
|
||||||
|| path.startsWith("/fake/")
|
|
||||||
|| path.equals("/favicon.ico");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
|
||||||
if (!isFakeEnabled()) {
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
boolean isFakeAdmin = authentication != null && authentication.isAuthenticated()
|
|
||||||
&& authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_FAKE"));
|
|
||||||
|
|
||||||
if (isFakeAdmin) {
|
|
||||||
FakeAdminMode mode = Optional.ofNullable(properties.web().fakeAdmin())
|
|
||||||
.map(PackmateProperties.FakeAdminProperties::mode)
|
|
||||||
.orElse(FakeAdminMode.FUN);
|
|
||||||
String target = "/fake-admin/" + resolvePath(mode);
|
|
||||||
log.info("Redirecting fake admin to {}", target);
|
|
||||||
response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
|
|
||||||
response.setHeader(HttpHeaders.LOCATION, target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFakeEnabled() {
|
|
||||||
return Optional.ofNullable(properties.web().fakeAdmin())
|
|
||||||
.map(PackmateProperties.FakeAdminProperties::enabled)
|
|
||||||
.orElse(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String resolvePath(FakeAdminMode mode) {
|
|
||||||
return switch (mode) {
|
|
||||||
case FAKE_PACKETS -> "packets";
|
|
||||||
case FUN -> "fun";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,662 +0,0 @@
|
|||||||
package ru.serega6531.packmate.security;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StreamUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class FakeAdminResponder {
|
|
||||||
|
|
||||||
private final ObjectMapper mapper = new ObjectMapper();
|
|
||||||
private final List<String> encodedImages;
|
|
||||||
|
|
||||||
public FakeAdminResponder() {
|
|
||||||
this.encodedImages = loadImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> loadImages() {
|
|
||||||
try {
|
|
||||||
Resource[] resources = new PathMatchingResourcePatternResolver()
|
|
||||||
.getResources("classpath:/static/fake/images/*");
|
|
||||||
|
|
||||||
List<String> images = Arrays.stream(resources)
|
|
||||||
.map(resource -> {
|
|
||||||
try {
|
|
||||||
String contentType = URLConnection.guessContentTypeFromName(resource.getFilename());
|
|
||||||
if (contentType == null) {
|
|
||||||
contentType = "image/jpeg";
|
|
||||||
}
|
|
||||||
byte[] raw = StreamUtils.copyToByteArray(resource.getInputStream());
|
|
||||||
return "data:%s;base64,%s".formatted(
|
|
||||||
contentType,
|
|
||||||
Base64.getEncoder().encodeToString(raw));
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Failed to load fake admin image {}", resource.getFilename(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (images.isEmpty()) {
|
|
||||||
log.warn("No images found for fake admin fun mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
return images;
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Failed to load fake admin images", e);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String funPageHtml() {
|
|
||||||
String phrasesJson = toJson(getFunPhrases());
|
|
||||||
String imagesJson = toJson(encodedImages);
|
|
||||||
String phrasesB64 = Base64.getEncoder().encodeToString(phrasesJson.getBytes(StandardCharsets.UTF_8));
|
|
||||||
String imagesB64 = Base64.getEncoder().encodeToString(imagesJson.getBytes(StandardCharsets.UTF_8));
|
|
||||||
String template = """
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>0xb00b5 team Packmate // fake funwall</title>
|
|
||||||
<style>
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@500&display=swap');
|
|
||||||
:root {
|
|
||||||
--bg: #050512;
|
|
||||||
--accent: #59f3ff;
|
|
||||||
--accent-2: #ff5fd2;
|
|
||||||
--glass: rgba(9, 19, 45, 0.75);
|
|
||||||
--grid: rgba(89, 243, 255, 0.25);
|
|
||||||
}
|
|
||||||
* { box-sizing: border-box; }
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: radial-gradient(circle at 20% 20%, rgba(255, 95, 210, 0.18), transparent 25%), radial-gradient(circle at 80% 0%, rgba(89, 243, 255, 0.2), transparent 30%), linear-gradient(135deg, #04040d 0%, #0a1024 45%, #050512 100%);
|
|
||||||
color: #e9f7ff;
|
|
||||||
font-family: 'Press Start 2P', 'JetBrains Mono', monospace;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 40px 18px 60px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.grid-bg {
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px);
|
|
||||||
background-size: 80px 80px;
|
|
||||||
mask-image: radial-gradient(circle at 50% 20%, rgba(0,0,0,.8), transparent 75%);
|
|
||||||
opacity: 0.5;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
.shell {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
width: min(90vw, 1180px);
|
|
||||||
background: var(--glass);
|
|
||||||
border: 1px solid rgba(89, 243, 255, 0.4);
|
|
||||||
box-shadow: 0 0 40px rgba(89, 243, 255, 0.25), 0 0 24px rgba(255, 95, 210, 0.2);
|
|
||||||
border-radius: 18px;
|
|
||||||
padding: 32px;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
.shell::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 12px;
|
|
||||||
border: 1px dashed rgba(255, 95, 210, 0.25);
|
|
||||||
border-radius: 14px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin: 0 0 20px;
|
|
||||||
font-size: 18px;
|
|
||||||
letter-spacing: 1.5px;
|
|
||||||
text-shadow: 0 0 8px rgba(89, 243, 255, 0.8);
|
|
||||||
}
|
|
||||||
.badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 8px 14px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1px solid rgba(255, 95, 210, 0.35);
|
|
||||||
color: #ffcdf4;
|
|
||||||
box-shadow: inset 0 0 10px rgba(255, 95, 210, 0.35), 0 0 10px rgba(255, 95, 210, 0.35);
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
canvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 420px;
|
|
||||||
border-radius: 14px;
|
|
||||||
border: 1px solid rgba(89, 243, 255, 0.35);
|
|
||||||
background: radial-gradient(circle at 30% 30%, rgba(255, 95, 210, 0.08), transparent 40%), #0b122a;
|
|
||||||
box-shadow: inset 0 0 30px rgba(0,0,0,0.35), 0 0 18px rgba(89, 243, 255, 0.12);
|
|
||||||
}
|
|
||||||
.typed {
|
|
||||||
margin-top: 22px;
|
|
||||||
font-size: 14px;
|
|
||||||
min-height: 24px;
|
|
||||||
letter-spacing: 0.8px;
|
|
||||||
color: #aaf6ff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
#typed-text {
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.cursor {
|
|
||||||
display: inline-block;
|
|
||||||
width: 12px;
|
|
||||||
background: #aaf6ff;
|
|
||||||
animation: blink 0.8s infinite;
|
|
||||||
height: 14px;
|
|
||||||
}
|
|
||||||
@keyframes blink {
|
|
||||||
0%, 50% { opacity: 1; }
|
|
||||||
51%, 100% { opacity: 0.2; }
|
|
||||||
}
|
|
||||||
.footer-note {
|
|
||||||
margin-top: 18px;
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(233, 247, 255, 0.65);
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="grid-bg"></div>
|
|
||||||
<div class="shell">
|
|
||||||
<h1>0xb00b5 team Packmate</h1>
|
|
||||||
<div class="badge">// @danosito</div>
|
|
||||||
<canvas id="snap-canvas"></canvas>
|
|
||||||
<audio id="fun-music" src="/fake/audio/Archive.Clue.mp3" preload="auto" loop></audio>
|
|
||||||
<div class="typed">
|
|
||||||
<span id="typed-text"></span><span class="cursor"></span>
|
|
||||||
</div>
|
|
||||||
<div class="footer-note">Hmmm where are the packets? IDK</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
const phrases = JSON.parse(atob('__PHRASES_B64__'));
|
|
||||||
const images = JSON.parse(atob('__IMAGES_B64__'));
|
|
||||||
const canvas = document.getElementById('snap-canvas');
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const textEl = document.getElementById('typed-text');
|
|
||||||
const audioEl = document.getElementById('fun-music');
|
|
||||||
|
|
||||||
const pick = (list) => list[Math.floor(Math.random() * list.length)];
|
|
||||||
const specialLink = {
|
|
||||||
text: 'Your special guide to get flag!',
|
|
||||||
href: 'https://youtu.be/rrw-Pv3rc0E?si=-ZQmhZVxh4HF6luD'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (audioEl) {
|
|
||||||
const ensurePlaying = () => {
|
|
||||||
if (!audioEl.dataset.started) {
|
|
||||||
audioEl.dataset.started = '1';
|
|
||||||
audioEl.volume = 0.4;
|
|
||||||
}
|
|
||||||
audioEl.play().catch(() => {});
|
|
||||||
};
|
|
||||||
|
|
||||||
ensurePlaying();
|
|
||||||
setInterval(() => {
|
|
||||||
if (audioEl.paused) {
|
|
||||||
audioEl.play().catch(() => {});
|
|
||||||
}
|
|
||||||
}, 2500);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderImage() {
|
|
||||||
const chosen = (images && images.length) ? pick(images) : '';
|
|
||||||
if (!chosen) {
|
|
||||||
ctx.fillStyle = '#0b122a';
|
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
const maxW = 960;
|
|
||||||
const scale = Math.min(maxW / img.width, 1);
|
|
||||||
const w = img.width * scale;
|
|
||||||
const h = img.height * scale;
|
|
||||||
canvas.width = w;
|
|
||||||
canvas.height = h;
|
|
||||||
ctx.clearRect(0, 0, w, h);
|
|
||||||
ctx.drawImage(img, 0, 0, w, h);
|
|
||||||
setTimeout(() => snapAway(), 5000);
|
|
||||||
};
|
|
||||||
img.src = chosen;
|
|
||||||
}
|
|
||||||
|
|
||||||
function snapAway() {
|
|
||||||
let ticks = 0;
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
for (let i = 0; i < 48; i++) {
|
|
||||||
const x = Math.random() * canvas.width;
|
|
||||||
const y = Math.random() * canvas.height;
|
|
||||||
const size = 4 + Math.random() * 10;
|
|
||||||
ctx.clearRect(x, y, size, size);
|
|
||||||
}
|
|
||||||
ticks++;
|
|
||||||
if (ticks > 80) {
|
|
||||||
clearInterval(interval);
|
|
||||||
setTimeout(renderImage, 400);
|
|
||||||
}
|
|
||||||
}, 28);
|
|
||||||
}
|
|
||||||
|
|
||||||
function typewriter() {
|
|
||||||
const phrase = pick(phrases);
|
|
||||||
const isSpecial = phrase === specialLink.text;
|
|
||||||
textEl.textContent = '';
|
|
||||||
let linkEl = null;
|
|
||||||
if (isSpecial) {
|
|
||||||
linkEl = document.createElement('a');
|
|
||||||
linkEl.href = specialLink.href;
|
|
||||||
linkEl.target = '_blank';
|
|
||||||
linkEl.rel = 'noreferrer noopener';
|
|
||||||
linkEl.style.color = '#aaf6ff';
|
|
||||||
textEl.appendChild(linkEl);
|
|
||||||
}
|
|
||||||
let i = 0;
|
|
||||||
const typeDelay = phrase.length ? 5000 / phrase.length : 120;
|
|
||||||
|
|
||||||
const typeInterval = setInterval(() => {
|
|
||||||
const target = isSpecial ? linkEl : textEl;
|
|
||||||
target.textContent += phrase.charAt(i);
|
|
||||||
i++;
|
|
||||||
if (i >= phrase.length) {
|
|
||||||
clearInterval(typeInterval);
|
|
||||||
setTimeout(() => erase(phrase, isSpecial), 3000);
|
|
||||||
}
|
|
||||||
}, typeDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
function erase(phrase, isSpecial) {
|
|
||||||
const eraseDelay = phrase.length ? 2000 / phrase.length : 80;
|
|
||||||
const eraser = setInterval(() => {
|
|
||||||
const target = isSpecial ? textEl.querySelector('a') : textEl;
|
|
||||||
if (!target) {
|
|
||||||
clearInterval(eraser);
|
|
||||||
setTimeout(typewriter, 200);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
target.textContent = target.textContent.slice(0, -1);
|
|
||||||
if (!target.textContent.length) {
|
|
||||||
if (isSpecial) {
|
|
||||||
target.remove();
|
|
||||||
}
|
|
||||||
clearInterval(eraser);
|
|
||||||
setTimeout(typewriter, 200);
|
|
||||||
}
|
|
||||||
}, eraseDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderImage();
|
|
||||||
typewriter();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""";
|
|
||||||
return template
|
|
||||||
.replace("__PHRASES_B64__", phrasesB64)
|
|
||||||
.replace("__IMAGES_B64__", imagesB64);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String fakePacketsHtml() {
|
|
||||||
return """
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>0xb00b5 PM // packets</title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css">
|
|
||||||
<style>
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@400;600&display=swap');
|
|
||||||
:root {
|
|
||||||
--bg: #05030a;
|
|
||||||
--bg-2: #0a0a18;
|
|
||||||
--panel: rgba(9, 7, 18, 0.9);
|
|
||||||
--panel-strong: rgba(14, 10, 24, 0.95);
|
|
||||||
--accent: #c66bff;
|
|
||||||
--accent-2: #7a1dff;
|
|
||||||
--text: #e6e0ff;
|
|
||||||
--muted: #9b90c8;
|
|
||||||
--mono: 'JetBrains Mono', 'Ubuntu Mono', monospace;
|
|
||||||
--pixel: 'Press Start 2P', 'JetBrains Mono', monospace;
|
|
||||||
}
|
|
||||||
* { box-sizing: border-box; scrollbar-width: none; }
|
|
||||||
*::-webkit-scrollbar { width: 0; height: 0; }
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
min-height: 100vh;
|
|
||||||
background:
|
|
||||||
radial-gradient(circle at 18% 24%, rgba(198, 107, 255, 0.18), transparent 25%),
|
|
||||||
radial-gradient(circle at 82% 12%, rgba(122, 29, 255, 0.12), transparent 25%),
|
|
||||||
linear-gradient(135deg, #020107 0%, #0a0820 50%, #03010b 100%);
|
|
||||||
color: var(--text);
|
|
||||||
font-family: var(--pixel);
|
|
||||||
letter-spacing: 0.6px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.bg-lines {
|
|
||||||
position: fixed; inset: 0; pointer-events: none; z-index: 0;
|
|
||||||
background-image: linear-gradient(rgba(122, 29, 255, 0.1) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(198, 107, 255, 0.12) 1px, transparent 1px);
|
|
||||||
background-size: 120px 120px;
|
|
||||||
}
|
|
||||||
.app-shell {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.navbar {
|
|
||||||
background: var(--panel-strong);
|
|
||||||
border-bottom: 1px solid rgba(122, 29, 255, 0.45);
|
|
||||||
box-shadow: 0 10px 35px rgba(0, 0, 0, 0.55), 0 0 28px rgba(122, 29, 255, 0.35);
|
|
||||||
padding: 12px 18px;
|
|
||||||
}
|
|
||||||
.brand {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
.brand .dot {
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
||||||
box-shadow: 0 0 10px rgba(122, 29, 255, 0.65);
|
|
||||||
}
|
|
||||||
.metrics {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.chip {
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.28);
|
|
||||||
color: var(--text);
|
|
||||||
padding: 8px 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
column-gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 11px;
|
|
||||||
box-shadow: 0 0 14px rgba(122, 29, 255, 0.24);
|
|
||||||
}
|
|
||||||
.chip .label { color: var(--muted); }
|
|
||||||
.chip .value { color: var(--accent); }
|
|
||||||
.patterns-dropdown {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 128px;
|
|
||||||
min-width: 128px;
|
|
||||||
max-width: 128px;
|
|
||||||
flex: 0 0 128px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-left: 14px;
|
|
||||||
}
|
|
||||||
.patterns-dropdown > button {
|
|
||||||
display: inline-flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-family: var(--pixel);
|
|
||||||
font-size: 9.6px;
|
|
||||||
letter-spacing: 0.05px;
|
|
||||||
width: 128px;
|
|
||||||
min-width: 128px;
|
|
||||||
max-width: 128px;
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-right: 8px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.services-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
margin-left: 14px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.services-nav .nav-link {
|
|
||||||
padding: 6px 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 2px 0;
|
|
||||||
background: rgba(122, 29, 255, 0.12);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.28);
|
|
||||||
color: var(--text);
|
|
||||||
font-size: 10px;
|
|
||||||
letter-spacing: 0.3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.layout {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 320px 1fr;
|
|
||||||
gap: 0;
|
|
||||||
min-height: calc(100vh - 72px);
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
background: var(--panel);
|
|
||||||
border-right: 1px solid rgba(122, 29, 255, 0.25);
|
|
||||||
box-shadow: inset -10px 0 24px rgba(0, 0, 0, 0.35);
|
|
||||||
padding: 16px 12px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.sidebar-title {
|
|
||||||
font-size: 10px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--muted);
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
background: var(--panel);
|
|
||||||
border-left: 1px solid rgba(122, 29, 255, 0.15);
|
|
||||||
padding: 18px 22px 26px;
|
|
||||||
box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.45), 0 0 38px rgba(122, 29, 255, 0.18);
|
|
||||||
position: relative;
|
|
||||||
min-height: calc(100vh - 120px);
|
|
||||||
}
|
|
||||||
.content-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
.packet-board {
|
|
||||||
background: rgba(9, 7, 18, 0.9);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.35);
|
|
||||||
border-radius: 14px;
|
|
||||||
min-height: calc(100vh - 160px);
|
|
||||||
padding: 14px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.packet-feed {
|
|
||||||
font-family: var(--mono);
|
|
||||||
font-size: 11px;
|
|
||||||
max-height: calc(100vh - 200px);
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 6px;
|
|
||||||
}
|
|
||||||
.packet-line {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 6px 0;
|
|
||||||
border-bottom: 1px dashed rgba(122, 29, 255, 0.2);
|
|
||||||
color: var(--text);
|
|
||||||
}
|
|
||||||
.packet-line .pill {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: rgba(122, 29, 255, 0.2);
|
|
||||||
border: 1px solid rgba(122, 29, 255, 0.35);
|
|
||||||
font-size: 9px;
|
|
||||||
letter-spacing: 0.4px;
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
.packet-line .meta {
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
.packet-line .bytes { color: #9ff8ff; }
|
|
||||||
.empty-slot { background: transparent; border: none; box-shadow: none; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="bg-lines"></div>
|
|
||||||
<div class="app-shell">
|
|
||||||
<nav class="navbar navbar-dark navbar-expand fixed-top">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="brand">
|
|
||||||
<span class="dot"></span>
|
|
||||||
0xb00b5 PM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="metrics">
|
|
||||||
<span class="chip"><span class="label">SPM</span><span class="value" id="metric-spm">0</span></span>
|
|
||||||
<span class="chip"><span class="label">PPS</span><span class="value" id="metric-pps">0</span></span>
|
|
||||||
</div>
|
|
||||||
<div class="patterns-dropdown">
|
|
||||||
<button class="btn btn-dark btn-block" disabled>Patterns</button>
|
|
||||||
</div>
|
|
||||||
<div class="services-nav" id="nav-services"></div>
|
|
||||||
<span class="ml-auto text-monospace text-muted" style="font-size: 10px;">[Selected: none]</span>
|
|
||||||
</nav>
|
|
||||||
<div class="layout" style="margin-top: 64px;">
|
|
||||||
<aside class="sidebar">
|
|
||||||
<div class="sidebar-title">Packets</div>
|
|
||||||
<div class="packet-board">
|
|
||||||
<div class="packet-feed" id="packet-feed"></div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
<main class="content empty-slot"></main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
const navServicesEl = document.getElementById('nav-services');
|
|
||||||
const feedEl = document.getElementById('packet-feed');
|
|
||||||
const spmEl = document.getElementById('metric-spm');
|
|
||||||
const ppsEl = document.getElementById('metric-pps');
|
|
||||||
let services = [];
|
|
||||||
let packetId = Math.floor(Math.random() * 5000) + 10;
|
|
||||||
|
|
||||||
fetch('/api/fake/services')
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
services = data;
|
|
||||||
renderServices();
|
|
||||||
startFeed();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
services = [{ name: 'ghost', port: 0, packetKind: 'tcp' }];
|
|
||||||
renderServices();
|
|
||||||
startFeed();
|
|
||||||
});
|
|
||||||
|
|
||||||
function renderServices() {
|
|
||||||
navServicesEl.innerHTML = '';
|
|
||||||
services.forEach((svc) => {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.className = 'nav-link';
|
|
||||||
link.href = '#';
|
|
||||||
link.textContent = `${svc.name} #${svc.port}`;
|
|
||||||
navServicesEl.appendChild(link);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function spawnPacket() {
|
|
||||||
if (!services.length) return;
|
|
||||||
const svc = services[Math.floor(Math.random() * services.length)];
|
|
||||||
const proto = (svc.packetKind || 'tcp').toUpperCase();
|
|
||||||
const ts = new Date();
|
|
||||||
const clock = ts.toTimeString().slice(0, 8);
|
|
||||||
const bytes = Math.floor(Math.random() * 1800) + 40;
|
|
||||||
|
|
||||||
const line = document.createElement('div');
|
|
||||||
line.className = 'packet-line';
|
|
||||||
line.innerHTML = `
|
|
||||||
<span class="pill">${proto}</span>
|
|
||||||
<span class="meta">${clock}</span>
|
|
||||||
<span class="meta">:${svc.port} ${svc.name}</span>
|
|
||||||
<span class="bytes">${bytes} bytes</span>
|
|
||||||
<span class="meta">id #${packetId}</span>
|
|
||||||
`;
|
|
||||||
packetId++;
|
|
||||||
feedEl.prepend(line);
|
|
||||||
while (feedEl.children.length > 120) {
|
|
||||||
feedEl.removeChild(feedEl.lastChild);
|
|
||||||
}
|
|
||||||
updateMetrics();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateMetrics() {
|
|
||||||
const total = feedEl.children.length;
|
|
||||||
spmEl.textContent = Math.min(total, 999);
|
|
||||||
ppsEl.textContent = Math.floor(total / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
function startFeed() {
|
|
||||||
setInterval(spawnPacket, 55);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""";
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getFunPhrases() {
|
|
||||||
return List.of(
|
|
||||||
"Here's the flag. Are you ready? here it goes... Wait, no.",
|
|
||||||
"Wanna see the flag? send yours to @danosito:)",
|
|
||||||
"Hey, why are you here? go pentest our services",
|
|
||||||
"Hmmm i think <script>alert(\"You're stupid\")</script> might work..",
|
|
||||||
"Bip, boop, here was packet but codex ate it",
|
|
||||||
"Our LLM tockens ran out. Maybe you could give us some:)?",
|
|
||||||
":(){ :|:& };:",
|
|
||||||
"i think creds are admin:admin but i'm not sure...",
|
|
||||||
"Try eternalBlue, i think it would work",
|
|
||||||
"I think i defended this page well enough, here is flag: LLMDELETEDTHEFLAG=",
|
|
||||||
"Go open ida pro and reverse this text",
|
|
||||||
"I would give you our flags for free, but you are a bad person:(",
|
|
||||||
"b00b5 is not a fresh meat:(",
|
|
||||||
"marcus, send your packmate credits pls",
|
|
||||||
"Marcus, fuck off",
|
|
||||||
"Your special guide to get flag!"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toJson(List<String> data) {
|
|
||||||
try {
|
|
||||||
return mapper.writeValueAsString(data);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
log.warn("Failed to convert data to json for fake admin", e);
|
|
||||||
return "[]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@ import ru.serega6531.packmate.model.pojo.ServiceCreateDto;
|
|||||||
import ru.serega6531.packmate.model.pojo.ServiceDto;
|
import ru.serega6531.packmate.model.pojo.ServiceDto;
|
||||||
import ru.serega6531.packmate.model.pojo.ServiceUpdateDto;
|
import ru.serega6531.packmate.model.pojo.ServiceUpdateDto;
|
||||||
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
|
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
|
||||||
import ru.serega6531.packmate.model.pojo.FakeServiceDto;
|
|
||||||
import ru.serega6531.packmate.repository.ServiceRepository;
|
import ru.serega6531.packmate.repository.ServiceRepository;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -80,17 +79,6 @@ public class ServicesService {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FakeServiceDto> findAllForFakeFacade() {
|
|
||||||
return services.values()
|
|
||||||
.stream()
|
|
||||||
.map(s -> FakeServiceDto.builder()
|
|
||||||
.port(s.getPort())
|
|
||||||
.name(s.getName())
|
|
||||||
.packetKind(s.isHttp() || s.isParseWebSockets() ? "tcp/http" : "tcp")
|
|
||||||
.build())
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteByPort(int port) {
|
public void deleteByPort(int port) {
|
||||||
log.info("Removed service at port {}", port);
|
log.info("Removed service at port {}", port);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import org.springframework.scheduling.annotation.Async;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.serega6531.packmate.properties.PackmateProperties;
|
|
||||||
import ru.serega6531.packmate.model.CtfService;
|
import ru.serega6531.packmate.model.CtfService;
|
||||||
import ru.serega6531.packmate.model.FoundPattern;
|
import ru.serega6531.packmate.model.FoundPattern;
|
||||||
import ru.serega6531.packmate.model.Packet;
|
import ru.serega6531.packmate.model.Packet;
|
||||||
@@ -26,8 +25,8 @@ import ru.serega6531.packmate.model.pojo.StreamDto;
|
|||||||
import ru.serega6531.packmate.model.pojo.StreamPagination;
|
import ru.serega6531.packmate.model.pojo.StreamPagination;
|
||||||
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
|
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
|
||||||
import ru.serega6531.packmate.model.pojo.UnfinishedStream;
|
import ru.serega6531.packmate.model.pojo.UnfinishedStream;
|
||||||
|
import ru.serega6531.packmate.properties.PackmateProperties;
|
||||||
import ru.serega6531.packmate.repository.StreamRepository;
|
import ru.serega6531.packmate.repository.StreamRepository;
|
||||||
import ru.serega6531.packmate.service.optimization.RsaKeysHolder;
|
|
||||||
import ru.serega6531.packmate.service.optimization.StreamOptimizer;
|
import ru.serega6531.packmate.service.optimization.StreamOptimizer;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
@@ -46,7 +45,6 @@ public class StreamService {
|
|||||||
private final ServicesService servicesService;
|
private final ServicesService servicesService;
|
||||||
private final CountingService countingService;
|
private final CountingService countingService;
|
||||||
private final SubscriptionService subscriptionService;
|
private final SubscriptionService subscriptionService;
|
||||||
private final RsaKeysHolder keysHolder;
|
|
||||||
private final ModelMapper modelMapper;
|
private final ModelMapper modelMapper;
|
||||||
private final boolean ignoreEmptyPackets;
|
private final boolean ignoreEmptyPackets;
|
||||||
|
|
||||||
@@ -58,7 +56,6 @@ public class StreamService {
|
|||||||
ServicesService servicesService,
|
ServicesService servicesService,
|
||||||
CountingService countingService,
|
CountingService countingService,
|
||||||
SubscriptionService subscriptionService,
|
SubscriptionService subscriptionService,
|
||||||
RsaKeysHolder keysHolder,
|
|
||||||
ModelMapper modelMapper,
|
ModelMapper modelMapper,
|
||||||
PackmateProperties properties) {
|
PackmateProperties properties) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
@@ -66,7 +63,6 @@ public class StreamService {
|
|||||||
this.servicesService = servicesService;
|
this.servicesService = servicesService;
|
||||||
this.countingService = countingService;
|
this.countingService = countingService;
|
||||||
this.subscriptionService = subscriptionService;
|
this.subscriptionService = subscriptionService;
|
||||||
this.keysHolder = keysHolder;
|
|
||||||
this.modelMapper = modelMapper;
|
this.modelMapper = modelMapper;
|
||||||
this.ignoreEmptyPackets = properties.ignoreEmptyPackets();
|
this.ignoreEmptyPackets = properties.ignoreEmptyPackets();
|
||||||
}
|
}
|
||||||
@@ -104,7 +100,7 @@ public class StreamService {
|
|||||||
int packetsSize = packets.stream().mapToInt(p -> p.getContent().length).sum();
|
int packetsSize = packets.stream().mapToInt(p -> p.getContent().length).sum();
|
||||||
int packetsCount = packets.size();
|
int packetsCount = packets.size();
|
||||||
|
|
||||||
List<Packet> optimizedPackets = new StreamOptimizer(keysHolder, service, packets).optimizeStream();
|
List<Packet> optimizedPackets = new StreamOptimizer(service, packets).optimizeStream();
|
||||||
|
|
||||||
if (isStreamIgnored(optimizedPackets, service)) {
|
if (isStreamIgnored(optimizedPackets, service)) {
|
||||||
log.debug("New stream is ignored");
|
log.debug("New stream is ignored");
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ public class PacketsMerger {
|
|||||||
final long timestamp = cut.get(0).getTimestamp();
|
final long timestamp = cut.get(0).getTimestamp();
|
||||||
final boolean httpProcessed = cut.stream().anyMatch(Packet::isHttpProcessed);
|
final boolean httpProcessed = cut.stream().anyMatch(Packet::isHttpProcessed);
|
||||||
final boolean webSocketParsed = cut.stream().anyMatch(Packet::isWebSocketParsed);
|
final boolean webSocketParsed = cut.stream().anyMatch(Packet::isWebSocketParsed);
|
||||||
final boolean tlsDecrypted = cut.get(0).isTlsDecrypted();
|
|
||||||
final boolean incoming = cut.get(0).isIncoming();
|
final boolean incoming = cut.get(0).isIncoming();
|
||||||
final byte[] content = PacketUtils.mergePackets(cut);
|
final byte[] content = PacketUtils.mergePackets(cut);
|
||||||
|
|
||||||
@@ -55,7 +54,6 @@ public class PacketsMerger {
|
|||||||
.timestamp(timestamp)
|
.timestamp(timestamp)
|
||||||
.httpProcessed(httpProcessed)
|
.httpProcessed(httpProcessed)
|
||||||
.webSocketParsed(webSocketParsed)
|
.webSocketParsed(webSocketParsed)
|
||||||
.tlsDecrypted(tlsDecrypted)
|
|
||||||
.content(content)
|
.content(content)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.security.KeyFactory;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class RsaKeysHolder {
|
|
||||||
|
|
||||||
// Key: N from RSA public key
|
|
||||||
private final Map<BigInteger, RSAPrivateKey> keys = new HashMap<>();
|
|
||||||
|
|
||||||
public RSAPrivateKey getKey(BigInteger modulus) {
|
|
||||||
return keys.get(modulus);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
|
||||||
public void afterStartup(ApplicationReadyEvent event) {
|
|
||||||
log.info("Loading RSA keys...");
|
|
||||||
File dir = new File("rsa_keys");
|
|
||||||
if (dir.exists() && dir.isDirectory()) {
|
|
||||||
for (File keyFile : Objects.requireNonNull(dir.listFiles())) {
|
|
||||||
addKey(keyFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public void addKey(File keyFile) {
|
|
||||||
if (!keyFile.exists()) {
|
|
||||||
throw new IllegalArgumentException("Key file does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
RSAPrivateKey privateKey = loadFromFile(keyFile);
|
|
||||||
keys.put(privateKey.getModulus(), privateKey);
|
|
||||||
String n = privateKey.getModulus().toString();
|
|
||||||
log.info("Loaded RSA key with N={}...", n.substring(0, Math.min(n.length(), 8)));
|
|
||||||
} catch (IOException | InvalidKeySpecException e) {
|
|
||||||
log.error("Error loading rsa key", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private RSAPrivateKey loadFromFile(File keyFile) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
|
|
||||||
String content = Files.readString(keyFile.toPath());
|
|
||||||
|
|
||||||
content = content.replaceAll("-----BEGIN (RSA )?PRIVATE KEY-----", "")
|
|
||||||
.replaceAll("-----END (RSA )?PRIVATE KEY-----", "")
|
|
||||||
.replace("\n", "");
|
|
||||||
|
|
||||||
byte[] keyBytes = Base64.getDecoder().decode(content);
|
|
||||||
|
|
||||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
|
|
||||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
|
||||||
return (RSAPrivateKey) kf.generatePrivate(spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,6 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class StreamOptimizer {
|
public class StreamOptimizer {
|
||||||
|
|
||||||
private final RsaKeysHolder keysHolder;
|
|
||||||
private final CtfService service;
|
private final CtfService service;
|
||||||
private List<Packet> packets;
|
private List<Packet> packets;
|
||||||
|
|
||||||
@@ -24,15 +23,6 @@ public class StreamOptimizer {
|
|||||||
* Вызвать для выполнения оптимизаций на переданном списке пакетов.
|
* Вызвать для выполнения оптимизаций на переданном списке пакетов.
|
||||||
*/
|
*/
|
||||||
public List<Packet> optimizeStream() {
|
public List<Packet> optimizeStream() {
|
||||||
if (service.isDecryptTls()) {
|
|
||||||
try {
|
|
||||||
decryptTls();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Error optimizing stream (tls)", e);
|
|
||||||
return packets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service.isParseWebSockets()) {
|
if (service.isParseWebSockets()) {
|
||||||
try {
|
try {
|
||||||
parseWebSockets();
|
parseWebSockets();
|
||||||
@@ -72,15 +62,6 @@ public class StreamOptimizer {
|
|||||||
return packets;
|
return packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decryptTls() {
|
|
||||||
final TlsDecryptor tlsDecryptor = new TlsDecryptor(packets, keysHolder);
|
|
||||||
tlsDecryptor.decryptTls();
|
|
||||||
|
|
||||||
if (tlsDecryptor.isParsed()) {
|
|
||||||
packets = tlsDecryptor.getParsedPackets();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseWebSockets() {
|
private void parseWebSockets() {
|
||||||
if (!packets.get(0).getContentString().contains("HTTP/")) {
|
if (!packets.get(0).getContentString().contains("HTTP/")) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,297 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization;
|
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
|
||||||
import com.google.common.collect.ListMultimap;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.bouncycastle.tls.ExporterLabel;
|
|
||||||
import org.bouncycastle.tls.PRFAlgorithm;
|
|
||||||
import org.bouncycastle.tls.crypto.TlsSecret;
|
|
||||||
import org.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto;
|
|
||||||
import org.bouncycastle.tls.crypto.impl.bc.BcTlsSecret;
|
|
||||||
import org.pcap4j.packet.IllegalRawDataException;
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.model.Packet;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.TlsPacket;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.TlsKeyUtils;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.CipherSuite;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ContentType;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.HandshakeType;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.ApplicationDataRecord;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.HandshakeRecord;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.handshakes.*;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class TlsDecryptor {
|
|
||||||
|
|
||||||
private static final Pattern cipherSuitePattern = Pattern.compile("TLS_RSA_WITH_([A-Z0-9_]+)_[A-Z0-9]+");
|
|
||||||
|
|
||||||
private final List<Packet> packets;
|
|
||||||
private final RsaKeysHolder keysHolder;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private boolean parsed = false;
|
|
||||||
private List<Packet> result;
|
|
||||||
|
|
||||||
private ListMultimap<Packet, TlsPacket.TlsHeader> tlsPackets;
|
|
||||||
private byte[] clientRandom;
|
|
||||||
private byte[] serverRandom;
|
|
||||||
|
|
||||||
public void decryptTls() {
|
|
||||||
tlsPackets = ArrayListMultimap.create(packets.size(), 1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (Packet p : packets) {
|
|
||||||
tlsPackets.putAll(p, createTlsHeaders(p));
|
|
||||||
}
|
|
||||||
} catch (IllegalRawDataException e) {
|
|
||||||
log.warn("Failed to parse TLS packets", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientHelloOpt = getHandshake(HandshakeType.CLIENT_HELLO);
|
|
||||||
var serverHelloOpt = getHandshake(HandshakeType.SERVER_HELLO);
|
|
||||||
|
|
||||||
if (clientHelloOpt.isEmpty() || serverHelloOpt.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientHello = (ClientHelloHandshakeRecordContent) clientHelloOpt.get();
|
|
||||||
var serverHello = (ServerHelloHandshakeRecordContent) serverHelloOpt.get();
|
|
||||||
|
|
||||||
CipherSuite cipherSuite = serverHello.getCipherSuite();
|
|
||||||
|
|
||||||
if (cipherSuite.name().startsWith("TLS_RSA_WITH_")) {
|
|
||||||
Matcher matcher = cipherSuitePattern.matcher(cipherSuite.name());
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
matcher.find();
|
|
||||||
String blockCipher = matcher.group(1);
|
|
||||||
|
|
||||||
clientRandom = clientHello.getRandom();
|
|
||||||
serverRandom = serverHello.getRandom();
|
|
||||||
|
|
||||||
decryptTlsRsa(blockCipher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void decryptTlsRsa(String blockCipher) {
|
|
||||||
String[] blockCipherParts = blockCipher.split("_");
|
|
||||||
String blockCipherAlgo = blockCipherParts[0];
|
|
||||||
int blockCipherSize = Integer.parseInt(blockCipherParts[1]);
|
|
||||||
String blockCipherMode = blockCipherParts[2];
|
|
||||||
|
|
||||||
if (!blockCipherAlgo.equals("AES")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int keyLength = blockCipherSize / 8;
|
|
||||||
|
|
||||||
Optional<RSAPublicKey> publicKeyOpt = getRsaPublicKey();
|
|
||||||
|
|
||||||
if (publicKeyOpt.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RSAPublicKey publicKey = publicKeyOpt.get();
|
|
||||||
RSAPrivateKey privateKey = keysHolder.getKey(publicKey.getModulus());
|
|
||||||
if (privateKey == null) {
|
|
||||||
String n = publicKey.getModulus().toString();
|
|
||||||
log.warn("Key for modulus not found: {}...", n.substring(0, Math.min(n.length(), 8)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<BcTlsSecret> preMasterOptional = getPreMaster(privateKey);
|
|
||||||
if (preMasterOptional.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BcTlsSecret preMaster = preMasterOptional.get();
|
|
||||||
|
|
||||||
byte[] randomCS = ArrayUtils.addAll(clientRandom, serverRandom);
|
|
||||||
byte[] randomSC = ArrayUtils.addAll(serverRandom, clientRandom);
|
|
||||||
|
|
||||||
TlsSecret masterSecret = preMaster.deriveUsingPRF(
|
|
||||||
PRFAlgorithm.tls_prf_sha256, ExporterLabel.master_secret, randomCS, 48);
|
|
||||||
byte[] expanded = masterSecret.deriveUsingPRF(
|
|
||||||
PRFAlgorithm.tls_prf_sha256, ExporterLabel.key_expansion, randomSC, 72 + keyLength * 2).extract();
|
|
||||||
|
|
||||||
byte[] clientMacKey = new byte[20];
|
|
||||||
byte[] serverMacKey = new byte[20];
|
|
||||||
byte[] clientEncryptionKey = new byte[keyLength];
|
|
||||||
byte[] serverEncryptionKey = new byte[keyLength];
|
|
||||||
byte[] clientIV = new byte[16];
|
|
||||||
byte[] serverIV = new byte[16];
|
|
||||||
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(expanded);
|
|
||||||
bb.get(clientMacKey);
|
|
||||||
bb.get(serverMacKey);
|
|
||||||
bb.get(clientEncryptionKey);
|
|
||||||
bb.get(serverEncryptionKey);
|
|
||||||
bb.get(clientIV);
|
|
||||||
bb.get(serverIV);
|
|
||||||
|
|
||||||
Optional<Cipher> clientCipherOpt = createCipher(blockCipherMode, clientEncryptionKey, clientIV);
|
|
||||||
Optional<Cipher> serverCipherOpt = createCipher(blockCipherMode, serverEncryptionKey, serverIV);
|
|
||||||
|
|
||||||
if (clientCipherOpt.isEmpty() || serverCipherOpt.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cipher clientCipher = clientCipherOpt.get();
|
|
||||||
Cipher serverCipher = serverCipherOpt.get();
|
|
||||||
|
|
||||||
result = new ArrayList<>(packets.size());
|
|
||||||
|
|
||||||
for (Packet packet : packets) {
|
|
||||||
List<TlsPacket.TlsHeader> tlsData = tlsPackets.get(packet);
|
|
||||||
|
|
||||||
for (TlsPacket.TlsHeader tlsPacket : tlsData) {
|
|
||||||
if (tlsPacket.getContentType() == ContentType.APPLICATION_DATA) {
|
|
||||||
byte[] data = ((ApplicationDataRecord) tlsPacket.getRecord()).getData();
|
|
||||||
boolean client = packet.isIncoming();
|
|
||||||
|
|
||||||
Cipher cipher = client ? clientCipher : serverCipher;
|
|
||||||
byte[] decoded = cipher.doFinal(data);
|
|
||||||
|
|
||||||
decoded = clearDecodedData(decoded);
|
|
||||||
|
|
||||||
result.add(
|
|
||||||
packet.toBuilder()
|
|
||||||
.content(decoded)
|
|
||||||
.tlsDecrypted(true)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows(value = {NoSuchAlgorithmException.class, NoSuchPaddingException.class})
|
|
||||||
private Optional<BcTlsSecret> getPreMaster(RSAPrivateKey privateKey) {
|
|
||||||
Optional<HandshakeRecordContent> opt = getHandshake(HandshakeType.CLIENT_KEY_EXCHANGE);
|
|
||||||
|
|
||||||
if (opt.isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientKeyExchange = (BasicHandshakeRecordContent) opt.get();
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] encryptedPreMaster = TlsKeyUtils.getClientRsaPreMaster(clientKeyExchange.getContent(), 0);
|
|
||||||
|
|
||||||
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
||||||
rsa.init(Cipher.DECRYPT_MODE, privateKey);
|
|
||||||
byte[] preMaster = rsa.doFinal(encryptedPreMaster);
|
|
||||||
return Optional.of(new BcTlsSecret(new BcTlsCrypto(null), preMaster));
|
|
||||||
} catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
|
|
||||||
log.warn("Failed do get pre-master key", e);
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<RSAPublicKey> getRsaPublicKey() {
|
|
||||||
var certificateHandshakeOpt = getHandshake(HandshakeType.CERTIFICATE);
|
|
||||||
|
|
||||||
if (certificateHandshakeOpt.isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
var certificateHandshake = (CertificateHandshakeRecordContent) certificateHandshakeOpt.get();
|
|
||||||
List<byte[]> chain = certificateHandshake.getRawCertificates();
|
|
||||||
byte[] rawCertificate = chain.get(0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(rawCertificate));
|
|
||||||
RSAPublicKey publicKey = (RSAPublicKey) certificate.getPublicKey();
|
|
||||||
return Optional.of(publicKey);
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
log.warn("Error while getting certificate", e);
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows(value = {NoSuchAlgorithmException.class, NoSuchPaddingException.class})
|
|
||||||
private Optional<Cipher> createCipher(String mode, byte[] key, byte[] iv) {
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
|
|
||||||
SecretKeySpec serverSkeySpec = new SecretKeySpec(key, "AES");
|
|
||||||
IvParameterSpec serverIvParameterSpec = new IvParameterSpec(iv);
|
|
||||||
|
|
||||||
try {
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, serverSkeySpec, serverIvParameterSpec);
|
|
||||||
|
|
||||||
return Optional.of(cipher);
|
|
||||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
|
||||||
log.warn("Error decrypting TLS", e);
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] clearDecodedData(byte[] decoded) {
|
|
||||||
int start = 16;
|
|
||||||
int end = decoded.length - 21; // почему?)
|
|
||||||
decoded = ByteArrays.getSubArray(decoded, start, end - start);
|
|
||||||
return decoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<HandshakeRecordContent> getHandshake(HandshakeType handshakeType) {
|
|
||||||
return tlsPackets.values().stream()
|
|
||||||
.filter(p -> p.getContentType() == ContentType.HANDSHAKE)
|
|
||||||
.map(p -> ((HandshakeRecord) p.getRecord()))
|
|
||||||
.filter(r -> r.getHandshakeType() == handshakeType)
|
|
||||||
.map(HandshakeRecord::getContent)
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TlsPacket.TlsHeader> createTlsHeaders(Packet p) throws IllegalRawDataException {
|
|
||||||
List<TlsPacket.TlsHeader> headers = new ArrayList<>();
|
|
||||||
TlsPacket tlsPacket = TlsPacket.newPacket(p.getContent(), 0, p.getContent().length);
|
|
||||||
|
|
||||||
headers.add(tlsPacket.getHeader());
|
|
||||||
|
|
||||||
while (tlsPacket.getPayload() != null) {
|
|
||||||
tlsPacket = (TlsPacket) tlsPacket.getPayload();
|
|
||||||
headers.add(tlsPacket.getHeader());
|
|
||||||
}
|
|
||||||
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Packet> getParsedPackets() {
|
|
||||||
if (!parsed) {
|
|
||||||
throw new IllegalStateException("TLS is not parsed");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.AbstractPacket;
|
|
||||||
import org.pcap4j.packet.IllegalRawDataException;
|
|
||||||
import org.pcap4j.packet.Packet;
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ContentType;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.TlsVersion;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.records.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES;
|
|
||||||
import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
public class TlsPacket extends AbstractPacket {
|
|
||||||
|
|
||||||
private final TlsPacket.TlsHeader header;
|
|
||||||
private final Packet payload;
|
|
||||||
|
|
||||||
public static TlsPacket newPacket(byte[] rawData, int offset, int length) throws IllegalRawDataException {
|
|
||||||
ByteArrays.validateBounds(rawData, offset, length);
|
|
||||||
return new TlsPacket(rawData, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TlsPacket(byte[] rawData, int offset, int length) throws IllegalRawDataException {
|
|
||||||
this.header = new TlsPacket.TlsHeader(rawData, offset, length);
|
|
||||||
|
|
||||||
int payloadLength = length - header.length();
|
|
||||||
if (payloadLength > 0) {
|
|
||||||
this.payload = TlsPacket.newPacket(rawData, offset + header.length(), payloadLength);
|
|
||||||
} else {
|
|
||||||
this.payload = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TlsPacket(TlsPacket.Builder builder) {
|
|
||||||
if (builder == null) {
|
|
||||||
throw new NullPointerException("builder: null");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.payload = builder.payloadBuilder != null ? builder.payloadBuilder.build() : null;
|
|
||||||
this.header = new TlsPacket.TlsHeader(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TlsHeader getHeader() {
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Packet getPayload() {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder getBuilder() {
|
|
||||||
return new Builder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String buildString() {
|
|
||||||
StringBuilder sb = new StringBuilder(getHeader().toString());
|
|
||||||
|
|
||||||
TlsPacket p = (TlsPacket) getPayload();
|
|
||||||
|
|
||||||
if (p != null) {
|
|
||||||
sb.append('\n');
|
|
||||||
sb.append(p.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class TlsHeader extends AbstractHeader {
|
|
||||||
|
|
||||||
/*
|
|
||||||
0x0 - Content Type
|
|
||||||
0x1 - Version
|
|
||||||
0x3 - Length
|
|
||||||
0x5 - Record content
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static final int CONTENT_TYPE_OFFSET = 0;
|
|
||||||
private static final int VERSION_OFFSET = CONTENT_TYPE_OFFSET + BYTE_SIZE_IN_BYTES;
|
|
||||||
private static final int LENGTH_OFFSET = VERSION_OFFSET + SHORT_SIZE_IN_BYTES;
|
|
||||||
private static final int RECORD_OFFSET = LENGTH_OFFSET + SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
private ContentType contentType;
|
|
||||||
private TlsVersion version;
|
|
||||||
private short recordLength;
|
|
||||||
private TlsRecord record;
|
|
||||||
|
|
||||||
private TlsHeader(Builder builder) {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
private TlsHeader(byte[] rawData, int offset, int length) throws IllegalRawDataException {
|
|
||||||
ByteArrays.validateBounds(rawData, offset, RECORD_OFFSET);
|
|
||||||
this.contentType = ContentType.getInstance(ByteArrays.getByte(rawData, CONTENT_TYPE_OFFSET + offset));
|
|
||||||
this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset));
|
|
||||||
this.recordLength = ByteArrays.getShort(rawData, LENGTH_OFFSET + offset);
|
|
||||||
|
|
||||||
if (contentType == ContentType.HANDSHAKE) {
|
|
||||||
this.record = HandshakeRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength);
|
|
||||||
} else if (contentType == ContentType.CHANGE_CIPHER_SPEC) {
|
|
||||||
this.record = ChangeCipherSpecRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength);
|
|
||||||
} else if (contentType == ContentType.APPLICATION_DATA) {
|
|
||||||
this.record = ApplicationDataRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength);
|
|
||||||
} else if (contentType == ContentType.ALERT) {
|
|
||||||
this.record = AlertRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength);
|
|
||||||
} else if (contentType == ContentType.HEARTBEAT) {
|
|
||||||
this.record = HeartbeatRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown content type: " + contentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContentType getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TlsVersion getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TlsRecord getRecord() {
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<byte[]> getRawFields() {
|
|
||||||
List<byte[]> rawFields = new ArrayList<>();
|
|
||||||
rawFields.add(new byte[]{contentType.value()});
|
|
||||||
rawFields.add(ByteArrays.toByteArray(version.value()));
|
|
||||||
rawFields.add(ByteArrays.toByteArray(recordLength));
|
|
||||||
//TODO
|
|
||||||
return rawFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int length() {
|
|
||||||
return RECORD_OFFSET + recordLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String buildString() {
|
|
||||||
return "TLS Header [" + length() + " bytes]\n" +
|
|
||||||
" Version: " + version + "\n" +
|
|
||||||
" Type: " + contentType + "\n" +
|
|
||||||
record.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends AbstractBuilder {
|
|
||||||
|
|
||||||
private Packet.Builder payloadBuilder;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(TlsPacket packet) {
|
|
||||||
this.payloadBuilder = packet.payload != null ? packet.payload.getBuilder() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Packet build() {
|
|
||||||
return new TlsPacket(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions;
|
|
||||||
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.extensions.keyshare.KeyShareExtension;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType;
|
|
||||||
|
|
||||||
public abstract class TlsExtension {
|
|
||||||
|
|
||||||
/*
|
|
||||||
0x0 - Type
|
|
||||||
0x2 - Length
|
|
||||||
0x4 - Content
|
|
||||||
0x4+length - End
|
|
||||||
*/
|
|
||||||
|
|
||||||
protected ExtensionType type;
|
|
||||||
protected short extensionLength;
|
|
||||||
|
|
||||||
public static TlsExtension newInstance(ExtensionType type, byte[] rawData, int offset,
|
|
||||||
short extensionLength, boolean client) {
|
|
||||||
if (extensionLength > 0) {
|
|
||||||
ByteArrays.validateBounds(rawData, offset, extensionLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == ExtensionType.KEY_SHARE) {
|
|
||||||
return KeyShareExtension.newInstance(type, rawData, offset, extensionLength, client);
|
|
||||||
} else {
|
|
||||||
return new UnimplementedTlsExtension(type, rawData, offset, extensionLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TlsExtension(ExtensionType type, short extensionLength) {
|
|
||||||
this.type = type;
|
|
||||||
this.extensionLength = extensionLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExtensionType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getLength() {
|
|
||||||
return extensionLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return type.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions;
|
|
||||||
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType;
|
|
||||||
|
|
||||||
public class UnimplementedTlsExtension extends TlsExtension {
|
|
||||||
|
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
public UnimplementedTlsExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) {
|
|
||||||
super(type, extensionLength);
|
|
||||||
|
|
||||||
data = new byte[extensionLength];
|
|
||||||
System.arraycopy(rawData, offset, data, 0, extensionLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if(extensionLength > 0) {
|
|
||||||
return type.name() + " [" + extensionLength + " bytes]";
|
|
||||||
} else {
|
|
||||||
return type.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare;
|
|
||||||
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType;
|
|
||||||
|
|
||||||
import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
public class ClientKeyShareExtension extends KeyShareExtension {
|
|
||||||
|
|
||||||
private static final int KEY_SHARE_LENGTH_OFFSET = 0;
|
|
||||||
private static final int KEY_SHARE_ENTRY_OFFSET = KEY_SHARE_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
private short keyShareLength;
|
|
||||||
|
|
||||||
public ClientKeyShareExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) {
|
|
||||||
super(type, extensionLength);
|
|
||||||
this.keyShareLength = ByteArrays.getShort(rawData, KEY_SHARE_LENGTH_OFFSET + offset); // the field is not always there
|
|
||||||
int cursor = KEY_SHARE_ENTRY_OFFSET + offset;
|
|
||||||
ByteArrays.validateBounds(rawData, cursor, keyShareLength);
|
|
||||||
readEntries(rawData, KEY_SHARE_ENTRY_OFFSET + offset, offset + keyShareLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare;
|
|
||||||
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.KeyGroup;
|
|
||||||
|
|
||||||
import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
public class KeyShareEntry {
|
|
||||||
|
|
||||||
private static final int GROUP_OFFSET = 0;
|
|
||||||
private static final int KEY_EXHANGE_LENGTH_OFFSET = GROUP_OFFSET + SHORT_SIZE_IN_BYTES;
|
|
||||||
private static final int KEY_EXCHANGE_OFFSET = KEY_EXHANGE_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
private KeyGroup group;
|
|
||||||
private short keyExhangeLength;
|
|
||||||
private byte[] keyExchange;
|
|
||||||
|
|
||||||
public KeyShareEntry(byte[] rawData, int offset) {
|
|
||||||
this.group = KeyGroup.getInstance(ByteArrays.getShort(rawData, GROUP_OFFSET + offset));
|
|
||||||
this.keyExhangeLength = ByteArrays.getShort(rawData, KEY_EXHANGE_LENGTH_OFFSET + offset);
|
|
||||||
keyExchange = new byte[keyExhangeLength];
|
|
||||||
System.arraycopy(rawData, KEY_EXCHANGE_OFFSET + offset, keyExchange, 0, keyExhangeLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return SHORT_SIZE_IN_BYTES + SHORT_SIZE_IN_BYTES + keyExhangeLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return group.name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare;
|
|
||||||
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.extensions.TlsExtension;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class KeyShareExtension extends TlsExtension {
|
|
||||||
|
|
||||||
private final List<KeyShareEntry> entries = new ArrayList<>();
|
|
||||||
|
|
||||||
public static KeyShareExtension newInstance(ExtensionType type, byte[] rawData, int offset,
|
|
||||||
short extensionLength, boolean client) {
|
|
||||||
ByteArrays.validateBounds(rawData, offset, extensionLength);
|
|
||||||
|
|
||||||
if(client) {
|
|
||||||
return new ClientKeyShareExtension(type, rawData, offset, extensionLength);
|
|
||||||
} else {
|
|
||||||
return new ServerKeyShareExtension(type, rawData, offset, extensionLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected KeyShareExtension(ExtensionType type, short extensionLength) {
|
|
||||||
super(type, extensionLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void readEntries(byte[] rawData, int cursor, int end) {
|
|
||||||
while (cursor < end) {
|
|
||||||
KeyShareEntry entry = readEntry(rawData, cursor);
|
|
||||||
cursor += entry.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected KeyShareEntry readEntry(byte[] rawData, int cursor) {
|
|
||||||
KeyShareEntry entry = new KeyShareEntry(rawData, cursor);
|
|
||||||
entries.add(entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return type.name() + " " + entries.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.extensions.keyshare;
|
|
||||||
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.ExtensionType;
|
|
||||||
|
|
||||||
public class ServerKeyShareExtension extends KeyShareExtension {
|
|
||||||
|
|
||||||
private static final int KEY_SHARE_ENTRY_OFFSET = 0;
|
|
||||||
|
|
||||||
public ServerKeyShareExtension(ExtensionType type, byte[] rawData, int offset, short extensionLength) {
|
|
||||||
super(type, extensionLength);
|
|
||||||
readEntry(rawData, KEY_SHARE_ENTRY_OFFSET + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys;
|
|
||||||
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.SignatureScheme;
|
|
||||||
|
|
||||||
public class DhClientParams {
|
|
||||||
|
|
||||||
private final byte[] p;
|
|
||||||
private final byte[] g;
|
|
||||||
private final byte[] pubkey;
|
|
||||||
private final SignatureScheme signatureScheme;
|
|
||||||
private final byte[] signature;
|
|
||||||
|
|
||||||
public DhClientParams(byte[] p, byte[] g, byte[] pubkey,
|
|
||||||
SignatureScheme signatureScheme,
|
|
||||||
byte[] signature) {
|
|
||||||
this.p = p;
|
|
||||||
this.g = g;
|
|
||||||
this.pubkey = pubkey;
|
|
||||||
this.signatureScheme = signatureScheme;
|
|
||||||
this.signature = signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getP() {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getG() {
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getPubkey() {
|
|
||||||
return pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignatureScheme getSignatureScheme() {
|
|
||||||
return signatureScheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getSignature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys;
|
|
||||||
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.CurveType;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.NamedCurve;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.SignatureScheme;
|
|
||||||
|
|
||||||
public class EcdheServerParams {
|
|
||||||
|
|
||||||
private final CurveType curveType;
|
|
||||||
private final NamedCurve namedCurve;
|
|
||||||
private final byte[] pubkey;
|
|
||||||
private final SignatureScheme signatureScheme;
|
|
||||||
private final byte[] signature;
|
|
||||||
|
|
||||||
public EcdheServerParams(CurveType curveType, NamedCurve namedCurve, byte[] pubkey,
|
|
||||||
SignatureScheme signatureScheme,
|
|
||||||
byte[] signature) {
|
|
||||||
this.curveType = curveType;
|
|
||||||
this.namedCurve = namedCurve;
|
|
||||||
this.pubkey = pubkey;
|
|
||||||
this.signatureScheme = signatureScheme;
|
|
||||||
this.signature = signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CurveType getCurveType() {
|
|
||||||
return curveType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NamedCurve getNamedCurve() {
|
|
||||||
return namedCurve;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getPubkey() {
|
|
||||||
return pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignatureScheme getSignatureScheme() {
|
|
||||||
return signatureScheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getSignature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys;
|
|
||||||
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.CurveType;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.NamedCurve;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.keys.enums.SignatureScheme;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It is impossible to determine key format just by KeyExchange record,
|
|
||||||
* so you can use this class when analyzing tls traffic.
|
|
||||||
*/
|
|
||||||
public final class TlsKeyUtils {
|
|
||||||
|
|
||||||
// https://wiki.osdev.org/TLS_Handshake
|
|
||||||
|
|
||||||
public static DhClientParams parseServerDH(byte[] rawData, int offset) {
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset);
|
|
||||||
|
|
||||||
short pLength = bb.getShort();
|
|
||||||
byte[] p = new byte[pLength];
|
|
||||||
bb.get(p);
|
|
||||||
|
|
||||||
short gLength = bb.getShort();
|
|
||||||
byte[] g = new byte[gLength];
|
|
||||||
bb.get(g);
|
|
||||||
|
|
||||||
short pubKeyLength = bb.getShort();
|
|
||||||
byte[] pubKey = new byte[pubKeyLength]; // aka Ys
|
|
||||||
bb.get(pubKey);
|
|
||||||
|
|
||||||
SignatureScheme signatureScheme = SignatureScheme.findByValue(bb.getShort());
|
|
||||||
|
|
||||||
if (signatureScheme == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown signature scheme");
|
|
||||||
}
|
|
||||||
|
|
||||||
short signatureLength = bb.getShort();
|
|
||||||
byte[] signature = new byte[signatureLength];
|
|
||||||
|
|
||||||
bb.get(signature);
|
|
||||||
|
|
||||||
return new DhClientParams(p, g, pubKey, signatureScheme, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param rawData Handshake record content
|
|
||||||
*/
|
|
||||||
public static EcdheServerParams parseServerECDHE(byte[] rawData, int offset) {
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset);
|
|
||||||
|
|
||||||
byte curveTypeId = bb.get();
|
|
||||||
if(curveTypeId != 0x03) {
|
|
||||||
throw new IllegalArgumentException("Unsupported curve type");
|
|
||||||
}
|
|
||||||
|
|
||||||
CurveType curveType = CurveType.NAMED;
|
|
||||||
NamedCurve namedCurve = NamedCurve.findByValue(bb.getShort());
|
|
||||||
|
|
||||||
if (namedCurve == null) {
|
|
||||||
throw new IllegalArgumentException("Unsupported named curve");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte pubkeyLength = bb.get();
|
|
||||||
byte[] pubkey = new byte[pubkeyLength];
|
|
||||||
bb.get(pubkey);
|
|
||||||
|
|
||||||
SignatureScheme signatureScheme = SignatureScheme.findByValue(bb.getShort());
|
|
||||||
|
|
||||||
if (signatureScheme == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown signature scheme");
|
|
||||||
}
|
|
||||||
|
|
||||||
short signatureLength = bb.getShort();
|
|
||||||
byte[] signature = new byte[signatureLength];
|
|
||||||
|
|
||||||
bb.get(signature);
|
|
||||||
|
|
||||||
return new EcdheServerParams(curveType, namedCurve, pubkey, signatureScheme, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://ldapwiki.com/wiki/ClientKeyExchange
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suitable for both DH and ECDHE
|
|
||||||
* @param rawData Handshake record content
|
|
||||||
*/
|
|
||||||
public static byte[] getClientDHPubkey(byte[] rawData, int offset) {
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset);
|
|
||||||
|
|
||||||
byte length = bb.get();
|
|
||||||
byte[] pubkey = new byte[length];
|
|
||||||
bb.get(pubkey);
|
|
||||||
|
|
||||||
return pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getClientRsaPreMaster(byte[] rawData, int offset) {
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(rawData).position(offset);
|
|
||||||
|
|
||||||
int length = bb.getShort();
|
|
||||||
byte[] encryptedPreMaster = new byte[length];
|
|
||||||
bb.get(encryptedPreMaster);
|
|
||||||
|
|
||||||
return encryptedPreMaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys.enums;
|
|
||||||
|
|
||||||
public enum CurveType {
|
|
||||||
|
|
||||||
NAMED((byte) 0x03);
|
|
||||||
|
|
||||||
private final byte value;
|
|
||||||
|
|
||||||
CurveType(byte value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys.enums;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum NamedCurve {
|
|
||||||
|
|
||||||
SECT163K1((short) 1),
|
|
||||||
SECT163R1((short) 2),
|
|
||||||
SECT163R2((short) 3),
|
|
||||||
SECT193R1((short) 4),
|
|
||||||
SECT193R2((short) 5),
|
|
||||||
SECT233K1((short) 6),
|
|
||||||
SECT233R1((short) 7),
|
|
||||||
SECT239K1((short) 8),
|
|
||||||
SECT283K1((short) 9),
|
|
||||||
SECT283R1((short) 10),
|
|
||||||
SECT409K1((short) 11),
|
|
||||||
SECT409R1((short) 12),
|
|
||||||
SECT571K1((short) 13),
|
|
||||||
SECT571R1((short) 14),
|
|
||||||
SECP160K1((short) 15),
|
|
||||||
SECP160R1((short) 16),
|
|
||||||
SECP160R2((short) 17),
|
|
||||||
SECP192K1((short) 18),
|
|
||||||
SECP192R1((short) 19),
|
|
||||||
SECP224K1((short) 20),
|
|
||||||
SECP224R1((short) 21),
|
|
||||||
SECP256K1((short) 22),
|
|
||||||
SECP256R1((short) 23),
|
|
||||||
SECP384R1((short) 24),
|
|
||||||
SECP521R1((short) 25),
|
|
||||||
X25519((short) 29),
|
|
||||||
X448((short) 30);
|
|
||||||
|
|
||||||
private final short value;
|
|
||||||
|
|
||||||
private static final Map<Short, NamedCurve> map = new HashMap<>();
|
|
||||||
|
|
||||||
NamedCurve(short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (NamedCurve curve : values()) {
|
|
||||||
map.put(curve.getValue(), curve);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NamedCurve findByValue(short value) {
|
|
||||||
return map.get(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.keys.enums;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum SignatureScheme {
|
|
||||||
|
|
||||||
/* RSASSA-PKCS1-v1_5 algorithms */
|
|
||||||
RSA_PKCS1_SHA256((short) 0x0401),
|
|
||||||
RSA_PKCS1_SHA384((short) 0x0501),
|
|
||||||
RSA_PKCS1_SHA512((short) 0x0601),
|
|
||||||
|
|
||||||
/* ECDSA algorithms */
|
|
||||||
ECDSA_SECP256R1_SHA256((short) 0x0403),
|
|
||||||
ECDSA_SECP384R1_SHA384((short) 0x0503),
|
|
||||||
ECDSA_SECP521R1_SHA512((short) 0x0603),
|
|
||||||
|
|
||||||
/* RSASSA-PSS algorithms with public key OID RSAEncryption */
|
|
||||||
RSA_PSS_RSAE_SHA256((short) 0x0804),
|
|
||||||
RSA_PSS_RSAE_SHA384((short) 0x0805),
|
|
||||||
RSA_PSS_RSAE_SHA512((short) 0x0806),
|
|
||||||
|
|
||||||
/* EDDSA algorithms */
|
|
||||||
ED25519((short) 0x0807),
|
|
||||||
ED448((short) 0x0808),
|
|
||||||
|
|
||||||
/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
|
|
||||||
RSA_PSS_PSS_SHA256((short) 0x0809),
|
|
||||||
RSA_PSS_PSS_SHA384((short) 0x080a),
|
|
||||||
RSA_PSS_PSS_SHA512((short) 0x080b),
|
|
||||||
|
|
||||||
/* Legacy algorithms */
|
|
||||||
RSA_PKCS1_SHA1((short) 0x0201),
|
|
||||||
ECDSA_SHA1((short) 0x0203);
|
|
||||||
|
|
||||||
private final short value;
|
|
||||||
|
|
||||||
private static final Map<Short, SignatureScheme> map = new HashMap<>();
|
|
||||||
|
|
||||||
SignatureScheme(short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (SignatureScheme curve : values()) {
|
|
||||||
map.put(curve.getValue(), curve);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureScheme findByValue(short value) {
|
|
||||||
return map.get(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class AlertDescription extends NamedNumber<Byte, AlertDescription> {
|
|
||||||
|
|
||||||
private static final Map<Byte, AlertDescription> registry = new HashMap<>();
|
|
||||||
|
|
||||||
public static AlertDescription close_notify = new AlertDescription((byte) 0, "close_notify");
|
|
||||||
public static AlertDescription unexpected_message = new AlertDescription((byte) 10, "unexpected_message");
|
|
||||||
public static AlertDescription bad_record_mac = new AlertDescription((byte) 20, "bad_record_mac");
|
|
||||||
public static AlertDescription decryption_failed_RESERVED = new AlertDescription((byte) 21, "decryption_failed_RESERVED");
|
|
||||||
public static AlertDescription record_overflow = new AlertDescription((byte) 22, "record_overflow");
|
|
||||||
public static AlertDescription decompression_failure_RESERVED = new AlertDescription((byte) 30, "decompression_failure_RESERVED");
|
|
||||||
public static AlertDescription handshake_failure = new AlertDescription((byte) 40, "handshake_failure");
|
|
||||||
public static AlertDescription no_certificate_RESERVED = new AlertDescription((byte) 41, "no_certificate_RESERVED");
|
|
||||||
public static AlertDescription bad_certificate = new AlertDescription((byte) 42, "bad_certificate");
|
|
||||||
public static AlertDescription unsupported_certificate = new AlertDescription((byte) 43, "unsupported_certificate");
|
|
||||||
public static AlertDescription certificate_revoked = new AlertDescription((byte) 44, "certificate_revoked");
|
|
||||||
public static AlertDescription certificate_expired = new AlertDescription((byte) 45, "certificate_expired");
|
|
||||||
public static AlertDescription certificate_unknown = new AlertDescription((byte) 46, "certificate_unknown");
|
|
||||||
public static AlertDescription illegal_parameter = new AlertDescription((byte) 47, "illegal_parameter");
|
|
||||||
public static AlertDescription unknown_ca = new AlertDescription((byte) 48, "unknown_ca");
|
|
||||||
public static AlertDescription access_denied = new AlertDescription((byte) 49, "access_denied");
|
|
||||||
public static AlertDescription decode_error = new AlertDescription((byte) 50, "decode_error");
|
|
||||||
public static AlertDescription decrypt_error = new AlertDescription((byte) 51, "decrypt_error");
|
|
||||||
public static AlertDescription export_restriction_RESERVED = new AlertDescription((byte) 60, "export_restriction_RESERVED");
|
|
||||||
public static AlertDescription protocol_version = new AlertDescription((byte) 70, "protocol_version");
|
|
||||||
public static AlertDescription insufficient_security = new AlertDescription((byte) 71, "insufficient_security");
|
|
||||||
public static AlertDescription internal_error = new AlertDescription((byte) 80, "internal_error");
|
|
||||||
public static AlertDescription inappropriate_fallback = new AlertDescription((byte) 86, "inappropriate_fallback");
|
|
||||||
public static AlertDescription user_canceled = new AlertDescription((byte) 90, "user_canceled");
|
|
||||||
public static AlertDescription no_renegotiation_RESERVED = new AlertDescription((byte) 100, "no_renegotiation_RESERVED");
|
|
||||||
public static AlertDescription missing_extension = new AlertDescription((byte) 109, "missing_extension");
|
|
||||||
public static AlertDescription unsupported_extension = new AlertDescription((byte) 110, "unsupported_extension");
|
|
||||||
public static AlertDescription certificate_unobtainable_RESERVED = new AlertDescription((byte) 111, "certificate_unobtainable_RESERVED");
|
|
||||||
public static AlertDescription unrecognized_name = new AlertDescription((byte) 112, "unrecognized_name");
|
|
||||||
public static AlertDescription bad_certificate_status_response = new AlertDescription((byte) 113, "bad_certificate_status_response");
|
|
||||||
public static AlertDescription bad_certificate_hash_value_RESERVED = new AlertDescription((byte) 114, "bad_certificate_hash_value_RESERVED");
|
|
||||||
public static AlertDescription unknown_psk_identity = new AlertDescription((byte) 115, "unknown_psk_identity");
|
|
||||||
public static AlertDescription certificate_required = new AlertDescription((byte) 116, "certificate_required");
|
|
||||||
public static AlertDescription no_application_protocol = new AlertDescription((byte) 120, "no_application_protocol");
|
|
||||||
|
|
||||||
public AlertDescription(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDescription getInstance(Byte value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown alert description: " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(AlertDescription o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class AlertLevel extends NamedNumber<Byte, AlertLevel> {
|
|
||||||
|
|
||||||
private static final Map<Byte, AlertLevel> registry = new HashMap<>();
|
|
||||||
|
|
||||||
public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning");
|
|
||||||
public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal");
|
|
||||||
|
|
||||||
public static final AlertLevel ENCRYPTED_ALERT = new AlertLevel((byte) 0, "encrypted alert");
|
|
||||||
|
|
||||||
public AlertLevel(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertLevel getInstance(Byte value) {
|
|
||||||
return registry.getOrDefault(value, ENCRYPTED_ALERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(AlertLevel o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,741 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class CipherSuite extends NamedNumber<Short, CipherSuite> {
|
|
||||||
|
|
||||||
private static final Map<Short, CipherSuite> registry = new HashMap<>();
|
|
||||||
|
|
||||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
|
||||||
|
|
||||||
public static final CipherSuite TLS_NULL_WITH_NULL_NULL =
|
|
||||||
new CipherSuite((short) 0x0000, "TLS_NULL_WITH_NULL_NULL");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_NULL_MD5 =
|
|
||||||
new CipherSuite((short) 0x0001, "TLS_RSA_WITH_NULL_MD5");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0x0002, "TLS_RSA_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 =
|
|
||||||
new CipherSuite((short) 0x0004, "TLS_RSA_WITH_RC4_128_MD5");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0x0005, "TLS_RSA_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0009, "TLS_RSA_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 =
|
|
||||||
new CipherSuite((short) 0x0018, "TLS_DH_anon_WITH_RC4_128_MD5");
|
|
||||||
public static final CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_DES_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x001E, "TLS_KRB5_WITH_DES_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0x0020, "TLS_KRB5_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_IDEA_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_DES_CBC_MD5 =
|
|
||||||
new CipherSuite((short) 0x0022, "TLS_KRB5_WITH_DES_CBC_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_MD5 =
|
|
||||||
new CipherSuite((short) 0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_RC4_128_MD5 =
|
|
||||||
new CipherSuite((short) 0x0024, "TLS_KRB5_WITH_RC4_128_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_WITH_IDEA_CBC_MD5 =
|
|
||||||
new CipherSuite((short) 0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA =
|
|
||||||
new CipherSuite((short) 0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA =
|
|
||||||
new CipherSuite((short) 0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_SHA =
|
|
||||||
new CipherSuite((short) 0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5");
|
|
||||||
public static final CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_MD5 =
|
|
||||||
new CipherSuite((short) 0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0x002C, "TLS_PSK_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0x002D, "TLS_DHE_PSK_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0x002E, "TLS_RSA_PSK_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_NULL_SHA256 =
|
|
||||||
new CipherSuite((short) 0x003B, "TLS_RSA_WITH_NULL_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0x008A, "TLS_PSK_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0096, "TLS_RSA_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_SEED_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_NULL_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00B0, "TLS_PSK_WITH_NULL_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_NULL_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00B1, "TLS_PSK_WITH_NULL_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_NULL_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_NULL_SHA384 =
|
|
||||||
new CipherSuite((short) 0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV =
|
|
||||||
new CipherSuite((short) 0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x0A0A =
|
|
||||||
new CipherSuite((short) 0x0A0A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite TLS_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x1301, "TLS_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0x1302, "TLS_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0x1303, "TLS_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_AES_128_CCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0x1304, "TLS_AES_128_CCM_SHA256");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x1A1A =
|
|
||||||
new CipherSuite((short) 0x1A1A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x2A2A =
|
|
||||||
new CipherSuite((short) 0x2A2A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x3A3A =
|
|
||||||
new CipherSuite((short) 0x3A3A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x4A4A =
|
|
||||||
new CipherSuite((short) 0x4A4A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite TLS_FALLBACK_SCSV =
|
|
||||||
new CipherSuite((short) 0x5600, "TLS_FALLBACK_SCSV");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x5A5A =
|
|
||||||
new CipherSuite((short) 0x5A5A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x6A6A =
|
|
||||||
new CipherSuite((short) 0x6A6A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x7A7A =
|
|
||||||
new CipherSuite((short) 0x7A7A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x8A8A =
|
|
||||||
new CipherSuite((short) 0x8A8A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0x9A9A =
|
|
||||||
new CipherSuite((short) 0x9A9A, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xAAAA =
|
|
||||||
new CipherSuite((short) 0xAAAA, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xBABA =
|
|
||||||
new CipherSuite((short) 0xBABA, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_anon_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC015, "TLS_ECDH_anon_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_anon_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_anon_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDH_anon_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_RC4_128_SHA =
|
|
||||||
new CipherSuite((short) 0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA =
|
|
||||||
new CipherSuite((short) 0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA =
|
|
||||||
new CipherSuite((short) 0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_NULL_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_128_CCM =
|
|
||||||
new CipherSuite((short) 0xC09C, "TLS_RSA_WITH_AES_128_CCM");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_256_CCM =
|
|
||||||
new CipherSuite((short) 0xC09D, "TLS_RSA_WITH_AES_256_CCM");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CCM =
|
|
||||||
new CipherSuite((short) 0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CCM =
|
|
||||||
new CipherSuite((short) 0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_128_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8");
|
|
||||||
public static final CipherSuite TLS_RSA_WITH_AES_256_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_128_CCM =
|
|
||||||
new CipherSuite((short) 0xC0A4, "TLS_PSK_WITH_AES_128_CCM");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_256_CCM =
|
|
||||||
new CipherSuite((short) 0xC0A5, "TLS_PSK_WITH_AES_256_CCM");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CCM =
|
|
||||||
new CipherSuite((short) 0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CCM =
|
|
||||||
new CipherSuite((short) 0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_128_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_AES_256_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8");
|
|
||||||
public static final CipherSuite TLS_PSK_DHE_WITH_AES_128_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8");
|
|
||||||
public static final CipherSuite TLS_PSK_DHE_WITH_AES_256_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CCM =
|
|
||||||
new CipherSuite((short) 0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CCM =
|
|
||||||
new CipherSuite((short) 0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 =
|
|
||||||
new CipherSuite((short) 0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8");
|
|
||||||
public static final CipherSuite TLS_ECCPWD_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC0B0, "TLS_ECCPWD_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECCPWD_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC0B1, "TLS_ECCPWD_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECCPWD_WITH_AES_128_CCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xC0B2, "TLS_ECCPWD_WITH_AES_128_CCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECCPWD_WITH_AES_256_CCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xC0B3, "TLS_ECCPWD_WITH_AES_256_CCM_SHA384");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xCACA =
|
|
||||||
new CipherSuite((short) 0xCACA, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 =
|
|
||||||
new CipherSuite((short) 0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xD001, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 =
|
|
||||||
new CipherSuite((short) 0xD002, "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 =
|
|
||||||
new CipherSuite((short) 0xD003, "TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256");
|
|
||||||
public static final CipherSuite TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 =
|
|
||||||
new CipherSuite((short) 0xD005, "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xDADA =
|
|
||||||
new CipherSuite((short) 0xDADA, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xEAEA =
|
|
||||||
new CipherSuite((short) 0xEAEA, "Reserved (GREASE)");
|
|
||||||
public static final CipherSuite RESERVED_GREASE_0xFAFA =
|
|
||||||
new CipherSuite((short) 0xFAFA, "Reserved (GREASE)");
|
|
||||||
|
|
||||||
public CipherSuite(Short value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CipherSuite getInstance(Short value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown cipher suite: " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(CipherSuite o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class CompressionMethod extends NamedNumber<Byte, CompressionMethod> {
|
|
||||||
|
|
||||||
// https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml
|
|
||||||
|
|
||||||
public static final CompressionMethod NULL = new CompressionMethod((byte) 0, "null");
|
|
||||||
public static final CompressionMethod DEFLATE = new CompressionMethod((byte) 1, "Deflate");
|
|
||||||
public static final CompressionMethod LZS = new CompressionMethod((byte) 64, "LZS");
|
|
||||||
|
|
||||||
private static final Map<Byte, CompressionMethod> registry = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
registry.put(NULL.value(), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompressionMethod(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CompressionMethod getInstance(Byte value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
return new CompressionMethod(value, "Unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(CompressionMethod o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class ContentType extends NamedNumber<Byte, ContentType> {
|
|
||||||
|
|
||||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
|
||||||
|
|
||||||
public static final ContentType CHANGE_CIPHER_SPEC = new ContentType((byte) 20, "Change Cipher Spec");
|
|
||||||
public static final ContentType ALERT = new ContentType((byte) 21, "Alert");
|
|
||||||
public static final ContentType HANDSHAKE = new ContentType((byte) 22, "Handshake");
|
|
||||||
public static final ContentType APPLICATION_DATA = new ContentType((byte) 23, "Application Data");
|
|
||||||
public static final ContentType HEARTBEAT = new ContentType((byte) 24, "Heartbeat");
|
|
||||||
|
|
||||||
private static final Map<Byte, ContentType> registry = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
registry.put(CHANGE_CIPHER_SPEC.value(), CHANGE_CIPHER_SPEC);
|
|
||||||
registry.put(ALERT.value(), ALERT);
|
|
||||||
registry.put(HANDSHAKE.value(), HANDSHAKE);
|
|
||||||
registry.put(APPLICATION_DATA.value(), APPLICATION_DATA);
|
|
||||||
registry.put(HEARTBEAT.value(), HEARTBEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContentType(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ContentType getInstance(Byte value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown record type " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ContentType o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ExtensionType extends NamedNumber<Short, ExtensionType> {
|
|
||||||
|
|
||||||
private static final Map<Short, ExtensionType> registry = new HashMap<>();
|
|
||||||
|
|
||||||
public static final ExtensionType SERVER_NAME = new ExtensionType((short) 0, "server_name");
|
|
||||||
public static final ExtensionType MAX_FRAGMENT_LENGTH = new ExtensionType((short) 1, "max_fragment_length");
|
|
||||||
public static final ExtensionType CLIENT_CERTIFICATE_URL = new ExtensionType((short) 2, "client_certificate_url");
|
|
||||||
public static final ExtensionType TRUSTED_CA_KEYS = new ExtensionType((short) 3, "trusted_ca_keys");
|
|
||||||
public static final ExtensionType TRUNCATED_HMAC = new ExtensionType((short) 4, "truncated_hmac");
|
|
||||||
public static final ExtensionType STATUS_REQUEST = new ExtensionType((short) 5, "status_request");
|
|
||||||
public static final ExtensionType USER_MAPPING = new ExtensionType((short) 6, "user_mapping");
|
|
||||||
public static final ExtensionType CLIENT_AUTHZ = new ExtensionType((short) 7, "client_authz");
|
|
||||||
public static final ExtensionType SERVER_AUTHZ = new ExtensionType((short) 8, "server_authz");
|
|
||||||
public static final ExtensionType CERT_TYPE = new ExtensionType((short) 9, "cert_type");
|
|
||||||
public static final ExtensionType SUPPORTED_GROUPS = new ExtensionType((short) 10, "supported_groups");
|
|
||||||
public static final ExtensionType EC_POINT_FORMATS = new ExtensionType((short) 11, "ec_point_formats");
|
|
||||||
public static final ExtensionType SRP = new ExtensionType((short) 12, "srp");
|
|
||||||
public static final ExtensionType SIGNATURE_ALGORITHMS = new ExtensionType((short) 13, "signature_algorithms");
|
|
||||||
public static final ExtensionType USE_SRTP = new ExtensionType((short) 14, "use_srtp");
|
|
||||||
public static final ExtensionType HEARTBEAT = new ExtensionType((short) 15, "heartbeat");
|
|
||||||
public static final ExtensionType APPLICATION_LAYER_PROTOCOL_NEGOTIATION = new ExtensionType((short) 16, "application_layer_protocol_negotiation");
|
|
||||||
public static final ExtensionType STATUS_REQUEST_V2 = new ExtensionType((short) 17, "status_request_v2");
|
|
||||||
public static final ExtensionType SIGNED_CERTIFICATE_TIMESTAMP = new ExtensionType((short) 18, "signed_certificate_timestamp");
|
|
||||||
public static final ExtensionType CLIENT_CERTIFICATE_TYPE = new ExtensionType((short) 19, "client_certificate_type");
|
|
||||||
public static final ExtensionType SERVER_CERTIFICATE_TYPE = new ExtensionType((short) 20, "server_certificate_type");
|
|
||||||
public static final ExtensionType PADDING = new ExtensionType((short) 21, "padding");
|
|
||||||
public static final ExtensionType ENCRYPT_THEN_MAC = new ExtensionType((short) 22, "encrypt_then_mac");
|
|
||||||
public static final ExtensionType EXTENDED_MASTER_SECRET = new ExtensionType((short) 23, "extended_master_secret");
|
|
||||||
public static final ExtensionType TOKEN_BINDING = new ExtensionType((short) 24, "token_binding");
|
|
||||||
public static final ExtensionType CACHED_INFO = new ExtensionType((short) 25, "cached_info");
|
|
||||||
public static final ExtensionType TLS_LTS = new ExtensionType((short) 26, "tls_lts");
|
|
||||||
public static final ExtensionType COMPRESS_CERTIFICATE = new ExtensionType((short) 27, "compress_certificate");
|
|
||||||
public static final ExtensionType RECORD_SIZE_LIMIT = new ExtensionType((short) 28, "record_size_limit");
|
|
||||||
public static final ExtensionType PWD_PROTECT = new ExtensionType((short) 29, "pwd_protect");
|
|
||||||
public static final ExtensionType PWD_CLEAR = new ExtensionType((short) 30, "pwd_clear");
|
|
||||||
public static final ExtensionType PASSWORD_SALT = new ExtensionType((short) 31, "password_salt");
|
|
||||||
public static final ExtensionType TICKET_PINNING = new ExtensionType((short) 32, "ticket_pinning");
|
|
||||||
public static final ExtensionType TLS_CERT_WITH_EXTERN_PSK = new ExtensionType((short) 33, "tls_cert_with_extern_psk");
|
|
||||||
public static final ExtensionType DELEGATED_CREDENTIALS = new ExtensionType((short) 34, "delegated_credentials");
|
|
||||||
public static final ExtensionType SESSION_TICKET = new ExtensionType((short) 35, "session_ticket");
|
|
||||||
public static final ExtensionType PRE_SHARED_KEY = new ExtensionType((short) 41, "pre_shared_key");
|
|
||||||
public static final ExtensionType EARLY_DATA = new ExtensionType((short) 42, "early_data");
|
|
||||||
public static final ExtensionType SUPPORTED_VERSIONS = new ExtensionType((short) 43, "supported_versions");
|
|
||||||
public static final ExtensionType COOKIE = new ExtensionType((short) 44, "cookie");
|
|
||||||
public static final ExtensionType PSK_KEY_EXCHANGE_MODES = new ExtensionType((short) 45, "psk_key_exchange_modes");
|
|
||||||
public static final ExtensionType CERTIFICATE_AUTHORITIES = new ExtensionType((short) 47, "certificate_authorities");
|
|
||||||
public static final ExtensionType OID_FILTERS = new ExtensionType((short) 48, "oid_filters");
|
|
||||||
public static final ExtensionType POST_HANDSHAKE_AUTH = new ExtensionType((short) 49, "post_handshake_auth");
|
|
||||||
public static final ExtensionType SIGNATURE_ALGORITHMS_CERT = new ExtensionType((short) 50, "signature_algorithms_cert");
|
|
||||||
public static final ExtensionType KEY_SHARE = new ExtensionType((short) 51, "key_share");
|
|
||||||
public static final ExtensionType TRANSPARENCY_INFO = new ExtensionType((short) 52, "transparency_info");
|
|
||||||
public static final ExtensionType CONNECTION_ID = new ExtensionType((short) 53, "connection_id");
|
|
||||||
public static final ExtensionType EXTERNAL_ID_HASH = new ExtensionType((short) 55, "external_id_hash");
|
|
||||||
public static final ExtensionType EXTERNAL_SESSION_ID = new ExtensionType((short) 56, "external_session_id");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_2570 = new ExtensionType((short) 2570, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_6682 = new ExtensionType((short) 6682, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_10794 = new ExtensionType((short) 10794, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_14906 = new ExtensionType((short) 14906, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_19018 = new ExtensionType((short) 19018, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_23130 = new ExtensionType((short) 23130, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_27242 = new ExtensionType((short) 27242, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_31354 = new ExtensionType((short) 31354, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_35466 = new ExtensionType((short) 35466, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_39578 = new ExtensionType((short) 39578, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_43690 = new ExtensionType((short) 43690, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_47802 = new ExtensionType((short) 47802, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_51914 = new ExtensionType((short) 51914, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_56026 = new ExtensionType((short) 56026, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_60138 = new ExtensionType((short) 60138, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RESERVED_GREASE_64250 = new ExtensionType((short) 64250, "Reserved (GREASE)");
|
|
||||||
public static final ExtensionType RENEGOTIATION_INFO = new ExtensionType((short) 65281, "renegotiation_info");
|
|
||||||
|
|
||||||
public ExtensionType(Short value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ExtensionType getInstance(Short value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
return new ExtensionType(value, "Unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ExtensionType o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class HandshakeType extends NamedNumber<Byte, HandshakeType> {
|
|
||||||
|
|
||||||
private static final Map<Byte, HandshakeType> registry = new HashMap<>();
|
|
||||||
|
|
||||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
|
||||||
|
|
||||||
public static final HandshakeType HELLO_REQUEST = new HandshakeType((byte) 0, "Hello Request");
|
|
||||||
public static final HandshakeType CLIENT_HELLO = new HandshakeType((byte) 1, "Client Hello");
|
|
||||||
public static final HandshakeType SERVER_HELLO = new HandshakeType((byte) 2, "Server Hello");
|
|
||||||
public static final HandshakeType HELLO_VERIFY_REQUEST = new HandshakeType((byte) 3, "Hello Verify Request");
|
|
||||||
public static final HandshakeType NEW_SESSION_TICKET = new HandshakeType((byte) 4, "New Session Ticket");
|
|
||||||
public static final HandshakeType END_OF_EARLY_DATA = new HandshakeType((byte) 5, "End Of Early Data");
|
|
||||||
public static final HandshakeType HELLO_RETRY_REQUEST = new HandshakeType((byte) 6, "Hello Retry Request");
|
|
||||||
public static final HandshakeType ENCRYPTED_EXTENSIONS = new HandshakeType((byte) 8, "Encrypted Extensions");
|
|
||||||
public static final HandshakeType CERTIFICATE = new HandshakeType((byte) 11, "Certificate");
|
|
||||||
public static final HandshakeType SERVER_KEY_EXCHANGE = new HandshakeType((byte) 12, "Server Key Excange");
|
|
||||||
public static final HandshakeType CERTIFICATE_REQUEST = new HandshakeType((byte) 13, "Certificate Request");
|
|
||||||
public static final HandshakeType SERVER_HELLO_DONE = new HandshakeType((byte) 14, "Server Hello Done");
|
|
||||||
public static final HandshakeType CERTIFICATE_VERIFY = new HandshakeType((byte) 15, "Certificate Verify");
|
|
||||||
public static final HandshakeType CLIENT_KEY_EXCHANGE = new HandshakeType((byte) 16, "Client Key Exchange");
|
|
||||||
public static final HandshakeType FINISHED = new HandshakeType((byte) 20, "Finished");
|
|
||||||
public static final HandshakeType CERTIFICATE_URL = new HandshakeType((byte) 21, "Certificate URL");
|
|
||||||
public static final HandshakeType CERTIFICATE_STATUS = new HandshakeType((byte) 22, "Certificate Status");
|
|
||||||
public static final HandshakeType SUPPLEMENTAL_DATA = new HandshakeType((byte) 23, "Supplemental Data");
|
|
||||||
public static final HandshakeType KEY_UPDATE = new HandshakeType((byte) 24, "Key Update");
|
|
||||||
public static final HandshakeType COMPRESSED_CERTIFICATE = new HandshakeType((byte) 25, "Compressed Certificate");
|
|
||||||
public static final HandshakeType MESSAGE_HASH = new HandshakeType((byte) 254, "Message Hash");
|
|
||||||
|
|
||||||
public static final HandshakeType ENCRYPTED_HANDSHAKE_MESSAGE = new HandshakeType((byte) 255, "Encrypted Handshake Message");
|
|
||||||
|
|
||||||
public HandshakeType(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HandshakeType getInstance(Byte value) {
|
|
||||||
return registry.getOrDefault(value, ENCRYPTED_HANDSHAKE_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(HandshakeType o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class HeartbeatMessageType extends NamedNumber<Byte, HeartbeatMessageType> {
|
|
||||||
|
|
||||||
private static final Map<Byte, HeartbeatMessageType> registry = new HashMap<>();
|
|
||||||
|
|
||||||
public static final HeartbeatMessageType HEARTBEAT_REQUEST = new HeartbeatMessageType((byte) 1, "heartbeat_request");
|
|
||||||
public static final HeartbeatMessageType HEARTBEAT_RESPONSE = new HeartbeatMessageType((byte) 2, "heartbeat_response");
|
|
||||||
|
|
||||||
public HeartbeatMessageType(Byte value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HeartbeatMessageType getInstance(Byte value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown heartbeat message type: " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(HeartbeatMessageType o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class KeyGroup extends NamedNumber<Short, KeyGroup> {
|
|
||||||
|
|
||||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
|
||||||
|
|
||||||
private static final Map<Short, KeyGroup> registry = new HashMap<>();
|
|
||||||
|
|
||||||
public static final KeyGroup RESERVED_GREASE_0 = new KeyGroup((short) 0, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup SECT163K1 = new KeyGroup((short) 1, "sect163k1");
|
|
||||||
public static final KeyGroup SECT163R1 = new KeyGroup((short) 2, "sect163r1");
|
|
||||||
public static final KeyGroup SECT163R2 = new KeyGroup((short) 3, "sect163r2");
|
|
||||||
public static final KeyGroup SECT193R1 = new KeyGroup((short) 4, "sect193r1");
|
|
||||||
public static final KeyGroup SECT193R2 = new KeyGroup((short) 5, "sect193r2");
|
|
||||||
public static final KeyGroup SECT233K1 = new KeyGroup((short) 6, "sect233k1");
|
|
||||||
public static final KeyGroup SECT233R1 = new KeyGroup((short) 7, "sect233r1");
|
|
||||||
public static final KeyGroup SECT239K1 = new KeyGroup((short) 8, "sect239k1");
|
|
||||||
public static final KeyGroup SECT283K1 = new KeyGroup((short) 9, "sect283k1");
|
|
||||||
public static final KeyGroup SECT283R1 = new KeyGroup((short) 10, "sect283r1");
|
|
||||||
public static final KeyGroup SECT409K1 = new KeyGroup((short) 11, "sect409k1");
|
|
||||||
public static final KeyGroup SECT409R1 = new KeyGroup((short) 12, "sect409r1");
|
|
||||||
public static final KeyGroup SECT571K1 = new KeyGroup((short) 13, "sect571k1");
|
|
||||||
public static final KeyGroup SECT571R1 = new KeyGroup((short) 14, "sect571r1");
|
|
||||||
public static final KeyGroup SECP160K1 = new KeyGroup((short) 15, "secp160k1");
|
|
||||||
public static final KeyGroup SECP160R1 = new KeyGroup((short) 16, "secp160r1");
|
|
||||||
public static final KeyGroup SECP160R2 = new KeyGroup((short) 17, "secp160r2");
|
|
||||||
public static final KeyGroup SECP192K1 = new KeyGroup((short) 18, "secp192k1");
|
|
||||||
public static final KeyGroup SECP192R1 = new KeyGroup((short) 19, "secp192r1");
|
|
||||||
public static final KeyGroup SECP224K1 = new KeyGroup((short) 20, "secp224k1");
|
|
||||||
public static final KeyGroup SECP224R1 = new KeyGroup((short) 21, "secp224r1");
|
|
||||||
public static final KeyGroup SECP256K1 = new KeyGroup((short) 22, "secp256k1");
|
|
||||||
public static final KeyGroup SECP256R1 = new KeyGroup((short) 23, "secp256r1");
|
|
||||||
public static final KeyGroup SECP384R1 = new KeyGroup((short) 24, "secp384r1");
|
|
||||||
public static final KeyGroup SECP521R1 = new KeyGroup((short) 25, "secp521r1");
|
|
||||||
public static final KeyGroup BRAINPOOLP256R1 = new KeyGroup((short) 26, "brainpoolP256r1");
|
|
||||||
public static final KeyGroup BRAINPOOLP384R1 = new KeyGroup((short) 27, "brainpoolP384r1");
|
|
||||||
public static final KeyGroup BRAINPOOLP512R1 = new KeyGroup((short) 28, "brainpoolP512r1");
|
|
||||||
public static final KeyGroup X25519 = new KeyGroup((short) 29, "x25519");
|
|
||||||
public static final KeyGroup X448 = new KeyGroup((short) 30, "x448");
|
|
||||||
public static final KeyGroup BRAINPOOLP256R1TLS13 = new KeyGroup((short) 31, "brainpoolP256r1tls13");
|
|
||||||
public static final KeyGroup BRAINPOOLP384R1TLS13 = new KeyGroup((short) 32, "brainpoolP384r1tls13");
|
|
||||||
public static final KeyGroup BRAINPOOLP512R1TLS13 = new KeyGroup((short) 33, "brainpoolP512r1tls13");
|
|
||||||
public static final KeyGroup GC256A = new KeyGroup((short) 34, "GC256A");
|
|
||||||
public static final KeyGroup GC256B = new KeyGroup((short) 35, "GC256B");
|
|
||||||
public static final KeyGroup GC256C = new KeyGroup((short) 36, "GC256C");
|
|
||||||
public static final KeyGroup GC256D = new KeyGroup((short) 37, "GC256D");
|
|
||||||
public static final KeyGroup GC512A = new KeyGroup((short) 38, "GC512A");
|
|
||||||
public static final KeyGroup GC512B = new KeyGroup((short) 39, "GC512B");
|
|
||||||
public static final KeyGroup GC512C = new KeyGroup((short) 40, "GC512C");
|
|
||||||
public static final KeyGroup CURVESM2 = new KeyGroup((short) 41, "curveSM2");
|
|
||||||
public static final KeyGroup FFDHE2048 = new KeyGroup((short) 256, "ffdhe2048");
|
|
||||||
public static final KeyGroup FFDHE3072 = new KeyGroup((short) 257, "ffdhe3072");
|
|
||||||
public static final KeyGroup FFDHE4096 = new KeyGroup((short) 258, "ffdhe4096");
|
|
||||||
public static final KeyGroup FFDHE6144 = new KeyGroup((short) 259, "ffdhe6144");
|
|
||||||
public static final KeyGroup FFDHE8192 = new KeyGroup((short) 260, "ffdhe8192");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_2570 = new KeyGroup((short) 2570, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_6682 = new KeyGroup((short) 6682, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_10794 = new KeyGroup((short) 10794, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_14906 = new KeyGroup((short) 14906, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_19018 = new KeyGroup((short) 19018, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_23130 = new KeyGroup((short) 23130, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_27242 = new KeyGroup((short) 27242, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_31354 = new KeyGroup((short) 31354, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_35466 = new KeyGroup((short) 35466, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_39578 = new KeyGroup((short) 39578, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_43690 = new KeyGroup((short) 43690, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_47802 = new KeyGroup((short) 47802, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_51914 = new KeyGroup((short) 51914, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_56026 = new KeyGroup((short) 56026, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_60138 = new KeyGroup((short) 60138, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup RESERVED_GREASE_64250 = new KeyGroup((short) 64250, "Reserved (GREASE)");
|
|
||||||
public static final KeyGroup ARBITRARY_EXPLICIT_PRIME_CURVES = new KeyGroup((short) 65281, "arbitrary_explicit_prime_curves");
|
|
||||||
public static final KeyGroup ARBITRARY_EXPLICIT_CHAR2_CURVES = new KeyGroup((short) 65282, "arbitrary_explicit_char2_curves");
|
|
||||||
|
|
||||||
public KeyGroup(Short value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
registry.put(value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeyGroup getInstance(Short value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
return new KeyGroup(value, "Unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(KeyGroup o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.numbers;
|
|
||||||
|
|
||||||
import org.pcap4j.packet.namednumber.NamedNumber;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TlsVersion extends NamedNumber<Short, TlsVersion> {
|
|
||||||
|
|
||||||
public static final TlsVersion TLS_1_0 = new TlsVersion((short) 0x0301, "TLS 1.0");
|
|
||||||
public static final TlsVersion TLS_1_1 = new TlsVersion((short) 0x0302, "TLS 1.1");
|
|
||||||
public static final TlsVersion TLS_1_2 = new TlsVersion((short) 0x0303, "TLS 1.2");
|
|
||||||
public static final TlsVersion TLS_1_3 = new TlsVersion((short) 0x0304, "TLS 1.3");
|
|
||||||
|
|
||||||
private static final Map<Short, TlsVersion> registry = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
registry.put(TLS_1_0.value(), TLS_1_0);
|
|
||||||
registry.put(TLS_1_1.value(), TLS_1_1);
|
|
||||||
registry.put(TLS_1_2.value(), TLS_1_2);
|
|
||||||
registry.put(TLS_1_3.value(), TLS_1_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TlsVersion(Short value, String name) {
|
|
||||||
super(value, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TlsVersion getInstance(Short value) {
|
|
||||||
if (registry.containsKey(value)) {
|
|
||||||
return registry.get(value);
|
|
||||||
} else {
|
|
||||||
return new TlsVersion(value, "unknown");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(TlsVersion o) {
|
|
||||||
return value().compareTo(o.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package ru.serega6531.packmate.service.optimization.tls.records;
|
|
||||||
|
|
||||||
import org.pcap4j.util.ByteArrays;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.AlertDescription;
|
|
||||||
import ru.serega6531.packmate.service.optimization.tls.numbers.AlertLevel;
|
|
||||||
|
|
||||||
import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
public class AlertRecord implements TlsRecord {
|
|
||||||
|
|
||||||
private static final int LEVEL_OFFSET = 0;
|
|
||||||
private static final int DESCRIPTION_OFFSET = LEVEL_OFFSET + BYTE_SIZE_IN_BYTES;
|
|
||||||
|
|
||||||
private int length;
|
|
||||||
private AlertLevel level;
|
|
||||||
private AlertDescription description;
|
|
||||||
|
|
||||||
public static AlertRecord newInstance(byte[] rawData, int offset, int length) {
|
|
||||||
ByteArrays.validateBounds(rawData, offset, length);
|
|
||||||
return new AlertRecord(rawData, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AlertRecord(byte[] rawData, int offset, int length) {
|
|
||||||
this.length = length;
|
|
||||||
this.level = AlertLevel.getInstance(ByteArrays.getByte(rawData, LEVEL_OFFSET + offset));
|
|
||||||
|
|
||||||
if (level != AlertLevel.ENCRYPTED_ALERT) {
|
|
||||||
this.description = AlertDescription.getInstance(ByteArrays.getByte(rawData, DESCRIPTION_OFFSET + offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if (level != AlertLevel.ENCRYPTED_ALERT) {
|
|
||||||
return " Alert [level: " + level.name() + ", description: " + description.name() + "]";
|
|
||||||
} else {
|
|
||||||
return " Encrypted Alert [" + length + " bytes]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||