Files
Trashbox/src/auth.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);
}