Commit 13cf7d94 authored by 957dd's avatar 957dd

验证加入了res验证

parent 279aa042
...@@ -10,6 +10,13 @@ message(STATUS "Mosquitto path: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/mosquitt ...@@ -10,6 +10,13 @@ message(STATUS "Mosquitto path: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/mosquitt
# 设置模式 Release 为发布模式,Debug 为调试模式。 # 设置模式 Release 为发布模式,Debug 为调试模式。
# 平时切换只需改这一行;命令行 -DCAR_BUILD_TYPE=Debug 会优先生效。 # 平时切换只需改这一行;命令行 -DCAR_BUILD_TYPE=Debug 会优先生效。
# 1、Debug 编译(推荐,不改源码)
# cmake -S . -B build -DCAR_BUILD_TYPE=Debug
# cmake --build build -j2
# 2. Release 编译(切回发布版)
# cmake -S . -B build -DCAR_BUILD_TYPE=Release
# cmake --build build -j2
set(CAR_DEFAULT_BUILD_TYPE "Release") set(CAR_DEFAULT_BUILD_TYPE "Release")
if(NOT DEFINED CAR_BUILD_TYPE) if(NOT DEFINED CAR_BUILD_TYPE)
set(CAR_BUILD_TYPE "${CAR_DEFAULT_BUILD_TYPE}") set(CAR_BUILD_TYPE "${CAR_DEFAULT_BUILD_TYPE}")
......
No preview for this file type
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#define HTTP_COMMON_H__ #define HTTP_COMMON_H__
#include "http_config_mqtt.h" #include "http_config_mqtt.h"
#include "http_consolepush.h"
#include "http_request.h" #include "http_request.h"
#endif #endif
\ No newline at end of file
#include "http_consolepush.h"
#include "common.h"
#include "pthrpoll.h"
void contril_pthread_open();
void contril_pthread_close();
// 全局变量(需加锁或原子操作)
static bool s_shutdown = false;
static ThreadPool_t *s_pool_control_push;
static pthread_mutex_t s_shutdown_mutex = PTHREAD_MUTEX_INITIALIZER;
static const control_push_t s_control_push_configs[]={
{
.control_push_pthread_open = contril_pthread_open,
.control_push_pthread_close = NULL
},
{
.control_push_pthread_open = NULL,
.control_push_pthread_close =contril_pthread_close
}
};
void connect_and_run_shell() {
int sock = 0;
struct sockaddr_in serv_addr;
// --- 连接到服务器 ---
while (!s_shutdown) {
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
my_zlog_error("Socket creation error");
sleep(5);
continue;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) {
my_zlog_error("Invalid address");
close(sock);
sleep(5);
continue;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Connection Failed: %s. Retrying in 5s...\n", strerror(errno));
close(sock);
sleep(5);
continue;
}
fprintf(stderr, "Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);
my_zlog_info("Connected to server");
break; // 连接成功,跳出循环
}
// --- 创建伪终端 (pty) 并启动 Shell ---
int master_fd;
pid_t pid = forkpty(&master_fd, NULL, NULL, NULL);
if (pid < 0) {
my_zlog_error("forkpty");
close(sock);
return;
}
else if (pid == 0) { // 子进程
// 用 /bin/bash 替换当前子进程
//execlp("/bin/bash", "bash", NULL);
// 在 execlp 之前,设置环境变量
setenv("TERM", "dumb", 1);
// 然后执行
execlp("/bin/bash", "bash", NULL);
// 如果 exec 返回,说明出错了
my_zlog_error("execlp");
exit(1);
}
// --- 父进程:数据中继 ---
fd_set read_fds;
while (!s_shutdown) {
FD_ZERO(&read_fds);
FD_SET(sock, &read_fds); // 监听来自服务器的命令
FD_SET(master_fd, &read_fds); // 监听来自 Shell 的输出
int max_fd = (sock > master_fd) ? sock : master_fd;
struct timeval tv;
tv.tv_sec = 1; // 每 1 秒超时
tv.tv_usec = 0;
int ret =select(max_fd + 1, &read_fds, NULL, NULL, &tv);
if ( ret< 0) {
my_zlog_error("select");
break;
}else if (ret == 0) {
// 超时,回到循环,检查 s_shutdown
continue;
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read;
// 检查是否有来自服务器的数据
if (FD_ISSET(sock, &read_fds)) {
bytes_read = read(sock, buffer, sizeof(buffer));
if (bytes_read <= 0) {
my_zlog_info("Connected to server disconnected.");
my_zlog_info( "Server disconnected.");
break; // 服务器断开
}
// 将命令写入 Shell
ssize_t bytes_written = write(master_fd, buffer, bytes_read);
if (bytes_written >= bytes_read) {
// 写入失败
my_zlog_info("write success");
}
}
// 检查是否有来自 Shell 的输出
if (FD_ISSET(master_fd, &read_fds)) {
bytes_read = read(master_fd, buffer, sizeof(buffer));
if (bytes_read <= 0) {
fprintf(stderr, "Shell process terminated.\n");
break; // Shell 进程结束
}
// 将 Shell 输出发送到服务器
if (send(sock, buffer, bytes_read, 0) < 0) {
fprintf(stderr, "Failed to send data to server.\n");
break;
}
}
}
my_zlog_info("Connected to close.");
// --- 清理 ---
close(sock);
close(master_fd);
kill(pid, SIGKILL); // 确保子进程被杀死
}
void contril_pthread_open(){
if(s_pool_control_push == NULL){
s_pool_control_push = thread_pool_init(1,1);
my_zlog_info("contril push pool pthread open");
thread_pool_add_task(s_pool_control_push , connect_and_run_shell, NULL);
}else {
my_zlog_info("control push pthread already open ");
}
}
void contril_pthread_close(){
if ( s_pool_control_push == NULL) {
my_zlog_info("control push pthread already NULL");
return; // 已销毁或无效句柄,直接返回
}else {
pthread_mutex_lock(&s_shutdown_mutex);
s_shutdown = true;
pthread_mutex_unlock(&s_shutdown_mutex);
my_zlog_info("control push pthread close success");
thread_pool_destroy(s_pool_control_push);
s_pool_control_push = NULL;
}
}
void control_pthread_function(char *string){
const control_push_t *g_control_push_config = NULL;
if(strcmp(string,"open")==0){
my_zlog_debug("open pthread");
g_control_push_config =&s_control_push_configs[0];
g_control_push_config ->control_push_pthread_open();
}else if(strcmp(string,"close")==0){
my_zlog_debug("close pthread");
g_control_push_config =&s_control_push_configs[1];
g_control_push_config ->control_push_pthread_close();
}else {
g_control_push_config =NULL;
}
if(!g_control_push_config){
my_zlog_warn("s_pool_control_push am NULL");
return ;
}
}
#ifndef HTTP_CONSOLEPUSH_H__
#define HTTP_CONSOLEPUSH_H__
#define SERVER_IP "123.56.231.114"
#define SERVER_PORT 8081
#define BUFFER_SIZE 4096
typedef struct{
void (*control_push_pthread_open)(void);
void (*control_push_pthread_close)(void);
}control_push_t;
void control_pthread_function(char *string);
#endif
\ No newline at end of file
#include "mqtt_aes.h"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <stdlib.h>
#include <string.h>
static int normalize_key(const char *secret_key, unsigned char *key_out, int *key_len_out)
{
size_t len = strlen(secret_key);
if (len == 16 || len == 24 || len == 32) {
memcpy(key_out, secret_key, len);
*key_len_out = (int)len;
return 0;
}
if (SHA256((const unsigned char *)secret_key, len, key_out) == NULL) {
return -1;
}
*key_len_out = 32;
return 0;
}
static const EVP_CIPHER *cipher_for_key_len(int key_len)
{
switch (key_len) {
case 16:
return EVP_aes_128_ecb();
case 24:
return EVP_aes_192_ecb();
case 32:
return EVP_aes_256_ecb();
default:
return NULL;
}
}
static unsigned char *base64_decode(const char *input, size_t *out_len)
{
BIO *bio = NULL;
BIO *b64 = NULL;
size_t len = strlen(input);
unsigned char *buffer = (unsigned char *)malloc(len * 3 / 4 + 4);
if (!buffer) {
return NULL;
}
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_mem_buf(input, (int)len);
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
int decoded = BIO_read(bio, buffer, (int)(len * 3 / 4 + 4));
BIO_free_all(bio);
if (decoded <= 0) {
free(buffer);
return NULL;
}
*out_len = (size_t)decoded;
return buffer;
}
int mqtt_aes_decrypt_body(const char *b64_cipher, const char *secret_key, char **plain_json_out)
{
unsigned char key_bytes[32];
int key_len = 0;
size_t cipher_len = 0;
unsigned char *cipher_bytes = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char *plain = NULL;
int out_len1 = 0;
int out_len2 = 0;
int total = 0;
if (!b64_cipher || !secret_key || !plain_json_out) {
return -1;
}
*plain_json_out = NULL;
if (normalize_key(secret_key, key_bytes, &key_len) != 0) {
return -1;
}
const EVP_CIPHER *cipher = cipher_for_key_len(key_len);
if (!cipher) {
return -1;
}
cipher_bytes = base64_decode(b64_cipher, &cipher_len);
if (!cipher_bytes || cipher_len == 0) {
free(cipher_bytes);
return -1;
}
ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
free(cipher_bytes);
return -1;
}
plain = (unsigned char *)malloc(cipher_len + 16);
if (!plain) {
EVP_CIPHER_CTX_free(ctx);
free(cipher_bytes);
return -1;
}
if (EVP_DecryptInit_ex(ctx, cipher, NULL, key_bytes, NULL) != 1) {
goto fail;
}
if (EVP_DecryptUpdate(ctx, plain, &out_len1, cipher_bytes, (int)cipher_len) != 1) {
goto fail;
}
if (EVP_DecryptFinal_ex(ctx, plain + out_len1, &out_len2) != 1) {
goto fail;
}
total = out_len1 + out_len2;
plain[total] = '\0';
*plain_json_out = (char *)plain;
plain = NULL;
EVP_CIPHER_CTX_free(ctx);
free(cipher_bytes);
return 0;
fail:
free(plain);
EVP_CIPHER_CTX_free(ctx);
free(cipher_bytes);
return -1;
}
#ifndef MQTT_AES_H__
#define MQTT_AES_H__
#define MQTT_ENCRYPT_KEY "Kp9mX2nQ7vRw4sLd"
#define MQTT_VERIFY_AUTH_KEY "fcrs-verify-off-2026"
/* AES/ECB/PKCS7 解密 Base64 密文,调用方 free(*plain_json_out)。成功返回 0。 */
int mqtt_aes_decrypt_body(const char *b64_cipher, const char *secret_key, char **plain_json_out);
#endif
...@@ -341,10 +341,6 @@ int device_message_receive(cJSON *json) ...@@ -341,10 +341,6 @@ int device_message_receive(cJSON *json)
{ {
cJSON *body = cJSON_GetObjectItem(json, "body"); // 提取 body数据段 cJSON *body = cJSON_GetObjectItem(json, "body"); // 提取 body数据段
if (!cJSON_IsObject(body))
{
return 1;
}
pthread_mutex_lock(&g_exit_count_mutex); pthread_mutex_lock(&g_exit_count_mutex);
g_devcontrol_exit_count = 0; g_devcontrol_exit_count = 0;
...@@ -352,6 +348,20 @@ int device_message_receive(cJSON *json) ...@@ -352,6 +348,20 @@ int device_message_receive(cJSON *json)
s_message_type = message_type->valueint; s_message_type = message_type->valueint;
my_zlog_debug("message_type: %d", message_type->valueint); my_zlog_debug("message_type: %d", message_type->valueint);
if (s_message_type == 2013) {
if (message2013_recverigy_open(body) == 0) {
my_zlog_info("进入是否需要验证");
return 0;
}
return 1;
}
if (!cJSON_IsObject(body))
{
return 1;
}
switch (s_message_type) switch (s_message_type)
{ {
case 2: case 2:
...@@ -422,18 +432,6 @@ int device_message_receive(cJSON *json) ...@@ -422,18 +432,6 @@ int device_message_receive(cJSON *json)
refresh_cam(); refresh_cam();
my_zlog_info("刷新成功"); my_zlog_info("刷新成功");
break; break;
case 2013:
message2013_recverigy_open(body);
my_zlog_info("进入是否需要验证");
break;
case 2014:
control_pthread_function("open");
my_zlog_info("打开控制台推送");
break;
case 2015:
control_pthread_function("close");
my_zlog_info("关闭控制台推送");
break;
case 2016: case 2016:
mqtt_verify_data_clear(body); mqtt_verify_data_clear(body);
my_zlog_info("清除验证数据"); my_zlog_info("清除验证数据");
......
#include <time.h> #include <time.h>
#include "mqtt_verify.h" #include "mqtt_verify.h"
#include "mqtt_aes.h"
#include "common.h" #include "common.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "device_identity.h" #include "device_identity.h"
#include "mqtt_init.h" #include "mqtt_init.h"
#include "mylog.h" #include "mylog.h"
...@@ -256,26 +251,75 @@ int message2006_verify(cJSON *body){ ...@@ -256,26 +251,75 @@ int message2006_verify(cJSON *body){
return 0; return 0;
} }
/*接收到是否打开验证的函数*/ /*接收到是否打开验证的函数;2013 仅接受 AES 加密 String body,明文一律拒绝*/
int message2013_recverigy_open(cJSON *body){ int message2013_recverigy_open(cJSON *body_raw)
cJSON *verifty_open_index = cJSON_GetObjectItem(body, "verify_status"); {
if(verifty_open_index == NULL){ cJSON *body = NULL;
my_zlog_warn("接收验证是否打开为空"); char *plain_json = NULL;
cJSON *verify_status = NULL;
cJSON *auth_key = NULL;
if (body_raw == NULL) {
my_zlog_warn("2013 body为空");
return -1;
}
if (cJSON_IsObject(body_raw)) {
my_zlog_warn("2013 必须加密下发,明文拒绝");
return -1;
}
if (!cJSON_IsString(body_raw) || body_raw->valuestring == NULL) {
my_zlog_warn("2013 body类型无效");
return -1;
}
if (mqtt_aes_decrypt_body(body_raw->valuestring, MQTT_ENCRYPT_KEY, &plain_json) != 0) {
my_zlog_warn("2013 body解密失败");
return -1;
}
body = cJSON_Parse(plain_json);
free(plain_json);
if (body == NULL) {
my_zlog_warn("2013 解密后JSON解析失败");
return -1;
}
verify_status = cJSON_GetObjectItem(body, "verify_status");
if (!cJSON_IsNumber(verify_status)) {
my_zlog_warn("2013 解密后缺少verify_status");
cJSON_Delete(body);
return -1; return -1;
} }
int verifty_open = verifty_open_index->valueint;
s_verify_open_got_reply = true; s_verify_open_got_reply = true;
s_verify_open_query_gave_up = false; s_verify_open_query_gave_up = false;
if(verifty_open == 0){ if (verify_status->valueint == 1) {
VERIFIED_MODE=FALSE; VERIFIED_MODE = TRUE;
my_zlog_info("关闭验证, verify_status=%d", verifty_open); my_zlog_info("开启验证成功(加密校验通过), verify_status=1");
}else { cJSON_Delete(body);
VERIFIED_MODE=TRUE; return 0;
my_zlog_info("开启验证, verify_status=%d", verifty_open);
} }
if (verify_status->valueint == 0) {
auth_key = cJSON_GetObjectItem(body, "auth_key");
if (!cJSON_IsString(auth_key) || auth_key->valuestring == NULL
|| strcmp(auth_key->valuestring, MQTT_VERIFY_AUTH_KEY) != 0) {
my_zlog_warn("2013 关闭验证 auth_key校验失败");
cJSON_Delete(body);
return -1;
}
VERIFIED_MODE = FALSE;
my_zlog_info("关闭验证成功(加密+auth_key校验通过)");
cJSON_Delete(body);
return 0; return 0;
}
my_zlog_warn("2013 verify_status无效: %d", verify_status->valueint);
cJSON_Delete(body);
return -1;
} }
/*发送是否打开验证的mqtt给后端验证*/ /*发送是否打开验证的mqtt给后端验证*/
......
...@@ -18,7 +18,7 @@ int receive_jwt(cJSON *body);//jwt验证 ...@@ -18,7 +18,7 @@ int receive_jwt(cJSON *body);//jwt验证
int message2006_verify(cJSON *body); int message2006_verify(cJSON *body);
/*接收到是否打开验证的函数*/ /*接收到是否打开验证的函数(2013 仅接受加密 body)*/
int message2013_recverigy_open(cJSON *body); int message2013_recverigy_open(cJSON *body);
/*发送是否打开验证的mqtt给后端验证初始化(首次发送3013)*/ /*发送是否打开验证的mqtt给后端验证初始化(首次发送3013)*/
......
...@@ -9,4 +9,4 @@ file perms = 600 ...@@ -9,4 +9,4 @@ file perms = 600
millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n" millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n"
[rules] [rules]
my_log.* "/home/orangepi/car/master/log/log_2026-05-22.log"; millisecond my_log.* "/home/orangepi/car/master/log/log_2026-06-10.log"; millisecond
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment