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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
|
#!/usr/bin/env python3
import os
import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
# Kurulum bayrağının konumu: Kullanıcının ana dizininde, yazma izni sorunu yaşamamak için.
SETUP_FLAG_FILE = os.path.expanduser("~/.setup_tamam")
# -------------------- Yardımcı Fonksiyonlar --------------------
def run_as_root(cmd_list):
"""
Belirtilen komut listesini pkexec kullanarak root ayrıcalıklarıyla çalıştırır.
Eğer kullanıcı root şifresini girmeyi iptal ederse, uygun uyarı mesajı verir.
"""
try:
subprocess.run(["pkexec"] + cmd_list, check=True)
except subprocess.CalledProcessError as e:
if e.returncode == 1:
raise RuntimeError("Root yetkilendirmesi iptal edildi! Lütfen root şifresini giriniz. Sistem, root yetkisi ile çalıştırılmalıdır.")
raise RuntimeError(f"Komut hatası: {e.cmd}, Çıkış kodu: {e.returncode}")
def set_setup_complete_flag():
"""
Kurulumun tamamlandığını belirten bayrak dosyasını oluşturur.
Böylece sonraki çalıştırmalarda kurulum sihirbazı tekrarlanmaz.
"""
try:
with open(SETUP_FLAG_FILE, "w") as file:
file.write("setup_complete")
except Exception as ex:
print(f"Kurulum bayrağı ayarlanırken hata: {ex}")
def read_users():
"""
Sistemdeki mevcut kullanıcıları /etc/passwd dosyasından okur.
"""
users = []
try:
with open("/etc/passwd", "r") as file:
for line in file:
parts = line.split(":")
if parts:
users.append(parts[0])
except Exception as ex:
print(f"Kullanıcılar okunurken hata: {ex}")
return users
def get_mount_device(mount_point):
"""
Belirtilen mount noktasının bağlı olduğu aygıtı /proc/mounts dosyasından bulur.
"""
try:
with open("/proc/mounts", "r") as file:
for line in file:
parts = line.split()
if parts[1] == mount_point:
return parts[0]
except Exception:
pass
return None
def overlayroot_status():
"""
Sistem Dondurma durumunu, /media/root-rw montajı ve /etc/overlayroot.conf dosyasına göre belirler.
"""
if get_mount_device("/media/root-rw"):
return True
conf_path = "/etc/overlayroot.conf"
if os.path.exists(conf_path):
try:
with open(conf_path, "r") as file:
content = file.read()
return "tmpfs" in content
except Exception:
return False
else:
try:
result = subprocess.run(["dpkg", "-l", "romtal-sistem-dondurma"],
capture_output=True, text=True)
return "overlayroot" in result.stdout
except Exception:
return False
# -------------------- Kurulum Sihirbazı (Setup Wizard) --------------------
class SetupWizard(Gtk.Window):
"""
Üç aşamalı kurulum sihirbazı:
1. Açıklama Sayfası: Neden non‑root kullanıcı kullanılmalı? İki seçenek sunar.
2. Kullanıcı Oluşturma Sayfası: Önerilen "ogrenci" adında, sınırlı yetkili kullanıcı oluşturulur.
3. Onay Sayfası: İşlemin tamamlandığı bildirildiği sayfa.
NOT: Notebook sekmeleri gizlenmiştir; kullanıcı yalnızca sayfa içindeki gezinme butonlarıyla ilerler.
"""
def __init__(self):
super().__init__(title="Kurulum Sihirbazı")
self.set_default_size(600, 500)
self.set_border_width(20)
self.notebook = Gtk.Notebook()
self.notebook.set_show_tabs(False)
self.add(self.notebook)
self.create_explanation_page()
self.create_user_creation_page()
self.create_confirmation_page()
def create_explanation_page(self):
page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
page.set_border_width(15)
explanation_label = Gtk.Label()
explanation_label.set_markup(
"<b>R.O.M.T.A.L | https://rasimoneltml.meb.k12.tr/</b>\n\n"
"<b>NOT:Eğer root şifreniz kolay tahmin edilebilir durumda ise hemen sudo passwd root komutunu kullanarak güçlü bir şifre belirleyin.</b>\n\n"
"<b>Neden Yeni Bir Kullanıcı Oluşturmalısınız?</b>\n\n"
"Bu sistem, güvenlik açısından root yetkisinin kullanılmaması gereken bir yapıya sahiptir. "
"Root yetkisine sahip bir kullanıcı, sistem üzerinde tam kontrol sağlar ve güvenlik risklerini artırır.\n\n"
"Eğer sisteminizde zaten root yetkisine sahip olmayan bir kullanıcı mevcutsa, bu adımı atlayabilirsiniz. "
"Aksi halde, lütfen 'Devam Et' butonuna basarak örneğin 'ogrenci' adlı sınırlı yetkili bir kullanıcı oluşturun."
)
explanation_label.set_line_wrap(True)
page.pack_start(explanation_label, True, True, 0)
nav_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
skip_button = Gtk.Button(label="Atla")
continue_button = Gtk.Button(label="Devam Et")
skip_button.connect("clicked", self.on_skip_clicked)
continue_button.connect("clicked", self.on_continue_to_creation)
nav_box.pack_start(skip_button, True, True, 0)
nav_box.pack_start(continue_button, True, True, 0)
page.pack_start(nav_box, False, False, 0)
self.notebook.append_page(page, Gtk.Label(label="Açıklama"))
def create_user_creation_page(self):
page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
page.set_border_width(15)
instruction_label = Gtk.Label(
label="Yeni bir kullanıcı oluşturmak için lütfen bilgileri giriniz. "
"Önerilen kullanıcı adı: 'ogrenci'"
)
instruction_label.set_line_wrap(True)
page.pack_start(instruction_label, False, False, 0)
form_grid = Gtk.Grid(column_spacing=10, row_spacing=10)
username_label = Gtk.Label(label="Kullanıcı Adı:")
self.username_entry = Gtk.Entry()
self.username_entry.set_text("ogrenci")
self.username_entry.set_placeholder_text("örn: ogrenci")
password_label = Gtk.Label(label="Şifre:")
self.password_entry = Gtk.Entry()
self.password_entry.set_placeholder_text("Güçlü bir şifre giriniz")
self.password_entry.set_visibility(False)
form_grid.attach(username_label, 0, 0, 1, 1)
form_grid.attach(self.username_entry, 1, 0, 1, 1)
form_grid.attach(password_label, 0, 1, 1, 1)
form_grid.attach(self.password_entry, 1, 1, 1, 1)
page.pack_start(form_grid, False, False, 0)
nav_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
back_button = Gtk.Button(label="Geri")
create_button = Gtk.Button(label="Kullanıcı Oluştur")
back_button.connect("clicked", lambda w: self.notebook.set_current_page(0))
create_button.connect("clicked", self.on_create_user)
nav_box.pack_start(back_button, True, True, 0)
nav_box.pack_start(create_button, True, True, 0)
page.pack_start(nav_box, False, False, 0)
self.notebook.append_page(page, Gtk.Label(label="Kullanıcı Oluşturma"))
def create_confirmation_page(self):
page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
page.set_border_width(15)
confirmation_label = Gtk.Label(
label="Kullanıcı başarıyla oluşturuldu.\nKurulum tamamlandı.\n"
"Ana arayüze geçmek için 'Devam Et' butonuna basınız."
)
confirmation_label.set_line_wrap(True)
page.pack_start(confirmation_label, True, True, 0)
nav_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
back_button = Gtk.Button(label="Geri")
continue_button = Gtk.Button(label="Devam Et")
back_button.connect("clicked", lambda w: self.notebook.set_current_page(1))
continue_button.connect("clicked", self.on_final_continue)
nav_box.pack_start(back_button, True, True, 0)
nav_box.pack_start(continue_button, True, True, 0)
page.pack_start(nav_box, False, False, 0)
self.notebook.append_page(page, Gtk.Label(label="Onay"))
def on_skip_clicked(self, widget):
"""
Eğer sisteminizde root yetkisine sahip olmayan bir kullanıcı mevcutsa,
bu adımı atlayarak ana arayüze geçin.
"""
set_setup_complete_flag()
self.hide()
main_app = SistemDondurmaGUI()
main_app.connect("destroy", Gtk.main_quit)
main_app.show_all()
def on_continue_to_creation(self, widget):
"""
'Devam Et' butonuna basıldığında, kullanıcı oluşturma sayfasına geçiş yapılır.
"""
self.notebook.set_current_page(1)
def on_create_user(self, widget):
"""
Kullanıcı adı ve şifre bilgilerini alır, ardından önerilen non‑root kullanıcıyı oluşturur.
Eğer girilen kullanıcı adı zaten sistemde mevcutsa hata mesajı gösterip farklı bir isim istenir.
Kullanıcı oluşturma ve şifre ayarlama işlemleri tek bir pkexec çağrısında birleştirilmiştir.
"""
username = self.username_entry.get_text().strip()
password = self.password_entry.get_text().strip()
if not username or not password:
self.show_dialog("Kullanıcı adı ve şifre boş bırakılamaz!", True)
return
if username in read_users():
self.show_dialog(f"{username} adlı kullanıcı zaten mevcut! Lütfen farklı bir kullanıcı adı giriniz.", True)
return
try:
cmd = ["sh", "-c", f"useradd -m --shell /bin/bash {username} && echo '{username}:{password}' | chpasswd"]
run_as_root(cmd)
self.show_dialog(f"{username} adlı kullanıcı başarıyla oluşturuldu.", False)
self.notebook.set_current_page(2)
except Exception as e:
self.show_dialog(f"Kullanıcı oluşturulurken hata: {e}", True)
def on_final_continue(self, widget):
"""
Kurulum tamamlandığında bayrak dosyası oluşturulur ve ana arayüz açılır.
"""
set_setup_complete_flag()
self.hide()
main_app = SistemDondurmaGUI()
main_app.connect("destroy", Gtk.main_quit)
main_app.show_all()
def show_dialog(self, message, is_error=False):
dialog = Gtk.MessageDialog(
transient_for=self,
flags=0,
message_type=Gtk.MessageType.ERROR if is_error else Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
text=message
)
dialog.run()
dialog.destroy()
# -------------------- Ana Uygulama Arayüzü (Sistem Dondurma GUI) --------------------
class SistemDondurmaGUI(Gtk.Window):
def __init__(self):
super().__init__(title="R.O.M.T.A.L Sistem Dondurma")
self.set_default_size(500, 300)
self.set_border_width(20)
self.setup_css()
self.overlayroot_aktif = overlayroot_status()
self.create_ui()
def setup_css(self):
css = b"""
label { font-size: 14px; }
"""
style_provider = Gtk.CssProvider()
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
def create_ui(self):
grid = Gtk.Grid(column_spacing=10, row_spacing=10)
grid.set_column_homogeneous(True)
self.status_label = Gtk.Label()
self.enable_btn = Gtk.Button(label="Sistem Dondurma Aktif Et")
self.enable_btn.connect("clicked", self.enable_overlayroot)
self.disable_btn = Gtk.Button(label="Sistem Dondurma Devre Dışı")
self.disable_btn.connect("clicked", self.disable_overlayroot)
footer_label = Gtk.Label(label="R.O.M.T.A.L | https://rasimoneltml.meb.k12.tr/")
grid.attach(self.status_label, 0, 0, 2, 1)
grid.attach(self.enable_btn, 0, 1, 1, 1)
grid.attach(self.disable_btn, 1, 1, 1, 1)
grid.attach(footer_label, 0, 2, 2, 1)
self.add(grid)
self.update_status()
def update_status(self):
status_text = "Aktif" if self.overlayroot_aktif else "Devre Dışı"
self.status_label.set_markup(f"<b>Sistem Dondurma Durumu: {status_text}</b>")
self.enable_btn.set_sensitive(not self.overlayroot_aktif)
self.disable_btn.set_sensitive(self.overlayroot_aktif)
def show_dialog(self, message, is_error=False):
dialog = Gtk.MessageDialog(
transient_for=self,
flags=0,
message_type=Gtk.MessageType.ERROR if is_error else Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
text=message
)
dialog.run()
dialog.destroy()
def enable_overlayroot(self, widget):
try:
cmd = [
"sh", "-c",
("rm -f /etc/overlayroot.conf && "
"echo 'overlayroot_cfgdisk=\"disable\"' > /etc/overlayroot.conf && "
"echo 'overlayroot=\"tmpfs\"' >> /etc/overlayroot.conf")
]
run_as_root(cmd)
self.overlayroot_aktif = True
self.update_status()
self.show_dialog("Sistem Dondurma başarıyla aktif edildi.\nDeğişikliklerin geçerli olması için sistemi yeniden başlatın.")
except Exception as e:
self.show_dialog(f"Sistem Dondurma etkinleştirilirken hata: {e}", True)
def disable_overlayroot(self, widget):
"""
Sistem Dondurma işlemini devre dışı bırakır.
Eğer /media/root-ro mount edilmişse ilgili dizin üzerinden işlem yapılır;
aksi halde, /etc/overlayroot.conf dosyası doğrudan güncellenir.
"""
try:
device = get_mount_device("/media/root-ro")
if device:
cmd = [
"sh", "-c",
(f"mount -o remount,rw {device} && "
"rm -f /media/root-ro/etc/overlayroot.conf && "
"echo 'overlayroot_cfgdisk=\"disable\"' > /media/root-ro/etc/overlayroot.conf && "
"echo 'overlayroot=\"\"' >> /media/root-ro/etc/overlayroot.conf")
]
else:
cmd = [
"sh", "-c",
("rm -f /etc/overlayroot.conf && "
"echo 'overlayroot_cfgdisk=\"disable\"' > /etc/overlayroot.conf && "
"echo 'overlayroot=\"\"' >> /etc/overlayroot.conf")
]
run_as_root(cmd)
self.overlayroot_aktif = False
self.update_status()
self.show_dialog("Sistem Dondurma başarıyla devre dışı bırakıldı.\nDeğişikliklerin geçerli olması için sistemi yeniden başlatın.")
except Exception as e:
self.show_dialog(f"Sistem Dondurma devre dışı bırakılırken hata: {e}", True)
# -------------------- Uygulama Giriş Noktası --------------------
if __name__ == "__main__":
if not os.path.exists(SETUP_FLAG_FILE):
wizard = SetupWizard()
wizard.connect("destroy", Gtk.main_quit)
wizard.show_all()
else:
app = SistemDondurmaGUI()
app.connect("destroy", Gtk.main_quit)
app.show_all()
Gtk.main()
|