/** * MANAGE.C * * @author HaxorSec */ #include #include #include #include #include #include #include #include #include #define CONFIG_FILE_NAME "/.minisocket_secrets.conf" #define USER_EXECUTABLE "/usr/bin/mini-nc" #define MENU_ITEM_COUNT 5 #define COLOR_GREEN "\033[1;32m" #define COLOR_RED "\033[1;31m" #define COLOR_YELLOW "\033[1;33m" #define COLOR_BLUE "\033[1;34m" #define COLOR_CYAN "\033[1;36m" #define COLOR_ORANGE "\033[38;5;208m" #define COLOR_RESET "\033[0m" void init_terminal(); void restore_terminal(); void enable_raw_mode(); void disable_raw_mode(); void get_config_path(char *buffer, size_t size); void press_enter_to_continue(); void clear_screen(); void trim_newline(char *str); void print_menu(int highlight); int get_interactive_choice(); void handle_add_secret(); int list_secrets(int show_header); void handle_connect(); void handle_delete_secret(); struct termios orig_termios; int raw_mode_enabled = 0; int main() { if (access(USER_EXECUTABLE, X_OK) != 0) { fprintf(stderr, COLOR_RED "[ERROR] Program '%s' was not found or could not be executed.\n" COLOR_RESET, USER_EXECUTABLE); return 1; } init_terminal(); enable_raw_mode(); int choice = 0; while (choice != MENU_ITEM_COUNT) { choice = get_interactive_choice(); disable_raw_mode(); clear_screen(); switch (choice) { case 1: handle_connect(); break; case 2: handle_add_secret(); break; case 3: printf(COLOR_CYAN "--- List of Saved Secrets ---\n\n" COLOR_RESET); if (list_secrets(0) == 0) printf("There are no secrets yet hidden.\n"); press_enter_to_continue(); break; case 4: handle_delete_secret(); break; case 5: printf("Exit manager...\n"); break; } if (choice != MENU_ITEM_COUNT) { enable_raw_mode(); } } return 0; } void restore_terminal() { if (raw_mode_enabled) { disable_raw_mode(); } } void init_terminal() { if (!isatty(STDIN_FILENO)) return; if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) { perror("tcgetattr"); exit(1); } atexit(restore_terminal); } void enable_raw_mode() { if (!isatty(STDIN_FILENO)) return; int flags = fcntl(STDIN_FILENO, F_GETFL, 0); if (flags != -1) { fcntl(STDIN_FILENO, F_SETFL, flags & ~O_NONBLOCK); } struct termios raw = orig_termios; raw.c_lflag &= ~(ECHO | ICANON); raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { perror("tcsetattr (enable)"); exit(1); } raw_mode_enabled = 1; } void disable_raw_mode() { if (!isatty(STDIN_FILENO)) return; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) { perror("tcsetattr (disable)"); } raw_mode_enabled = 0; } void clear_screen() { printf("\x1b[2J\x1b[H"); } void print_menu(int highlight) { clear_screen(); const char* menu_items[MENU_ITEM_COUNT] = { "Connect", "Add New Secret", "Secret List", "Delete Secret", "Exit" }; const char* colors[MENU_ITEM_COUNT] = {COLOR_GREEN, COLOR_CYAN, "", COLOR_RED, ""}; printf(COLOR_BLUE "========================================\n"); printf(" Minisocket User Connection Manager\n"); printf(" HaxorSec@2025\n"); printf("========================================\n\n" COLOR_RESET); printf(COLOR_YELLOW "Use [↑][↓] to navigate and [Enter] to select:\n" COLOR_RESET); for (int i = 0; i < MENU_ITEM_COUNT; i++) { if (i + 1 == highlight) { printf(COLOR_ORANGE " >> %s%s%s\n", colors[i], menu_items[i], COLOR_RESET); } else { printf(" %s%s%s\n", colors[i], menu_items[i], COLOR_RESET); } } } int get_interactive_choice() { int selection = 1; char c; while (1) { print_menu(selection); ssize_t read_result = read(STDIN_FILENO, &c, 1); if (read_result != 1) { if (read_result == -1) perror("read"); exit(1); } if (c == '\033') { char seq[2]; if (read(STDIN_FILENO, &seq[0], 1) != 1) continue; if (read(STDIN_FILENO, &seq[1], 1) != 1) continue; if (seq[0] == '[') { if (seq[1] == 'A') { if (--selection < 1) selection = MENU_ITEM_COUNT; } else if (seq[1] == 'B') { if (++selection > MENU_ITEM_COUNT) selection = 1; } } } else if (c == '\n' || c == '\r') { return selection; } else if (c > '0' && c <= ('0' + MENU_ITEM_COUNT)) { return c - '0'; } } } void get_config_path(char *buffer, size_t size) { const char *home_dir = getenv("HOME"); if (home_dir == NULL) { strncpy(buffer, ".minisocket_secrets.conf", size); } else { snprintf(buffer, size, "%s%s", home_dir, CONFIG_FILE_NAME); } } void trim_newline(char *str) { str[strcspn(str, "\n\r")] = 0; } void press_enter_to_continue() { printf("\nPress [Enter] to return to the menu..."); fflush(stdout); tcflush(STDIN_FILENO, TCIFLUSH); int c; while ((c = getchar()) != '\n' && c != EOF) {} } void handle_add_secret() { char label[100], secret[100]; char config_path[PATH_MAX]; get_config_path(config_path, sizeof(config_path)); printf(COLOR_CYAN "--- Add New Secret ---\n\n" COLOR_RESET); printf("Enter Label (example: workspace, office_server): "); fgets(label, sizeof(label), stdin); trim_newline(label); printf("Enter Secret Key: "); fgets(secret, sizeof(secret), stdin); trim_newline(secret); if (strlen(label) == 0 || strlen(secret) == 0) { printf(COLOR_RED "\nLabel and Secret cannot be empty!\n" COLOR_RESET); press_enter_to_continue(); return; } FILE *fp = fopen(config_path, "a"); if (!fp) { perror("Failed to open configuration file"); press_enter_to_continue(); return; } fprintf(fp, "%s:%s\n", label, secret); fclose(fp); printf(COLOR_GREEN "\nSecret '%s' successfully saved!\n" COLOR_RESET, label); press_enter_to_continue(); } int list_secrets(int show_header) { char config_path[PATH_MAX]; get_config_path(config_path, sizeof(config_path)); FILE *fp = fopen(config_path, "r"); if (!fp) return 0; if (show_header) printf(COLOR_CYAN "--- Select Secret to Connect ---\n\n" COLOR_RESET); char line[256]; int count = 0; while (fgets(line, sizeof(line), fp)) { count++; char *secret_ptr = strchr(line, ':'); if (secret_ptr) { *secret_ptr = '\0'; printf(" [%d] %s\n", count, line); } } fclose(fp); return count; } void handle_connect() { int total_secrets = list_secrets(1); if (total_secrets == 0) { printf("There are no secrets yet...\n"); press_enter_to_continue(); return; } printf("\nType the number to connect (or 0 to cancel): "); char input[10]; int choice = 0; if (fgets(input, sizeof(input), stdin) != NULL) choice = atoi(input); if (choice <= 0 || choice > total_secrets) { printf(COLOR_YELLOW "Connection aborted.\n" COLOR_RESET); press_enter_to_continue(); return; } char config_path[PATH_MAX]; get_config_path(config_path, sizeof(config_path)); FILE *fp = fopen(config_path, "r"); if (!fp) return; char line[256], target_secret[100] = ""; int current_line = 0; while(fgets(line, sizeof(line), fp)) { current_line++; if (current_line == choice) { char *secret_ptr = strchr(line, ':'); if(secret_ptr) { strcpy(target_secret, secret_ptr + 1); trim_newline(target_secret); } break; } } fclose(fp); if (strlen(target_secret) > 0) { disable_raw_mode(); clear_screen(); printf("Trying to connect to shell with selected secret...\n"); pid_t pid = fork(); if (pid == 0) { char *args[] = {USER_EXECUTABLE, "-s", target_secret, NULL}; execv(USER_EXECUTABLE, args); perror("execv user"); exit(1); } else if (pid > 0) { int status; waitpid(pid, &status, 0); printf("\nThe shell session has been closed.\n"); press_enter_to_continue(); } else { perror("fork"); } } } void handle_delete_secret() { printf(COLOR_RED "---Delete Secret ---\n\n" COLOR_RESET); int total_secrets = list_secrets(0); if (total_secrets == 0) { printf("There are no secrets to delete.\n"); press_enter_to_continue(); return; } printf("\nType a number to delete (or 0 to cancel): "); char input[10]; int choice = 0; if (fgets(input, sizeof(input), stdin) != NULL) choice = atoi(input); if (choice <= 0 || choice > total_secrets) { printf(COLOR_YELLOW "Deletion cancelled.\n" COLOR_RESET); press_enter_to_continue(); return; } char config_path[PATH_MAX], temp_path[PATH_MAX + 4]; get_config_path(config_path, sizeof(config_path)); snprintf(temp_path, sizeof(temp_path), "%s.tmp", config_path); FILE *orig_fp = fopen(config_path, "r"); FILE *temp_fp = fopen(temp_path, "w"); if (!orig_fp || !temp_fp) { fprintf(stderr, COLOR_RED "Failed to process configuration file.\n" COLOR_RESET); if (orig_fp) fclose(orig_fp); if (temp_fp) fclose(temp_fp); press_enter_to_continue(); return; } char line[256], deleted_label[100] = ""; int current_line = 0; while(fgets(line, sizeof(line), orig_fp)) { current_line++; if (current_line != choice) { fputs(line, temp_fp); } else { char* p = strchr(line, ':'); if (p) *p = '\0'; strncpy(deleted_label, line, sizeof(deleted_label)-1); deleted_label[sizeof(deleted_label)-1] = '\0'; } } fclose(orig_fp); fclose(temp_fp); if (remove(config_path) == 0) { if (rename(temp_path, config_path) == 0) { printf(COLOR_GREEN "\nSecret '%s' was successfully deleted.\n" COLOR_RESET, deleted_label); } else { perror("rename"); printf(COLOR_RED "Failed to restore configuration file!\n" COLOR_RESET); } } else { perror("remove"); printf(COLOR_RED "Failed to delete old configuration file!\n" COLOR_RESET); } press_enter_to_continue(); }