7 Commits

Author SHA1 Message Date
Sergey Shkurov
cc66f47d0d Update README.md 2023-08-05 02:01:25 +04:00
Sergey Shkurov
d085e04168 Remove RsaKeysHolder 2023-08-05 02:00:39 +04:00
Sergey Shkurov
65c6de9a06 Update frontend 2023-08-03 03:22:55 +04:00
Sergey Shkurov
b7f61fc435 Remove more test files 2023-08-03 02:56:43 +04:00
Sergey Shkurov
b02185794d Remove test 2023-08-03 02:56:06 +04:00
Sergey Shkurov
5ee345735d Remove dto fields 2023-08-03 02:56:00 +04:00
Sergey Shkurov
88e76c096d Remove TLS support 2023-08-03 02:46:30 +04:00
122 changed files with 77 additions and 39005 deletions

View File

@@ -6,4 +6,3 @@ docker-compose.yml
Dockerfile_*
data
README*
references_for_redisign

View File

@@ -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

View File

@@ -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
View File

@@ -1,4 +1,4 @@
references_for_redisign
src/main/resources/static/*
*.pcap
data

24
.gitlab-ci.yml Normal file
View 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
View File

@@ -0,0 +1,3 @@
[submodule "frontend"]
path = frontend
url = https://gitlab.com/packmate/packmate-frontend.git

View File

@@ -1,10 +1,10 @@
<div align="center">
# 0xb00b5 team Packmate
# Packmate
</div>
### [[EN](README_EN.md) | RU]
Утилита перехвата и анализа трафика для CTF, переосмысленная в пиксельном неоне.
Утилита перехвата и анализа трафика для CTF.
#### Фичи:
* Поддерживает перехват живого трафика и обработку pcap файлов
@@ -22,32 +22,27 @@
* Автоматически проводит urldecode
* Разархивирует GZIP в HTTP на лету
* Разархивирует сжатые WebSockets
* Расшифровывает TLS на RSA при наличии приватного ключа
* Обманка для входа `admin:admin` с режимами `fun` и `fake_packets`, чтобы любопытные так и не добрались до настоящих пакетов
![Скриншот главного окна](screenshots/Screenshot.png)
### Обманка 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, его необходимо клонировать так:
```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 clone --recursive https://git.danosito.com/0xb00b5/0xb00b5-packmate.git
git clone --recursive https://gitlab.com/packmate/Packmate.git
```
Если репозиторий уже был склонирован без подмодулей, необходимо выполнить:
```bash
git pull # Забираем свежую версию мастер-репы
git pull # Забираем свежую версию мастер-репы из gitlab
git submodule update --init --recursive
```
@@ -60,7 +55,7 @@ git submodule update --init --recursive
sudo docker compose up --build -d
```
При успешном запуске 0xb00b5 team Packmate будет видно с любого хоста на порту `65000`.
При успешном запуске Packmate будет видно с любого хоста на порту `65000`.
БД будет слушать на порту 65001, но будет разрешать подключения только с localhost.
## Использование
@@ -68,5 +63,5 @@ sudo docker compose up --build -d
<div align="right">
*@danosito*
*desu~*
</div>

View File

@@ -1,10 +1,10 @@
<div align="center">
# 0xb00b5 team Packmate
# Packmate
</div>
### [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:
* 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 automatically decompress GZIPed HTTP
* 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
![Main window](screenshots/Screenshot.png)
### 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
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
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
As this repository contains frontend part as a git submodule, it has to be cloned like this:
```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
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:
@@ -60,7 +55,7 @@ After filling in env file you can launch the app:
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.
## Usage

View File

@@ -6,28 +6,21 @@ services:
LOCAL_IP: ${PACKMATE_LOCAL_IP}
MODE: ${PACKMATE_MODE:-LIVE}
PCAP_FILE: ${PACKMATE_PCAP_FILE:-}
WEB_LOGIN: ${PACKMATE_WEB_LOGIN:-0xb00b5}
WEB_PASSWORD: ${PACKMATE_WEB_PASSWORD:-87654321}
FAKE_ADMIN_AUTH_ENABLED: ${PACKMATE_FAKE_ADMIN_ENABLED:-true}
FAKE_ADMIN_MODE: ${PACKMATE_FAKE_ADMIN_MODE:-fun}
WEB_LOGIN: ${PACKMATE_WEB_LOGIN:-BinaryBears}
WEB_PASSWORD: ${PACKMATE_WEB_PASSWORD:-123456}
OLD_STREAMS_CLEANUP_ENABLED: ${PACKMATE_OLD_STREAMS_CLEANUP_ENABLED:-false}
OLD_STREAMS_CLEANUP_INTERVAL: ${PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL:-5}
OLD_STREAMS_CLEANUP_THRESHOLD: ${PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD:-240}
env_file:
- .env
cap_add:
- NET_ADMIN
- NET_RAW
privileged: true
container_name: packmate-app
build:
context: .
dockerfile: docker/Dockerfile_app
network_mode: "host"
image: cr.danosito.com/0xb00b5/0xb00b5-packmate:${BUILD_TAG:-latest}
image: registry.gitlab.com/packmate/packmate:${BUILD_TAG:-latest}
volumes:
- "./pcaps/:/app/pcaps/:ro"
- "./rsa_keys/:/app/rsa_keys/:ro"
depends_on:
db:
condition: service_healthy

View File

@@ -1,6 +1,5 @@
FROM node:19-alpine
WORKDIR /tmp/build/
RUN apk add --no-cache python3 make g++
COPY ./frontend/ .
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.interface-name=${INTERFACE}", "--packmate.local-ip=${LOCAL_IP}", \
"--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.interval=${OLD_STREAMS_CLEANUP_INTERVAL}", \
"--packmate.cleanup.threshold=${OLD_STREAMS_CLEANUP_THRESHOLD}", \

View File

@@ -1,6 +1,6 @@
## Настройка
0xb00b5 team Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
Packmate использует настройки из файла `.env` (в той же папке, что и `docker-compose.yml`)
### Основные настройки
```dotenv
@@ -10,17 +10,13 @@ PACKMATE_LOCAL_IP=10.20.1.1
PACKMATE_WEB_LOGIN=SomeUser
# Пароль для web-авторизации
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`.
1. `LIVE` - это основной режим работы во время CTF. 0xb00b5 team Packmate обрабатывает живой трафик и сразу выводит результаты.
2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен 0xb00b5 team Packmate, или тех, где невозможно запустить его на вулнбоксе.
3. `VIEW` - 0xb00b5 team Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
Packmate поддерживает три основных режима работы: `LIVE`, `FILE` и `VIEW`.
1. `LIVE` - это основной режим работы во время CTF. Packmate обрабатывает живой трафик и сразу выводит результаты.
2. `FILE` - обрабатывает трафик из pcap файлов. Полезен для анализа трафика с прошедших CTF, где не был запущен Packmate, или тех, где невозможно запустить его на вулнбоксе.
3. `VIEW` - Packmate не обрабатывает трафик, а только показывает уже обработанные стримы. Полезен для разборов после завершения CTF.
<details>
<summary>Настройка LIVE</summary>
@@ -56,7 +52,7 @@ PACKMATE_PCAP_FILE=dump.pcap
<details>
<summary>Настройка VIEW</summary>
В этом режиме 0xb00b5 team Packmate просто показывает уже имеющиеся данные.
В этом режиме Packmate просто показывает уже имеющиеся данные.
```dotenv
# Режим работы - просмотр
@@ -66,7 +62,7 @@ PACKMATE_MODE=VIEW
</details>
### Очистка БД
На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу 0xb00b5 team Packmate и занимает много места на диске.
На крупных CTF через какое-то время накапливается большое количество трафика. Это замедляет работу Packmate и занимает много места на диске.
Для оптимизации работы, рекомендуется включить регулярную очистку БД от старых стримов. Это будет работать только в режиме `LIVE`.
```dotenv
@@ -83,7 +79,7 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
```dotenv
# Пароль от БД. Из-за того, что БД принимает подключения только с localhost, менять его необязательно, но можно, для дополнительной безопасности.
PACKMATE_DB_PASSWORD=K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
# Версия 0xb00b5 team Packmate. Можно изменить, если нужен другой тег образа из cr.danosito.com/danosito/0xb00b5-packmate.
# Версия Packmate. Можно изменить, если нужно использовать другой образ из docker registry.
BUILD_TAG=latest
```

View File

@@ -1,6 +1,6 @@
## 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
```dotenv
@@ -10,17 +10,13 @@ PACKMATE_LOCAL_IP=10.20.1.1
PACKMATE_WEB_LOGIN=SomeUser
# Password for the web interface
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
0xb00b5 team 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.
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.
3. `VIEW` - 0xb00b5 team Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
Packmate supports 3 modes of operation: `LIVE`, `FILE` и `VIEW`.
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 Packmate wasn't launched, or CTFs where it's impossible to use it on the vulnbox.
3. `VIEW` - Packmate does not process any traffic, but simply shows already processed streams. Useful for post-game analyses.
<details>
<summary>LIVE setup</summary>
@@ -56,7 +52,7 @@ PACKMATE_PCAP_FILE=dump.pcap
<details>
<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
# Mode: viewing the data
@@ -66,7 +62,7 @@ PACKMATE_MODE=VIEW
</details>
### 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.
```dotenv
@@ -83,7 +79,7 @@ PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=240
```dotenv
# 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
# 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
```

1
frontend Submodule

Submodule frontend added at a15d846d37

86
frontend/.gitignore vendored
View File

@@ -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*
$*$

View File

@@ -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/).

View File

@@ -1,8 +0,0 @@
module.exports = {
presets: [
'@vue/app',
],
plugins: [
'@babel/plugin-proposal-optional-chaining',
],
};

31852
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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"
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -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

View File

@@ -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"
}

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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 = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'/': '&#x2F;',
};
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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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');

View File

@@ -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);
}

View File

@@ -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',
});

View File

@@ -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;
},
}),
],
});

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,3 +0,0 @@
module.exports = {
lintOnSave: false,
};

View File

@@ -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-----

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -7,20 +7,13 @@ import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
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
@EnableWebSecurity
@@ -29,46 +22,31 @@ public class SecurityConfiguration {
@Bean
public InMemoryUserDetailsManager userDetailsService(PackmateProperties properties, PasswordEncoder passwordEncoder) {
List<UserDetails> users = new ArrayList<>();
users.add(User.builder()
UserDetails user = User.builder()
.username(properties.web().accountLogin())
.password(passwordEncoder.encode(properties.web().accountPassword()))
.roles("USER")
.build());
.build();
Optional.ofNullable(properties.web().fakeAdmin())
.filter(PackmateProperties.FakeAdminProperties::enabled)
.ifPresent(fakeAdmin -> users.add(User.builder()
.username("admin")
.password(passwordEncoder.encode("admin"))
.roles("FAKE")
.build()));
return new InMemoryUserDetailsManager(users);
return new InMemoryUserDetailsManager(user);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, FakeAdminAuthFilter fakeAdminAuthFilter) throws Exception {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf()
.disable()
.authorizeHttpRequests((auth) ->
auth.requestMatchers("/site.webmanifest", "/fake-admin/**", "/fake/**", "/api/fake/**")
auth.requestMatchers("/site.webmanifest")
.permitAll()
.requestMatchers("/api/**", "/ws/**")
.hasRole("USER")
.anyRequest()
.authenticated()
)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.and()
.headers()
.frameOptions()
.sameOrigin()
.and()
.addFilterAfter(fakeAdminAuthFilter, BasicAuthenticationFilter.class)
.build();
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -23,8 +23,6 @@ public class CtfService {
@Column(nullable = false)
private String name;
private boolean decryptTls;
private boolean http;
private boolean urldecodeHttpRequests;

View File

@@ -53,8 +53,6 @@ public class Packet {
private boolean webSocketParsed = false;
private boolean tlsDecrypted = false;
private boolean hasHttpBody = false;
@Column(nullable = false)

View File

@@ -1,6 +0,0 @@
package ru.serega6531.packmate.model.enums;
public enum FakeAdminMode {
FUN,
FAKE_PACKETS
}

View File

@@ -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;
}

View File

@@ -13,7 +13,6 @@ public class PacketDto {
private boolean incoming;
private boolean ungzipped;
private boolean webSocketParsed;
private boolean tlsDecrypted;
private boolean hasHttpBody;
private byte[] content;

View File

@@ -7,7 +7,6 @@ public class ServiceCreateDto {
private int port;
private String name;
private boolean decryptTls;
private boolean http;
private boolean urldecodeHttpRequests;
private boolean mergeAdjacentPackets;

View File

@@ -7,7 +7,6 @@ public class ServiceDto {
private int port;
private String name;
private boolean decryptTls;
private boolean http;
private boolean urldecodeHttpRequests;
private boolean mergeAdjacentPackets;

View File

@@ -7,7 +7,6 @@ public class ServiceUpdateDto {
private int port;
private String name;
private boolean decryptTls;
private boolean http;
private boolean urldecodeHttpRequests;
private boolean mergeAdjacentPackets;

View File

@@ -3,7 +3,6 @@ package ru.serega6531.packmate.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import ru.serega6531.packmate.model.enums.CaptureMode;
import ru.serega6531.packmate.model.enums.FakeAdminMode;
import java.net.InetAddress;
@@ -21,13 +20,7 @@ public record PackmateProperties(
public record WebProperties(
String accountLogin,
String accountPassword,
FakeAdminProperties fakeAdmin
) {}
public record FakeAdminProperties(
boolean enabled,
FakeAdminMode mode
String accountPassword
) {}
public record TimeoutProperties(

View File

@@ -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";
};
}
}

View File

@@ -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 "[]";
}
}
}

View File

@@ -14,7 +14,6 @@ import ru.serega6531.packmate.model.pojo.ServiceCreateDto;
import ru.serega6531.packmate.model.pojo.ServiceDto;
import ru.serega6531.packmate.model.pojo.ServiceUpdateDto;
import ru.serega6531.packmate.model.pojo.SubscriptionMessage;
import ru.serega6531.packmate.model.pojo.FakeServiceDto;
import ru.serega6531.packmate.repository.ServiceRepository;
import java.net.InetAddress;
@@ -80,17 +79,6 @@ public class ServicesService {
.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) {
log.info("Removed service at port {}", port);

View File

@@ -12,7 +12,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ru.serega6531.packmate.properties.PackmateProperties;
import ru.serega6531.packmate.model.CtfService;
import ru.serega6531.packmate.model.FoundPattern;
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.SubscriptionMessage;
import ru.serega6531.packmate.model.pojo.UnfinishedStream;
import ru.serega6531.packmate.properties.PackmateProperties;
import ru.serega6531.packmate.repository.StreamRepository;
import ru.serega6531.packmate.service.optimization.RsaKeysHolder;
import ru.serega6531.packmate.service.optimization.StreamOptimizer;
import java.time.ZonedDateTime;
@@ -46,7 +45,6 @@ public class StreamService {
private final ServicesService servicesService;
private final CountingService countingService;
private final SubscriptionService subscriptionService;
private final RsaKeysHolder keysHolder;
private final ModelMapper modelMapper;
private final boolean ignoreEmptyPackets;
@@ -58,7 +56,6 @@ public class StreamService {
ServicesService servicesService,
CountingService countingService,
SubscriptionService subscriptionService,
RsaKeysHolder keysHolder,
ModelMapper modelMapper,
PackmateProperties properties) {
this.repository = repository;
@@ -66,7 +63,6 @@ public class StreamService {
this.servicesService = servicesService;
this.countingService = countingService;
this.subscriptionService = subscriptionService;
this.keysHolder = keysHolder;
this.modelMapper = modelMapper;
this.ignoreEmptyPackets = properties.ignoreEmptyPackets();
}
@@ -104,7 +100,7 @@ public class StreamService {
int packetsSize = packets.stream().mapToInt(p -> p.getContent().length).sum();
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)) {
log.debug("New stream is ignored");

View File

@@ -45,7 +45,6 @@ public class PacketsMerger {
final long timestamp = cut.get(0).getTimestamp();
final boolean httpProcessed = cut.stream().anyMatch(Packet::isHttpProcessed);
final boolean webSocketParsed = cut.stream().anyMatch(Packet::isWebSocketParsed);
final boolean tlsDecrypted = cut.get(0).isTlsDecrypted();
final boolean incoming = cut.get(0).isIncoming();
final byte[] content = PacketUtils.mergePackets(cut);
@@ -55,7 +54,6 @@ public class PacketsMerger {
.timestamp(timestamp)
.httpProcessed(httpProcessed)
.webSocketParsed(webSocketParsed)
.tlsDecrypted(tlsDecrypted)
.content(content)
.build());
}

View File

@@ -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);
}
}

View File

@@ -11,7 +11,6 @@ import java.util.List;
@Slf4j
public class StreamOptimizer {
private final RsaKeysHolder keysHolder;
private final CtfService service;
private List<Packet> packets;
@@ -24,15 +23,6 @@ public class StreamOptimizer {
* Вызвать для выполнения оптимизаций на переданном списке пакетов.
*/
public List<Packet> optimizeStream() {
if (service.isDecryptTls()) {
try {
decryptTls();
} catch (Exception e) {
log.warn("Error optimizing stream (tls)", e);
return packets;
}
}
if (service.isParseWebSockets()) {
try {
parseWebSockets();
@@ -72,15 +62,6 @@ public class StreamOptimizer {
return packets;
}
private void decryptTls() {
final TlsDecryptor tlsDecryptor = new TlsDecryptor(packets, keysHolder);
tlsDecryptor.decryptTls();
if (tlsDecryptor.isParsed()) {
packets = tlsDecryptor.getParsedPackets();
}
}
private void parseWebSockets() {
if (!packets.get(0).getContentString().contains("HTTP/")) {
return;

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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]";
}
}
}

Some files were not shown because too many files have changed in this diff Show More