261 lines
7.1 KiB
C
261 lines
7.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <sys/stat.h>
|
|
#include <dirent.h>
|
|
#include "auth.h"
|
|
#include "config.h"
|
|
#include "utils.h"
|
|
|
|
#define TOKEN_DIR "/tmp/trashbox_tokens"
|
|
#define TOKEN_SALT "TrashBoxSecretSalt2024"
|
|
|
|
// ============================================
|
|
// ПРОВЕРКА ПАРОЛЯ
|
|
// ============================================
|
|
|
|
int check_folder_password(const char *folder_name, const char *password) {
|
|
if (!password || !folder_name || password[0] == '\0') return 0;
|
|
|
|
FILE *f = fopen(g_config.passwd_file, "r");
|
|
if (!f) {
|
|
fprintf(stderr, "DEBUG: cannot open passwd file: %s\n", g_config.passwd_file);
|
|
return 0;
|
|
}
|
|
|
|
char line[512];
|
|
while (fgets(line, sizeof(line), f)) {
|
|
line[strcspn(line, "\r\n")] = 0;
|
|
char *colon = strchr(line, ':');
|
|
if (!colon) continue;
|
|
*colon = '\0';
|
|
char *folder = line;
|
|
char *pass = colon + 1;
|
|
const char *last_slash = strrchr(folder_name, '/');
|
|
const char *base_name = last_slash ? last_slash + 1 : folder_name;
|
|
|
|
if (strcmp(folder, folder_name) == 0 || strcmp(folder, base_name) == 0) {
|
|
fclose(f);
|
|
return strcmp(pass, password) == 0;
|
|
}
|
|
}
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
int is_folder_protected(const char *folder_path) {
|
|
if (!folder_path || folder_path[0] == '\0') return 0;
|
|
|
|
FILE *f = fopen(g_config.passwd_file, "r");
|
|
if (!f) return 0;
|
|
|
|
char line[512];
|
|
while (fgets(line, sizeof(line), f)) {
|
|
line[strcspn(line, "\r\n")] = 0;
|
|
char *colon = strchr(line, ':');
|
|
if (!colon) continue;
|
|
*colon = '\0';
|
|
const char *last_slash = strrchr(folder_path, '/');
|
|
const char *folder_name = last_slash ? last_slash + 1 : folder_path;
|
|
if (strcmp(line, folder_path) == 0 || strcmp(line, folder_name) == 0) {
|
|
fclose(f);
|
|
return 1;
|
|
}
|
|
}
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
// ============================================
|
|
// ЛИМИТ ПОПЫТОК
|
|
// ============================================
|
|
|
|
void get_attempts_file(char *buf, size_t size, const char *folder_name, const char *ip) {
|
|
char safe_folder[256];
|
|
strncpy(safe_folder, folder_name, sizeof(safe_folder) - 1);
|
|
safe_folder[sizeof(safe_folder) - 1] = '\0';
|
|
for (char *p = safe_folder; *p; p++) {
|
|
if (*p == '/' || *p == '\\' || *p == '.') *p = '_';
|
|
}
|
|
snprintf(buf, size, "/tmp/trashbox_attempts_%s_%s", safe_folder, ip);
|
|
}
|
|
|
|
int check_attempts(const char *folder_name, const char *ip) {
|
|
if (!folder_name || !ip) return 0;
|
|
|
|
char attempts_file[256];
|
|
get_attempts_file(attempts_file, sizeof(attempts_file), folder_name, ip);
|
|
|
|
FILE *f = fopen(attempts_file, "r");
|
|
if (!f) return 0;
|
|
|
|
int attempts;
|
|
time_t first_attempt_time;
|
|
|
|
if (fscanf(f, "%d %ld", &attempts, &first_attempt_time) != 2) {
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
fclose(f);
|
|
|
|
time_t now = time(NULL);
|
|
if (now - first_attempt_time > g_config.block_time) {
|
|
unlink(attempts_file);
|
|
return 0;
|
|
}
|
|
|
|
return attempts >= g_config.max_attempts;
|
|
}
|
|
|
|
void add_attempt(const char *folder_name, const char *ip) {
|
|
if (!folder_name || !ip) return;
|
|
|
|
char attempts_file[256];
|
|
get_attempts_file(attempts_file, sizeof(attempts_file), folder_name, ip);
|
|
|
|
int attempts = 0;
|
|
time_t first_attempt_time = time(NULL);
|
|
|
|
FILE *f = fopen(attempts_file, "r");
|
|
if (f) {
|
|
fscanf(f, "%d %ld", &attempts, &first_attempt_time);
|
|
fclose(f);
|
|
attempts++;
|
|
} else {
|
|
attempts = 1;
|
|
}
|
|
|
|
f = fopen(attempts_file, "w");
|
|
if (f) {
|
|
fprintf(f, "%d %ld\n", attempts, first_attempt_time);
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
void clear_attempts(const char *folder_name, const char *ip) {
|
|
if (!folder_name || !ip) return;
|
|
|
|
char attempts_file[256];
|
|
get_attempts_file(attempts_file, sizeof(attempts_file), folder_name, ip);
|
|
unlink(attempts_file);
|
|
}
|
|
|
|
// ============================================
|
|
// ТОКЕНЫ
|
|
// ============================================
|
|
|
|
char* generate_token(const char *path) {
|
|
// ============================================
|
|
// ФИНАЛЬНЫЙ ФИКС: очищаем путь от любых нежелательных символов
|
|
// ============================================
|
|
char clean_path[1024];
|
|
strncpy(clean_path, path, sizeof(clean_path) - 1);
|
|
clean_path[sizeof(clean_path) - 1] = '\0';
|
|
|
|
// Удаляем всё после '%' и другие нежелательные символы
|
|
char *p = clean_path;
|
|
while (*p) {
|
|
if (*p == '%' || *p == '\n' || *p == '\r') {
|
|
*p = '\0';
|
|
break;
|
|
}
|
|
p++;
|
|
}
|
|
|
|
// Если путь пустой — используем "default"
|
|
if (clean_path[0] == '\0') {
|
|
strcpy(clean_path, "default");
|
|
}
|
|
|
|
mkdir(TOKEN_DIR, 0700);
|
|
|
|
time_t now = time(NULL);
|
|
char input[1024];
|
|
snprintf(input, sizeof(input), "%ld_%s_%s", now, clean_path, TOKEN_SALT);
|
|
|
|
unsigned long hash = 0;
|
|
for (int i = 0; input[i]; i++) {
|
|
hash = hash * 31 + input[i];
|
|
}
|
|
|
|
char token[256];
|
|
snprintf(token, sizeof(token), "%lx_%ld", hash, now);
|
|
|
|
char token_file[512];
|
|
snprintf(token_file, sizeof(token_file), "%s/%s", TOKEN_DIR, token);
|
|
|
|
FILE *f = fopen(token_file, "w");
|
|
if (!f) return NULL;
|
|
fprintf(f, "%s", clean_path);
|
|
fclose(f);
|
|
|
|
return strdup(token);
|
|
}
|
|
|
|
int check_token(const char *token, char *path, size_t path_size) {
|
|
if (!token || !token[0]) return 0;
|
|
|
|
char token_file[512];
|
|
snprintf(token_file, sizeof(token_file), "%s/%s", TOKEN_DIR, token);
|
|
|
|
FILE *f = fopen(token_file, "r");
|
|
if (!f) return 0;
|
|
|
|
char stored_path[1024];
|
|
if (fgets(stored_path, sizeof(stored_path), f) == NULL) {
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
fclose(f);
|
|
|
|
stored_path[strcspn(stored_path, "\n")] = '\0';
|
|
|
|
// Обрезаем % в конце
|
|
char *pp = stored_path;
|
|
while (*pp) {
|
|
if (*pp == '%' || *pp == '\n' || *pp == '\r') {
|
|
*pp = '\0';
|
|
break;
|
|
}
|
|
pp++;
|
|
}
|
|
|
|
struct stat st;
|
|
if (stat(token_file, &st) != 0) return 0;
|
|
|
|
time_t now = time(NULL);
|
|
if (now - st.st_mtime > 3600) {
|
|
unlink(token_file);
|
|
return 0;
|
|
}
|
|
|
|
strncpy(path, stored_path, path_size - 1);
|
|
path[path_size - 1] = '\0';
|
|
|
|
return 1;
|
|
}
|
|
|
|
void cleanup_old_tokens(void) {
|
|
DIR *dir = opendir(TOKEN_DIR);
|
|
if (!dir) return;
|
|
|
|
struct dirent *entry;
|
|
time_t now = time(NULL);
|
|
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
if (entry->d_name[0] == '.') continue;
|
|
|
|
char token_file[512];
|
|
snprintf(token_file, sizeof(token_file), "%s/%s", TOKEN_DIR, entry->d_name);
|
|
|
|
struct stat st;
|
|
if (stat(token_file, &st) == 0) {
|
|
if (now - st.st_mtime > 3600) {
|
|
unlink(token_file);
|
|
}
|
|
}
|
|
}
|
|
closedir(dir);
|
|
} |