-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheula.py
More file actions
189 lines (156 loc) · 7.06 KB
/
Copy patheula.py
File metadata and controls
189 lines (156 loc) · 7.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/python3
"""EULA/Disclaimer module for the pentesting framework."""
import curses
import os
CONFIG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config")
EULA_FILE = os.path.join(CONFIG_DIR, "eula.txt")
def has_accepted_eula():
"""Check if user has permanently accepted the EULA."""
if os.path.exists(EULA_FILE):
try:
with open(EULA_FILE, "r") as f:
return f.read().strip() == "1"
except Exception:
return False
return False
def save_eula_acceptance():
"""Save permanent EULA acceptance to file."""
os.makedirs(CONFIG_DIR, exist_ok=True)
with open(EULA_FILE, "w") as f:
f.write("1")
def show_eula(stdscr):
"""Display the EULA disclaimer screen with Accept/Deny navigation."""
curses.curs_set(0)
curses.start_color()
curses.use_default_colors()
# Color pairs
curses.init_pair(1, curses.COLOR_RED, -1) # Warning/accent
curses.init_pair(2, curses.COLOR_WHITE, -1) # Normal text
curses.init_pair(3, 8, -1) # Dark gray notes
curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_GREEN) # Selected Accept
curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_RED) # Selected Deny
curses.init_pair(6, curses.COLOR_WHITE, -1) # Unselected button
selected = 0 # 0=Accept, 1=Deny
disclaimer_lines = [
"",
"This framework is designed EXCLUSIVELY for authorized",
"security auditing and educational purposes.",
"",
"You MUST have explicit written authorization before",
"using this tool on any system or network.",
"",
"Sami does NOT assume any responsibility for misuse",
"or unauthorized activity. The user is solely liable",
"for ensuring compliance with applicable laws.",
"",
]
while True:
stdscr.clear()
h, w = stdscr.getmaxyx()
# Calculate box dimensions
max_line_len = max(len(line) for line in disclaimer_lines) if disclaimer_lines else 0
title = "!! DISCLAIMER / AVISO LEGAL !!"
box_w = max(max_line_len + 8, len(title) + 6, 52)
box_h = len(disclaimer_lines) + 6
box_x = max(0, (w - box_w) // 2)
box_y = max(0, (h - box_h) // 2)
# Top border
stdscr.addstr(box_y, box_x, "+" + "=" * (box_w - 2) + "+", curses.color_pair(1) | curses.A_BOLD)
# Title line
title_pad = box_w - 2 - len(title)
left_pad = title_pad // 2
stdscr.addstr(box_y + 1, box_x, "|", curses.color_pair(1) | curses.A_BOLD)
stdscr.addstr(box_y + 1, box_x + 1, " " * left_pad, curses.color_pair(1))
stdscr.addstr(box_y + 1, box_x + 1 + left_pad, title, curses.color_pair(1) | curses.A_BOLD)
right_fill = box_w - 2 - left_pad - len(title)
if right_fill > 0:
stdscr.addstr(box_y + 1, box_x + 1 + left_pad + len(title), " " * right_fill, curses.color_pair(1))
stdscr.addstr(box_y + 1, box_x + box_w - 1, "|", curses.color_pair(1) | curses.A_BOLD)
# Separator
stdscr.addstr(box_y + 2, box_x, "+" + "=" * (box_w - 2) + "+", curses.color_pair(1) | curses.A_BOLD)
# Content lines
for i, line in enumerate(disclaimer_lines):
y = box_y + 3 + i
stdscr.addstr(y, box_x, "|", curses.color_pair(2))
line_pad = box_w - 2 - len(line)
left_content_pad = line_pad // 2
stdscr.addstr(y, box_x + 1, " " * left_content_pad, curses.color_pair(2))
if line:
stdscr.addstr(y, box_x + 1 + left_content_pad, line, curses.color_pair(2))
right_content = box_w - 2 - left_content_pad - len(line)
if right_content > 0:
stdscr.addstr(y, box_x + box_w - 1 - right_content, " " * right_content, curses.color_pair(2))
stdscr.addstr(y, box_x + box_w - 1, "|", curses.color_pair(2))
# Separator before buttons
btn_sep_y = box_y + 3 + len(disclaimer_lines)
stdscr.addstr(btn_sep_y, box_x, "+" + "=" * (box_w - 2) + "+", curses.color_pair(1) | curses.A_BOLD)
# Buttons
accept_str = " Accept "
deny_str = " Deny "
buttons_y = btn_sep_y + 1
total_btn_w = len(accept_str) + 5 + len(deny_str)
btn_start_x = box_x + (box_w - total_btn_w) // 2
# Row background
stdscr.addstr(buttons_y, box_x, "|", curses.color_pair(2))
stdscr.addstr(buttons_y, box_x + 1, " " * (box_w - 2), curses.color_pair(2))
if selected == 0:
stdscr.addstr(buttons_y, btn_start_x, accept_str, curses.color_pair(4) | curses.A_BOLD)
stdscr.addstr(buttons_y, btn_start_x + len(accept_str) + 5, deny_str, curses.color_pair(6))
else:
stdscr.addstr(buttons_y, btn_start_x, accept_str, curses.color_pair(6))
stdscr.addstr(buttons_y, btn_start_x + len(accept_str) + 5, deny_str, curses.color_pair(5) | curses.A_BOLD)
stdscr.addstr(buttons_y, box_x + box_w - 1, "|", curses.color_pair(2))
# Bottom border
stdscr.addstr(buttons_y + 1, box_x, "+" + "=" * (box_w - 2) + "+", curses.color_pair(1) | curses.A_BOLD)
# Notes in dark gray
note1 = "Shift+Enter or P = Accept permanently (won't show again)"
note2 = "Navigate: Left/Right or A/D | Select: Enter"
note_y = buttons_y + 3
if note_y < h - 1:
stdscr.addstr(note_y, max(0, (w - len(note1)) // 2), note1, curses.color_pair(3))
if note_y + 1 < h - 1:
stdscr.addstr(note_y + 1, max(0, (w - len(note2)) // 2), note2, curses.color_pair(3))
stdscr.refresh()
# Handle key input
key = stdscr.getch()
if key in (curses.KEY_LEFT, ord('a'), ord('A')):
selected = 0
elif key in (curses.KEY_RIGHT, ord('d'), ord('D')):
selected = 1
elif key in (10, 13, curses.KEY_ENTER):
if selected == 0:
return "accept"
else:
return "deny"
elif key in (ord('p'), ord('P')):
if selected == 0:
return "permanent"
elif key == 27: # ESC - check for Shift+Enter escape sequence
stdscr.nodelay(True)
seq = ''
try:
while True:
ch = stdscr.getch()
if ch == -1:
break
seq += chr(ch)
except Exception:
pass
stdscr.nodelay(False)
# Shift+Enter in Kitty: \x1b[13;2u
# Shift+Enter in xterm: \x1b[27;2;13~
if '13;2' in seq or '2;13' in seq:
if selected == 0:
return "permanent"
def check_eula():
"""Main EULA check. Returns True if user can proceed, False if denied."""
if has_accepted_eula():
return True
result = curses.wrapper(show_eula)
if result == "accept":
return True
elif result == "permanent":
save_eula_acceptance()
return True
else:
return False