Skip to content

Commit 6d3f76a

Browse files
committed
Tilføj "GRUB: Skift kodeord"
1 parent 50af91b commit 6d3f76a

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

grub_set_password.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: "GRUB: Skift kodeord"
3+
parent: "System"
4+
source: scripts/grub_set_password.py
5+
parameters:
6+
- name: "Adgangskode"
7+
type: "password"
8+
default: null
9+
mandatory: true
10+
compatibility:
11+
- "22.04"
12+
- "BorgerPC"
13+
---
14+
15+
## Beskrivelse
16+
Dette script vil gøre at alle GRUB-menuerne på nær Ubuntu vil kræve en adgangskode for brugeren superuser.
17+
GRUB er den "Bootloader" som OS2borgerPC og Ubuntu benytter som standard. Den er ansvarlig for at starte operativsystemet.
18+
19+
Hvis du forsøger at redigere i indstillingerne til GRUB vil den også bede om brugernavn, som er "superuser".
20+
21+
Bemærk: Dette script køres automatisk under installationen, hvor der genereres et tilfældigt kodeord, så menuerne er beskyttet som standard. Hvis alt du ønsker er at sikre GRUB, er det derfor ikke nødvendigt at køre. Men hvis du gerne selv vil have adgang til at kunne gå ind at redigere GRUB under opstart kan du køre dette script.
22+
23+
Det er vigtigt at man afprøver scriptet på en enkelt borgerpc før man ruller det ud på dem alle sammen.
24+
25+
Det er også vigtigt at man husker det kodeord man sætter på GRUB.
26+
Det er dog muligt at ændre det igen hvis man glemmer kodeordet.
27+
28+
*Note: GRUB (og GRUB2) er kort sagt en "bootloader", ligesom BOOTMGR og NTLDR i Windows.
29+
Du kan læse nærmere om den her: https://help.ubuntu.com/community/Grub2
30+
31+
Dette script er blevet testet og virker på Ubuntu 22.04.

scripts/grub_set_password.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
================================================================
5+
HEADER
6+
================================================================
7+
% SYNOPSIS
8+
+ grub_set_password.py PASSWORD
9+
%
10+
% DESCRIPTION
11+
% This script locks all GRUB functionality, apart from booting with the
12+
% default options of an installed Linux-based operating system, behind the
13+
% given password.
14+
%
15+
% It takes one mandatory parameter: the password to use. (The GRUB username
16+
% associated with this password will always be "superuser".)
17+
%
18+
================================================================
19+
- IMPLEMENTATION
20+
- version grub_set_password.py (magenta.dk) 1.0.0
21+
- author Alexander Faithfull
22+
- copyright Copyright 2019, Magenta ApS
23+
- Portions copyright 2015 Ryan Sawhill Aroha
24+
- license GNU General Public License v3+
25+
- email af@magenta.dk
26+
-
27+
================================================================
28+
HISTORY
29+
2019/10/28 : af : Script created
30+
31+
================================================================
32+
END_OF_HEADER
33+
================================================================
34+
"""
35+
36+
from os import chmod, rename, urandom
37+
from sys import argv, exit
38+
from hashlib import pbkdf2_hmac
39+
from binascii import hexlify
40+
from subprocess import run, DEVNULL
41+
42+
# This function was taken from https://github.com/ryran/burg2-mkpasswd-pbkdf2
43+
# (and lightly tweaked for use here):
44+
#
45+
# Copyright 2015 Ryan Sawhill Aroha <rsaw@redhat.com>
46+
#
47+
# This program is free software: you can redistribute it and/or modify
48+
# it under the terms of the GNU General Public License as published by
49+
# the Free Software Foundation, either version 3 of the License, or
50+
# (at your option) any later version.
51+
#
52+
# This program is distributed in the hope that it will be useful,
53+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
54+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
55+
# General Public License <gnu.org/licenses/gpl.html> for more details.
56+
57+
58+
def grub2_mkpasswd_pbkdf2(passphrase, iterCount=100000, saltLength=64, debug=False):
59+
algo = "sha512"
60+
61+
binSalt = urandom(saltLength)
62+
hexSalt = hexlify(binSalt).decode("ascii")
63+
passHash = hexlify(
64+
pbkdf2_hmac(algo, passphrase.encode("ascii"), binSalt, iterCount)
65+
).decode("ascii")
66+
67+
if debug:
68+
print("algo = '{}'".format(algo))
69+
print("iterCount = '{}'".format(iterCount))
70+
print("saltLength = '{}'".format(saltLength))
71+
print("hexSalt = '{}'".format(hexSalt))
72+
return "grub.pbkdf2.{}.{}.{}.{}".format(algo, iterCount, hexSalt, passHash)
73+
74+
75+
# This patch tweaks the behaviour of update-grub(1) very slightly so that the
76+
# default launch entry for the installed operating system can be used even if
77+
# GRUB's other functions are password-protected
78+
diff = r"""\
79+
diff --git a/10_linux b/10_linux
80+
old mode 100644
81+
new mode 100755
82+
index 68700d9..b8ef18d
83+
--- a/10_linux
84+
+++ b/10_linux
85+
@@ -129,7 +129,7 @@ linux_entry ()
86+
fi
87+
echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
88+
else
89+
- echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
90+
+ echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --unrestricted {" | sed "s/^/$submenu_indentation/"
91+
fi
92+
if [ "$quick_boot" = 1 ]; then
93+
echo " recordfail" | sed "s/^/$submenu_indentation/"
94+
""" # noqa W291,E501
95+
96+
97+
def main():
98+
if len(argv) != 2:
99+
print("Syntax: {0} PASSWORD".format(argv[0]))
100+
exit(1)
101+
102+
# Since we manually patch /etc/grub.d/10_linux (and we need that patch to
103+
# remain in place, or the system will become unbootable without the
104+
# password), instruct dpkg(1) to leave it alone!
105+
diversion = run(["dpkg-divert", "--add", "--no-rename", "/etc/grub.d/10_linux"])
106+
if diversion.returncode != 0:
107+
print("diversion failed")
108+
exit(1)
109+
110+
# Check if we've already patched /etc/grub.d/10_linux by checking if
111+
# unapplying it would succeed
112+
already_applied = run(
113+
[
114+
"patch",
115+
"--dry-run",
116+
"--reverse",
117+
"--silent",
118+
"--force",
119+
"/etc/grub.d/10_linux",
120+
],
121+
input=diff,
122+
stdout=DEVNULL,
123+
stderr=DEVNULL,
124+
universal_newlines=True,
125+
)
126+
if already_applied.returncode != 0:
127+
# If we haven't, then patch it now
128+
print("patching /etc/grub.d/10_linux")
129+
application = run(
130+
["patch", "--silent", "--force", "/etc/grub.d/10_linux"],
131+
input=diff,
132+
universal_newlines=True,
133+
)
134+
if application.returncode != 0:
135+
print("patch failed")
136+
exit(1)
137+
else:
138+
print("/etc/grub.d/10_linux is already patched")
139+
140+
# For safety's sake, patch(1) sometimes leaves a copy of the original file
141+
# behind (for example, if the patch didn't *precisely* match). If that file
142+
# exists, then we should make sure it's not executable so
143+
# that update-grub(1) won't try to run it
144+
try:
145+
chmod("/etc/grub.d/10_linux.orig", 0o600)
146+
except FileNotFoundError:
147+
pass
148+
149+
# Now update /etc/grub.d/40_custom with the appropriately-hashed form of
150+
# the password. We do this in a slightly careful way: we populate a
151+
# temporary file with all of the lines from that file that *don't* have a
152+
# special tag comment in them (to make sure we don't leave old settings
153+
# lying around), after which we write two new lines with that tag comment.
154+
# Then we change the permissions on the temporary file to make it
155+
# executable and move it into place over the old one
156+
encoded = grub2_mkpasswd_pbkdf2(argv[1], debug=True)
157+
with open("/etc/grub.d/40_custom.tmp", "wt") as new:
158+
with open("/etc/grub.d/40_custom", "r+t") as old:
159+
for line in old:
160+
if "# OS2borgerPC lockdown" not in line:
161+
new.write(line)
162+
new.write('set superusers="superuser" # OS2borgerPC lockdown\n')
163+
new.write(
164+
"password_pbkdf2 superuser" " {0} # OS2borgerPC lockdown\n".format(encoded)
165+
)
166+
chmod("/etc/grub.d/40_custom.tmp", 0o700)
167+
rename("/etc/grub.d/40_custom.tmp", "/etc/grub.d/40_custom")
168+
169+
# Finally, having done all of that, run update-grub(1) to generate a new
170+
# grub.cfg
171+
result = run(["update-grub"])
172+
if result.returncode != 0:
173+
print("update-grub failed")
174+
exit(1)
175+
176+
177+
if __name__ == "__main__":
178+
main()

0 commit comments

Comments
 (0)