-
Notifications
You must be signed in to change notification settings - Fork 1
/
ai-conf
executable file
·2667 lines (2291 loc) · 111 KB
/
ai-conf
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
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env bash
source "${0%/*}/ai-funcs"
################################################################################
# Here are more global variables to share amongst functions
################################################################################
declare -r TITLEBAR="AI CONFIGURATION"
declare -ra PORTLIST=(
21_ftp
22_ssh
23_telnet
25_smtp
53_dns
69_tftp
70_gopher
80_http
88_kerberos5
110_pop3
123_ntp
137:139_netbios
143_imap
161:162_snmp
194_irc
389_ldap
443_https
445_smb
465_smtps
587_starttls
636_ldaps
749_kerberos-adm
750_kerberos4
873_rsync
992_telnets
993_imaps
994_ircs
995_pop3s
1900_upnp
2049_nfsd
3478_stun
8200_dlna-webgui
8384_syncthing-webgui
20048_nfs-acl
21027_syncthing-discovery
22000_syncthing-listen
64738_murmur
)
################################################################################
# Overly-cautious verification of required binaries
################################################################################
for CMD in arch-chroot cp curl date env genfstab head ip ln localedef pacman-key \
passwd paste readlink rename stat systemctl tail tar useradd usermod; do
BIN["${CMD}"]="$(GET_COMMAND "${CMD}")" || ERR_LIST+="CRIT: Couldn't find ${CMD}\n"
done
CHECK_FOR_FAILURE_POINTS
function CONVERT_NETMASK {
case "${1}" in
0) echo '0.0.0.0';;
1) echo '128.0.0.0';;
2) echo '192.0.0.0';;
3) echo '244.0.0.0';;
4) echo '240.0.0.0';;
5) echo '248.0.0.0';;
6) echo '252.0.0.0';;
7) echo '254.0.0.0';;
8) echo '255.0.0.0';;
9) echo '255.128.0.0';;
10) echo '255.192.0.0';;
11) echo '255.244.0.0';;
12) echo '255.240.0.0';;
13) echo '255.248.0.0';;
14) echo '255.252.0.0';;
15) echo '255.254.0.0';;
16) echo '255.255.0.0';;
17) echo '255.255.128.0';;
18) echo '255.255.192.0';;
19) echo '255.255.244.0';;
20) echo '255.255.240.0';;
21) echo '255.255.248.0';;
22) echo '255.255.252.0';;
23) echo '255.255.254.0';;
24) echo '255.255.255.0';;
25) echo '255.255.255.128';;
26) echo '255.255.255.192';;
27) echo '255.255.255.244';;
28) echo '255.255.255.240';;
29) echo '255.255.255.248';;
30) echo '255.255.255.252';;
31) echo '255.255.255.254';;
32) echo '255.255.255.255';;
'0.0.0.0') echo '0';;
'128.0.0.0') echo '1';;
'192.0.0.0') echo '2';;
'244.0.0.0') echo '3';;
'240.0.0.0') echo '4';;
'248.0.0.0') echo '5';;
'252.0.0.0') echo '6';;
'254.0.0.0') echo '7';;
'255.0.0.0') echo '8';;
'255.128.0.0') echo '9';;
'255.192.0.0') echo '10';;
'255.244.0.0') echo '11';;
'255.240.0.0') echo '12';;
'255.248.0.0') echo '13';;
'255.252.0.0') echo '14';;
'255.254.0.0') echo '15';;
'255.255.0.0') echo '16';;
'255.255.128.0') echo '17';;
'255.255.192.0') echo '18';;
'255.255.244.0') echo '19';;
'255.255.240.0') echo '20';;
'255.255.248.0') echo '21';;
'255.255.252.0') echo '22';;
'255.255.254.0') echo '23';;
'255.255.255.0') echo '24';;
'255.255.255.128') echo '25';;
'255.255.255.192') echo '26';;
'255.255.255.244') echo '27';;
'255.255.255.240') echo '28';;
'255.255.255.248') echo '29';;
'255.255.255.252') echo '30';;
'255.255.255.254') echo '31';;
'255.255.255.255') echo '32';;
esac
}
function USE_PRIVILEGE {
# This is just a wrapper so you don't have to type "${BIN[sudo]}" all the time
GET_PRIVILEGE && "${BIN[sudo]}" "${@}" || return 1
}
function FIND_EDITOR {
# Respect the user's preference, but if not specicified,
# try to find one in order from 'easiest' to 'hardest'.
if [[ -n ${EDITOR} ]]; then command -v "${EDITOR}"
elif [[ -e /bin/nano ]]; then echo '/bin/nano'
elif [[ -e /usr/bin/mcedit ]]; then echo '/usr/bin/mcedit'
elif [[ -e /usr/bin/dte ]]; then echo '/usr/bin/dte'
elif [[ -e /usr/bin/kak ]]; then echo '/usr/bin/kak'
elif [[ -e /usr/bin/helix ]]; then echo '/usr/bin/helix'
elif [[ -e /usr/bin/nvim ]]; then echo '/usr/bin/nvim'
elif [[ -e /usr/bin/vis ]]; then echo '/usr/bin/vis'
elif [[ -e /usr/bin/vim ]]; then echo '/usr/bin/vim'
elif [[ -e /usr/bin/vi ]]; then echo '/usr/bin/vi'
elif [[ -e /usr/bin/e3 ]]; then echo '/usr/bin/e3'
fi
}
################################################################################
# Function that retrieve configuration settings
################################################################################
function GET_DEFAULT_EDITOR {
# NOTE: This concerns the EDITOR environment variable in the chroot.
RETVALUE="$("${BIN[grep]}" -hRs 'export\s*EDITOR=' "${OSCHROOT}/etc/profile.d" | \
"${BIN[cut]}" -d= -f2)"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[not set]'
}
function GET_FAIL2BAN_SSHD {
local CFG_FILE="${OSCHROOT}/etc/fail2ban/jail.d/sshd.local"
if [[ -e "${CFG_FILE}" ]]; then
local MAXRETRY="$("${BIN[grep]}" 'maxretry' "${CFG_FILE}" | "${BIN[cut]}" -d= -f2 | "${BIN[tr]}" -d ' ')"
local FINDTIME="$("${BIN[grep]}" 'findtime' "${CFG_FILE}" | "${BIN[cut]}" -d= -f2 | "${BIN[tr]}" -d ' ')"
local BAN_TIME="$("${BIN[grep]}" 'bantime' "${CFG_FILE}" | "${BIN[cut]}" -d= -f2 | "${BIN[tr]}" -d ' ')"
local IGNOREIP="$("${BIN[grep]}" 'ignoreip' "${CFG_FILE}" | "${BIN[cut]}" -d= -f2 | "${BIN[sed]}" 's/^\s\+//g')"
printf 'Ban for %s after %s failures within %s, ignoring %s' "${BAN_TIME}" "${MAXRETRY}" "${FINDTIME}" "${IGNOREIP}"
else
echo '[no config]'
fi
}
function GET_RESOLV_LINK {
"${BIN[readlink]}" "${OSCHROOT}/etc/resolv.conf"
}
function GET_HOSTS {
local RETVALUE
RETVALUE="$("${BIN[grep]}" -v '^\s*#\|^\s*$' "${OSCHROOT}/etc/hosts" | \
"${BIN[sed]}" 's/\s\+[0-9a-z-]*\.[0-9a-z-]*\.[0-9a-z-]*/ /g;s/\s\+$//g;s/\s\+/ = /g' | \
"${BIN[tr]}" '\n' ',' | "${BIN[sed]}" 's/,$//g;s/,/, /g')"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[not set]'
}
function GET_IPTABLES_PORTS_CLOSED_GLOBALLY {
"${BIN[grep]}" 'OUTPUT.*DROP' "${OSCHROOT}/etc/iptables/iptables.rules" | \
"${BIN[sed]}" 's/.*--dport \([0-9]\+\) .*/\1/g' | \
"${BIN[sort]}" -un | "${BIN[paste]}" -d\ -s
}
function GET_IPTABLES_PORTS_OPEN_GLOBALLY {
"${BIN[grep]}" -- '--dport\s\+[0-9]\+.*ACCEPT' "${OSCHROOT}/etc/iptables/iptables.rules" | \
"${BIN[grep]}" -v -- '-s [a-z.]\+\|-d [0-9./]\{9,18\}' | \
"${BIN[sed]}" 's/.*--dport \([0-9]\+\) .*/\1/g' | \
"${BIN[sort]}" -un | "${BIN[paste]}" -d\ -s
}
function GET_LANGUAGES {
"${BIN[grep]}" -v '^\s*#' "${OSCHROOT}/etc/locale.gen" | \
"${BIN[sed]}" 's/^\s*\([a-z]\{2,3\}\)_.*\.UTF-8 UTF-8.*/\1/g;' | \
"${BIN[sort]}" -u | "${BIN[paste]}" -d\ -s
}
function GET_LOCAL_DOMAIN {
"${BIN[grep]}" 'Domains=' "${OSCHROOT}/etc/systemd/resolved.conf" | "${BIN[cut]}" -d= -f2
}
function GET_LOCALES {
[[ -n ${1} ]] && LOCALES="$("${BIN[grep]}" -s "^\#*\(${1// /\\|}\).*\.UTF-8 UTF-8" "${OSCHROOT}/etc/locale.gen")"
[[ -z ${1} ]] && LOCALES="$("${BIN[grep]}" -s "^[a-z].*\.UTF-8 UTF-8" "${OSCHROOT}/etc/locale.gen")"
if [[ -z ${1} ]] && [[ -z ${LOCALES} ]]; then
echo '[none selected]'
else
"${BIN[sed]}" 's/\.UTF-8 UTF-8.*//g;' <<< "${LOCALES}" | "${BIN[paste]}" -d\ -s
fi
}
function GET_LOCALE_COLLATION {
if [[ -e "${OSCHROOT}/etc/locale.conf" ]]; then
"${BIN[grep]}" -s LC_COLLATE "${OSCHROOT}/etc/locale.conf" | "${BIN[cut]}" -d= -f2
else
echo '[no config]'
fi
}
function GET_LOCALE_MESSAGES {
if [[ -e "${OSCHROOT}/etc/locale.conf" ]]; then
"${BIN[grep]}" -s LC_MESSAGES "${OSCHROOT}/etc/locale.conf" | "${BIN[cut]}" -d= -f2
else
echo '[no config]'
fi
}
function GET_MKINITCPIO_COMPRESSION {
local COMPTYPE
COMPTYPE=$("${BIN[grep]}" '^\s*COMPRESSION=' "${OSCHROOT}/etc/mkinitcpio.conf" | "${BIN[cut]}" -d\" -f2)
echo "${COMPTYPE:-zstd}"
}
function GET_MKINITCPIO_HOOKS {
"${BIN[grep]}" '^\s*HOOKS=' "${OSCHROOT}/etc/mkinitcpio.conf" | "${BIN[sed]}" 's/.*(\(.*\)).*/\1/g'
}
function GET_MKINITCPIO_MODULES {
local RETVALUE
RETVALUE="$("${BIN[grep]}" '^\s*MODULES=' "${OSCHROOT}/etc/mkinitcpio.conf" | \
"${BIN[sed]}" 's/.*(\(.*\)).*/\1/g')"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[none]'
}
function GET_NANORC_COLORS {
local WHOHASIT
"${BIN[grep]}" -q '^\s*set [a-z]\+color [a-z,]\+' "${OSCHROOT}/etc/nanorc" && WHOHASIT+='Set globally '
USE_PRIVILEGE "${BIN[grep]}" -qsR '^\s*set [a-z]\+color [a-z,]\+' "${OSCHROOT}/root/.nanorc" && WHOHASIT+='and by root '
USE_PRIVILEGE "${BIN[grep]}" -qsR '^\s*set [a-z]\+color [a-z,]\+' "${OSCHROOT}/root/.config/nano/nanorc" && WHOHASIT+='and by root '
for USERHOME in "${OSCHROOT}"/home/*; do
USE_PRIVILEGE "${BIN[grep]}" -qsR '^\s*set [a-z]\+color [a-z,]\+' "${USERHOME}/.nanorc" && WHOHASIT+="and by ${USERHOME##*\/} "
USE_PRIVILEGE "${BIN[grep]}" -qsR '^\s*set [a-z]\+color [a-z,]\+' "${USERHOME}/.config/nano/nanorc" && WHOHASIT+="and by ${USERHOME##*\/} "
done
[[ -n ${WHOHASIT} ]] && echo "${WHOHASIT% }" || echo '[not set]'
}
function GET_NANORC_INCLUDES {
local RETVALUE="$("${BIN[grep]}" '^\s*include' "${OSCHROOT}/etc/nanorc" | \
"${BIN[cut]}" -d\ -f2 | "${BIN[tr]}" -d '"' | "${BIN[paste]}" -d, -s | \
"${BIN[sed]}" 's/,/, /g')"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[none]'
}
function GET_NANORC_OPTIONS {
local NANOOPTS CFG_FILE="${OSCHROOT}/etc/nanorc"
if [[ -e ${CFG_FILE} ]]; then
NANOOPTS="$("${BIN[grep]}" 'set ' "${OSCHROOT}/etc/nanorc" | "${BIN[grep]}" -v '[.,:;\"0-9]\|color')"
case "${1}" in
all)
NANOOPTS=$("${BIN[sed]}" 's/^\s*\#*\s*set //g' <<< "${NANOOPTS}");;
enabled)
NANOOPTS=$("${BIN[grep]}" -v '^\s*#' <<< "${NANOOPTS}" | "${BIN[sed]}" 's/^\s*set\s*//g');;
esac
NANOOPTS="$("${BIN[sort]}" -u <<< "${NANOOPTS}" | ${BIN[paste]} -d\ -s)"
[[ -n ${NANOOPTS} ]] && echo "${NANOOPTS}" || { [[ ${1} == enabled ]] && echo '[none set]'; }
else
[[ ${1} == enabled ]] && echo '[no config]'
fi
}
function GET_NTP {
local CFG_FILE="${OSCHROOT}/etc/ntp.conf"
local UPSTREAM UNBLOCKD BLOCKED SERVEDTO
UPSTREAM="$("${BIN[grep]}" '^\s*server' "${CFG_FILE}" | "${BIN[wc]}" -l)"
if "${BIN[grep]}" '^\s*restrict\s*default.*noserve' "${CFG_FILE}"; then
UNBLOCKD="$("${BIN[grep]}" '^\s*restrict' "${CFG_FILE}" | \
"${BIN[grep]}" -v 'default\|noserve' | "${BIN[cut]}" -d\ -f2 | paste -d\ -s)"
[[ -z ${UNBLOCKD} ]] && unset UNBLOCKD
SERVEDTO="everyone blocked${UNBLOCKD+ except }${UNBLOCKD}"
else
BLOCKED="$("${BIN[grep]}" '^\s*restrict.*noserve' "${CFG_FILE}" | \
"${BIN[grep]}" -v 'default' | "${BIN[cut]}" -d\ -f2 | paste -d\ -s)"
[[ -z ${BLOCKED} ]] && unset BLOCKED
SERVEDTO="serve everyone${BLOCKED+ except }${BLOCKED}"
fi
echo "${UPSTREAM} upstream server(s), ${SERVEDTO}"
}
function GET_NSSWITCH_HOSTS {
"${BIN[grep]}" '^\s*hosts' "${OSCHROOT}/etc/nsswitch.conf" | "${BIN[sed]}" 's/\s*hosts:\s*//g'
}
function GET_PACMAN_REPOS {
"${BIN[grep]}" '^\[' "${OSCHROOT}/etc/pacman.conf" | \
${BIN[grep]} -v options | "${BIN[tr]}" -d '[]' | "${BIN[paste]}" -d\ -s
}
function GET_PACMAN_OPTIONS {
"${BIN[grep]}" '^[A-Z]' "${OSCHROOT}/etc/pacman.conf" | \
"${BIN[grep]}" -v 'Architecture\|Dir\|Hold\|Ignore\|Server\|Include\|SigLevel' | \
"${BIN[tr]}" -d ' ' | "${BIN[paste]}" -d\ -s
}
function GET_PRIMARY_LANGUAGE {
local RETVALUE CFG_FILE="${OSCHROOT}/etc/locale.conf"
if [[ -e ${CFG_FILE} ]]; then
RETVALUE="$("${BIN[grep]}" -s LANGUAGE "${CFG_FILE}" | "${BIN[cut]}" -d= -f2)"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[not selected]'
else
echo '[no config]'
fi
}
function GET_PLYMOUTH_THEME {
"${BIN[grep]}" Theme "${OSCHROOT}/etc/plymouth/plymouthd.conf" | "${BIN[tr]}" 'T' 't'
}
function GET_SMARTD_DEVICESCAN {
"${BIN[grep]}" '^\s*DEVICESCAN' "${OSCHROOT}/etc/smartd.conf" | "${BIN[sed]}" 's/^\s*DEVICESCAN\s*//g'
}
function GET_SSHD_LISTEN_INFO {
local CFG_FILE="${OSCHROOT}/etc/ssh/sshd_config"
local SVCSTATE OPENPRTS LSTNADRS
IS_SSHD_ENABLED && SVCSTATE+="enabled" || SVCSTATE+="disabled"
OPENPRTS="$("${BIN[grep]}" -s '^\s*Port' "${CFG_FILE}" | "${BIN[sed]}" 's/.*[ \t]//g' | "${BIN[sort]}" -n | "${BIN[paste]}" -d, -s)"
LSTNADRS="$("${BIN[grep]}" -s '^\s*ListenAddress' "${CFG_FILE}" | "${BIN[sed]}" 's/.*[ \t]//g' | "${BIN[sort]}" -n | "${BIN[paste]}" -d, -s)"
[[ -z ${OPENPRTS} ]] && OPENPRTS='22'
for ADDRESS in ${LSTNADRS}; do
if [[ ${ADDRESS} =~ [0-9af]:[0-9]{2,5}$ ]]; then
LISTENS+="${ADDRESS} "
else
LISTENS+="${ADDRESS}:${OPENPRTS} "
fi
done
if [[ -z ${LISTENS} ]] && [[ -s ${OSCHROOT}/etc/hosts ]]; then
LISTENS="$("${BIN[grep]}" -s "\s$(<"${OSCHROOT}/etc/hostname")\." "${OSCHROOT}/etc/hosts" | "${BIN[sed]}" 's/\s.*//g'):${OPENPRTS}"
fi
[[ -z ${LISTENS} ]] && LISTENS="0.0.0.0:${OPENPRTS}"
echo "Service ${SVCSTATE}, listening on ${LISTENS% }"
}
function GET_SYSTEMD_JOURNAL_SIZE {
{ "${BIN[grep]}" '^\s*SystemMaxUse' "${OSCHROOT}/etc/systemd/journald.conf" || echo default; } | "${BIN[cut]}" -d= -f2
}
function GET_SYSTEMD_RESOLVED {
"${BIN[grep]}" '^\s*[A-Z]' "${OSCHROOT}/etc/systemd/resolved.conf" | "${BIN[paste]}" -d\ -s
}
function GET_SYSTEMD_LOGIND_HANDLELIDSWITCH {
{ "${BIN[grep]}" -s '^\s*HandleLidSwitch=' "${OSCHROOT}/etc/systemd/logind.conf" || echo '=default (suspend)'; } | "${BIN[cut]}" -d= -f2
}
function GET_SYSTEMD_SERVICE_START_TIMEOUT {
{ "${BIN[grep]}" '^\s*DefaultTimeoutStartSec' "${OSCHROOT}/etc/systemd/system.conf" || echo default; } | "${BIN[cut]}" -d= -f2
}
function GET_SYSTEMD_SERVICE_STOP_TIMEOUT {
{ "${BIN[grep]}" '^\s*DefaultTimeoutStopSec' "${OSCHROOT}/etc/systemd/system.conf" || echo default; } | "${BIN[cut]}" -d= -f2
}
function GET_SYSTEMD_TIMESYNCD_SERVERS {
"${BIN[grep]}" -v '^\s*[#\[]\|^\s*$' "${OSCHROOT}/etc/systemd/timesyncd.conf" | \
"${BIN[cut]}" -d= -f2 | "${BIN[paste]}" -d\ -s
}
function GET_SUDO_CONFIG {
# This function gathers up all the uncommented options present between
# /etc/sudoers and its @includedir directive
local SUDO_CFG INCL_DIR
# Parse the config file into a variable (ignore commented-out and blank lines)
SUDO_CFG="$("${BIN[sudo]}" "${BIN[grep]}" -sv '^\s*#\|^$' "${OSCHROOT}/etc/sudoers")"
if [[ ${SUDO_CFG} =~ @includedir ]]; then
# If the config file specified an @includedir, get configs from those files as well
INCL_DIR="$("${BIN[grep]}" 'includedir' <<< "${SUDO_CFG}" | "${BIN[cut]}" -d\ -f2)"
SUDO_CFG+=$'\n' # The trailing newline got stripped out, so add it back in
SUDO_CFG+="$("${BIN[sudo]}" sh -c "'${BIN[grep]}' -hsv '^\s*#' ${OSCHROOT}${INCL_DIR}/*" | "${BIN[grep]}" -v "^\s*$")"
fi
echo "${SUDO_CFG}"
}
function INTERPRET_SUDO_CONFIG {
# This function differs from GET_SUDO_CONFIG in that it tries to present the
# configuration in natural language rather than straight-up config file format
local MEANING SUDO_CFG="$(GET_SUDO_CONFIG)"
[[ ${SUDO_CFG} =~ %wheel ]] && MEANING+='wheel can use, '
[[ ${SUDO_CFG} =~ rootpw ]] && MEANING+='require root password, '
[[ ${SUDO_CFG} =~ passprompt ]] && MEANING+='custom prompt set, '
if [[ ${SUDO_CFG} =~ passwd_timeout ]]; then
TIMEOUT="$("${BIN[grep]}" passwd_timeout <<< "${SUDO_CFG}" | ${BIN[tail]} -1 | "${BIN[cut]}" -d= -f2)"
if [[ ${TIMEOUT} == 0 ]]; then
MEANING+='no password timeout, '
else
MEANING+="password timeout in ${TIMEOUT} minutes"
fi
fi
[[ ${SUDO_CFG} =~ 'timestamp_type global' ]] && MEANING+='global authentication, '
if [[ ${SUDO_CFG} =~ timestamp_timeout ]]; then
TIMEOUT="$("${BIN[grep]}" timestamp_timeout <<< "${SUDO_CFG}" | "${BIN[cut]}" -d= -f2)"
if [[ ${TIMEOUT} == 0 ]]; then
MEANING+='always prompt for password, '
elif [[ ${TIMEOUT} -lt 0 ]]; then
MEANING+="credentials cached forever, "
else
MEANING+="credential timeout in ${TIMEOUT} minutes"
fi
fi
[[ -n ${MEANING} ]] && "${BIN[sed]}" 's/, $//g' <<< "${MEANING}" || echo '[nothing set]'
}
function GET_TIMEZONE {
local TIMEZONE
if [[ -L "${OSCHROOT}/etc/localtime" ]]; then
TIMEZONE="$("${BIN[readlink]}" "${OSCHROOT}/etc/localtime")"
case "${1}" in
short) "${BIN[sed]}" 's|.*zoneinfo/||g' <<< "${TIMEZONE}";;
full) echo "${TIMEZONE}";;
esac
else
[[ ${1} == short ]] && echo "[not set]"
fi
}
function GET_USERNAMES {
local USRWPGID THISUSER PGRPNAME RETVALUE
USRWPGID=$("${BIN[grep]}" ':x:0:\|:x:[0-9]\{4\}:' "${OSCHROOT}/etc/passwd" | "${BIN[cut]}" -d: -f1,4 | "${BIN[tr]}" '\n' ' ')
for THISUSER in ${USRWPGID}; do
PGRPNAME=$("${BIN[grep]}" ":${THISUSER#*:}:" "${OSCHROOT}/etc/group" | "${BIN[cut]}" -d: -f1)
RETVALUE+="${THISUSER%:*}:${PGRPNAME} "
done
"${BIN[paste]}" -d\ -s <<< "${RETVALUE}"
}
function GET_USERNAME_GROUP_MEMBERSHIP_COUNT {
local LOGINAME GRPCOUNT RETVALUE
for LOGINAME in $(GET_USERNAMES | "${BIN[sed]}" 's/:[a-z]\+ / /g'); do
GRPCOUNT=$("${BIN[grep]}" "${LOGINAME}" "${OSCHROOT}/etc/group" | "${BIN[wc]}" -l)
RETVALUE+="${LOGINAME} in ${GRPCOUNT}, "
done
"${BIN[sed]}" 's/, $//g' <<< "${RETVALUE}"
}
function GET_USERNAME_PASSWORD {
local USERLIST LOGINAME PSWRDSTR SHRT_OUT LONG_OUT
[[ -n "${1}" ]] && USERLIST="${1}" || USERLIST="$(GET_USERNAMES | "${BIN[sed]}" 's/:[a-z]\+ / /g')"
for LOGINAME in ${USERLIST}; do
PSWRDSTR="$("${BIN[sudo]}" "${BIN[grep]}" "${LOGINAME%:*}" "${OSCHROOT}/etc/shadow" | "${BIN[cut]}" -d: -f2)"
case "${PSWRDSTR}" in
*'!'*) SHRT_OUT+="${LOGINAME}:locked "; LONG_OUT='locked out';;
'$1$'*) SHRT_OUT+="${LOGINAME}:MD5 "; LONG_OUT='password-protected (MD5)';;
'$2'[abxy]'$'*) SHRT_OUT+="${LOGINAME}:Blowfish "; LONG_OUT='password-protected (Blowfish)';;
'$5$'*) SHRT_OUT+="${LOGINAME}:SHA256 "; LONG_OUT='password-protected (SHA256)';;
'$6$'*) SHRT_OUT+="${LOGINAME}:SHA512 "; LONG_OUT='password-protected (SHA512)';;
*) SHRT_OUT+="${LOGINAME}:open "; LONG_OUT='unprotected'
esac
done
[[ -n "${1}" ]] && echo "${LONG_OUT}" || echo "${SHRT_OUT}" | "${BIN[paste]}" -d\ -s
}
function GET_USERNAME_SHELL {
"${BIN[grep]}" ':x:0:\|:x:[0-9]\{4\}:' "${OSCHROOT}/etc/passwd" | "${BIN[cut]}" -d: -f1,7 | "${BIN[sed]}" 's|/.*/||g' | "${BIN[paste]}" -d\ -s
}
function GET_VCONSOLE_FONT {
local RETVALUE CFG_FILE="${OSCHROOT}/etc/vconsole.conf"
if [[ -e ${CFG_FILE} ]]; then
RETVALUE="$("${BIN[grep]}" -s FONT "${OSCHROOT}/etc/vconsole.conf" | \
"${BIN[cut]}" -d= -f2)"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[not selected]'
else
echo '[no config]'
fi
}
function GET_VCONSOLE_KEYMAP {
local RETVALUE CFG_FILE="${OSCHROOT}/etc/vconsole.conf"
if [[ -e ${CFG_FILE} ]]; then
RETVALUE="$("${BIN[grep]}" -s KEYMAP "${OSCHROOT}/etc/vconsole.conf" | \
"${BIN[cut]}" -d= -f2)"
[[ -n ${RETVALUE} ]] && echo "${RETVALUE}" || echo '[not selected]'
else
echo '[no config]'
fi
}
function GET_VIDEO_ACCELERATION_SCRIPT_RESULTS {
local CFG_FILE="${OSCHROOT}/etc/profile.d/video-accel.sh"
[[ -e "${CFG_FILE}" ]] && \
"${BIN[env]}" -i sh -c "source ${CFG_FILE}; set" | \
"${BIN[grep]}" DRIVER | "${BIN[paste]}" -d\ -s
}
function IS_FSTAB_SET {
"${BIN[grep]}" -qv '^\s*#\|^\s*$' "${OSCHROOT}/etc/fstab"
}
function IS_PLYMOUTH_HOOK_PRESENT {
"${BIN[grep]}" -q '^\s*HOOKS\s*=\s*(.*plymouth.*)\s*' "${OSCHROOT}/etc/mkinitcpio.conf"
}
function IS_POLICYKIT_ROOTPW_SET {
USE_PRIVILEGE "${BIN[grep]}" -qsR 'return\s*\[\s*.\s*unix-user\s*:\s*root\s*.\s*\]\s*;' "${OSCHROOT}/etc/polkit-1/rules.d"
}
function IS_SSHD_ENABLED {
set -- "${OSCHROOT}"/etc/systemd/system/*/sshd.service; test -f "${1}"
}
function IS_STICKYDIRS_FIXED {
"${BIN[grep]}" -qsR '\s*fs\.protected_regular\s*=\s*0' "${OSCHROOT}/etc/sysctl.d"
}
function IS_SYSTEMD_RESOLVED_ENABLED {
set -- "${OSCHROOT}"/etc/systemd/system/*/systemd-resolved.service; test -f "${1}"
}
function CONFIGURE_DEFAULT_EDITOR {
local -r CFG_FILE="${OSCHROOT}/etc/profile.d/editor.sh"
local -r CFG_ITEM="export EDITOR"
##############################################################################
local -r BAKTITLE="Default Console Text Editor"
local -r HELP_MSG="Select your default console text editor:"
##############################################################################
local -a SUGGESTS DESCRIPS
local SELECTED KNOWN KNOWNS PREV_CFG="$(GET_DEFAULT_EDITOR)"
KNOWNS=(dte:/usr/bin/dte e3:/usr/bin/e3 helix:/usr/bin/helix)
KNOWNS+=(helix:/usr/bin/hx kakoune:/usr/bin/kak mcedit:/usr/bin/mcedit)
KNOWNS+=(nano:/usr/bin/nano neovim:/usr/bin/nvim vi:/usr/bin/vi)
KNOWNS+=(vim:/usr/bin/vim vis:/usr/bin/vis)
for KNOWN in "${KNOWNS[@]}"; do
if [[ -e "${OSCHROOT}${KNOWN#*:}" ]]; then
SUGGESTS+=("${KNOWN%:*}"); DESCRIPS+=("${KNOWN#*:}")
fi
done
DIALOG_SINGLE_SELECT "${TITLEBAR}" "${BAKTITLE}" 'hidetags' "${PREV_CFG}" \
"${HELP_MSG}" 'SUGGESTS' 'SUGGESTS' || return 1
SELECTED="$(</tmp/selection)"
USE_PRIVILEGE sh -c "echo '${CFG_ITEM}=${SELECTED}' > '${CFG_FILE}'"
}
function CONFIGURE_FAIL2BAN_SSHD {
local -r CFG_FILE="${OSCHROOT}/etc/fail2ban/jail.d/sshd.local"
[[ -d ${CFG_FILE%/*} ]] || return 0
##############################################################################
local -r BAKTITLE="Fail2Ban SSHD"
local -r HELP_MSG="Copy ${HOME}/fstab to ${CFG_FILE}?"
##############################################################################
local LOCAL_HN IPFROMHF LOCAL_SN
if [[ -e ${CFG_FILE} ]]; then
DIALOG_YESNO "${TITLEBAR}" "Configuration Found" "Replace existing configuration?" || return 0
USE_PRIVILEGE "${BIN[mv]}" "${CFG_FILE}" "${CFG_FILE}.$("${BIN[date]}" +%Y-%m-%d_%H:%M:%S)"
fi
LOCAL_HN="$(<"${OSCHROOT}/etc/hostname")"
IPFROMHF="$("${BIN[grep]}" "[0-9.]\{7,15\}.*${LOCAL_HN}" "${OSCHROOT}" | "${BIN[sed]}" 's/\s.*//g')"
if ! [[ ${IPFROMHF} =~ ^127 ]]; then
case "${IPFROMHF}" in
10.*) SNSUFFIX='/8';;
169.254.*) SNSUFFIX='/16';;
192.168.*) SNSUFFIX='/24';;
esac
LOCAL_SN="${IPFROMHF}${SNSUFFIX}"
fi
USE_PRIVILEGE sh -c "cat <<- ENDOFSCRIPT > '${CFG_FILE}'
[sshd]
enabled = true
filter = sshd
banaction = iptables
backend = systemd
maxretry = 5
findtime = 24h
bantime = 2w
ignoreip = 127.0.0.1/8${LOCAL_SN+ }${LOCAL_SN}
ENDOFSCRIPT"
}
function CONFIGURE_FSTAB {
local -r CFG_FILE="${OSCHROOT}/etc/fstab"
##############################################################################
local -r BAKTITLE="fstab"
local -r HELP_MSG="Copy ${HOME}/fstab to ${CFG_FILE}?"
##############################################################################
local USRFSTAB=false FSTABSET=false
IS_FSTAB_SET && FSTABSET=true || FSTABSET=false
[[ -e ${HOME}/fstab ]] && USRFSTAB=true || USRFSTAB=false
if ${FSTABSET}; then
if ${USRFSTAB}; then
WARNING="Found ${HOME}/fstab but ${CFG_FILE} has already been written to.\n"
WARNING+="Reset ${CFG_FILE} with ${HOME}/fstab?"
if DIALOG_YESNO "${TITLEBAR}" "${BAKTITLE}" "${WARNING}"; then
USE_PRIVILEGE sh -c "'${BIN[grep]}' '^\s*#' '${CFG_FILE}' > '${CFG_FILE}.tmp'"
USE_PRIVILEGE sh -c "'${BIN[grep]}' 'file *systems*\|details' '${CFG_FILE}.tmp' > '${CFG_FILE}'"
USE_PRIVILEGE "${BIN[rm]}" "${CFG_FILE}.tmp"
USE_PRIVILEGE sh -c "'${BIN[cat]}' '${HOME}/fstab' >> '${CFG_FILE}'"
else
USE_PRIVILEGE "$(FIND_EDITOR)" "${CFG_FILE}"
fi
else
USE_PRIVILEGE "$(FIND_EDITOR)" "${CFG_FILE}"
fi
elif ${USRFSTAB}; then
if DIALOG_YESNO "${TITLEBAR}" "${BAKTITLE}" "${HELP_MSG}"; then
USE_PRIVILEGE sh -c "'${BIN[cat]}' '${HOME}/fstab' >> '${CFG_FILE}'"
elif DIALOG_YESNO "${TITLEBAR}" "${BAKTITLE}" "Use genfstab?"; then
USE_PRIVILEGE sh -c "'${BIN[genfstab]}' -L '${OSCHROOT}' | \
'${BIN[sed]}' 's/^#.*//g;s/\s\+/\t/g;s/\([0-9]\)\t\([0-9]\)$/\1 \2/g' | \
'${BIN[sed]}' '/^$/d' >> '${OSCHROOT}/etc/fstab'"
else
USE_PRIVILEGE "$(FIND_EDITOR)" "${CFG_FILE}"
fi
fi
return 0
}
function CONFIGURE_HOSTNAME {
local -r CFG_FILE="${OSCHROOT}/etc/hostname"
##############################################################################
local -r BAKTITLE="Hostname"
local -r HELP_MSG="Set your hostname"
##############################################################################
DIALOG_INPUT "${TITLEBAR}" "${BAKTITLE}" "${HELP_MSG}" "$(<"${CFG_FILE}")" || return 1
SELECTED=$(</tmp/selection)
USE_PRIVILEGE sh -c "echo '${SELECTED}' > '${CFG_FILE}'"
}
function CONFIGURE_HOSTS {
local -r CFG_FILE="${OSCHROOT}/etc/hosts"
local -r CFG_ITEM="$(<"${CFG_FILE/hosts/hostname}")"
##############################################################################
local -r BAKTITLE="Hostname"
local -r HELP_MSG="Set your hostname"
##############################################################################
local -a SUGGESTS DESCRIPS
local LOCAL_IP="$("${BIN[ip]}" route get 1 | "${BIN[head]}" -1 | "${BIN[sed]}" 's/.*src \([0-9.]\+\).*/\1/g')"
local LOCAL_DN="$("${BIN[grep]}" 'Domains=' "${OSCHROOT}/etc/systemd/resolved.conf" | "${BIN[cut]}" -d= -f2)"
local LOCAL_HN="${CFG_ITEM}" SELECTED
SUGGESTS=('127.0.1.1' "${LOCAL_IP}")
DESCRIPS=('This computer uses a dynamic IP address' 'This computer uses a static IP address')
DIALOG_SINGLE_SELECT "${TITLEBAR}" "${BAKTITLE}" 'showtags' '127.0.0.1' \
"${HELP_MSG}" 'SUGGESTS' 'DESCRIPS' || return 1
SELECTED="$(</tmp/selection)"
USE_PRIVILEGE "${BIN[touch]}" "${CFG_FILE}"
if ${BIN[grep]} -q '127.0.0.1\s\+localhost' "${CFG_FILE}"; then
USE_PRIVILEGE "${BIN[sed]}" "s/.*127\.0\.0\.1.*/127.0.0.1\tlocalhost.${LOCAL_DN}\tlocalhost/g" "${CFG_FILE}"
else
USE_PRIVILEGE sh -c "'${BIN[printf]}' '%s\t%s\t%s\n' '127.0.0.1' 'localhost.${LOCAL_DN}' 'localhost' >> '${CFG_FILE}'"
fi
if ${BIN[grep]} -q '::1\s\+localhost' "${CFG_FILE}"; then
USE_PRIVILEGE "${BIN[sed]}" "s/.*::1.*/::1\t\tlocalhost.${LOCAL_DN}\tlocalhost/g" "${CFG_FILE}"
else
USE_PRIVILEGE sh -c "'${BIN[printf]}' '%s\t\t%s\t%s\n' '::1' 'localhost.${LOCAL_DN}' 'localhost' >> '${CFG_FILE}'"
fi
if ${BIN[grep]} -q "${LOCAL_HN}" "${CFG_FILE}"; then
USE_PRIVILEGE "${BIN[sed]}" "s/.*${LOCAL_HN}.*/${SELECTED}\t${LOCAL_HN}.${LOCAL_DN}\t${LOCAL_HN}/g" "${CFG_FILE}"
else
USE_PRIVILEGE sh -c "'${BIN[printf]}' '%s\t%s\t%s\n' '${SELECTED}' '${LOCAL_HN}.${LOCAL_DN}' '${LOCAL_HN}' >> '${CFG_FILE}'"
fi
}
function CONFIGURE_IPTABLES {
local -r CFG_FILE="${OSCHROOT}/etc/iptables/iptables.rules"
##############################################################################
local -r BAKTITLE='IPTables Configuration'
##############################################################################
local -a DENYPRTS DENYDSCS DENYSELS ALOWPRTS ALOWDSCS ALOWSELS CMBNPRTS
local -a XTRAPRTS
local RAWSECTN FLTR_INT STATEFUL OBHOSTAD GLBLDROP GLBLACPT REMAINDR NEWIPTBL
local GHGITIPR HELP_MSG PORTNMBR ALOWSLCT DENYSLCT EXISTING SYSSSHPN GH_RULES
local ALOWSLCT DENYSLCT EXTRA_PN FTPROUTE FTPSTATE KNOWN_PN PRTDSCRP LC
RAWSECTN="$("${BIN[grep]}" -Pzo '(?s)\*raw.*?COMMIT\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
FLTR_INT="$("${BIN[grep]}" -Pzo '(?s)\*filter(\n:[0-9A-Z :\[\]-]*)*\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
STATEFUL="$("${BIN[grep]}" -Pzo '(?s)(#.[^\n]*\s*)?-A[^\n]*INPUT[^\n]*?\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
OBHOSTAD="$("${BIN[grep]}" -Pzo '(?s)(#.[^\n]*\s*)?-A\s*OUTPUT[^\n]*? -d [^\n]*?\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
GLBLDROP="$("${BIN[grep]}" -Pzo '(?s)(#.[^\n]*\s*)?-A\s*OUTPUT[^\n]*?DROP[^\n]*?\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
GLBLACPT="$("${BIN[grep]}" -v '^-A\s*\(TCP\|UDP\|OUTPUT\).*\s-[ds]\s' "${CFG_FILE}" | \
"${BIN[grep]}" -Pzo '(?s)(\n#[^\n]+)*(\n-A\s*?(TC|UD)P[^\n]*)+\n' | "${BIN[tr]}" -d "$'\0'")"
REMAINDR="$("${BIN[grep]}" -Pzo '(?s)(\n#.[^\n]*\s*)*?\n*#*\s*-A\s*(TC|UD)P[^\n]*? -[ds] [^\n]*?\n' "${CFG_FILE}" | "${BIN[tr]}" -d "$'\0'")"
# Parse Gloabl Drops and Allows for unknown ports.
SYSSSHPN="$(GET_SSHD_LISTEN_INFO | "${BIN[sed]}" 's/.*on //g;s/ /\n/g' | "${BIN[grep]}" -Po ':[0-9]{1,}$' | "${BIN[tr]}" -d ':')"
EXISTING="$("${BIN[grep]}" -v '^\s*$\|^\s*#' <<< "${GLBLDROP}" | "${BIN[sed]}" 's/.*--dport\s*\([0-9]\+\).*/\1/g' | "${BIN[tr]}" '\n' ' ')"
EXISTING+="$("${BIN[grep]}" -v '^\s*$\|^\s*#' <<< "${GLBLACPT}" | "${BIN[sed]}" 's/.*--dport\s*\([0-9]\+\).*/\1/g' | "${BIN[tr]}" '\n' ' ')"
EXISTING+="${SYSSSHPN}"
EXISTING="$("${BIN[tr]}" ' ' '\n' <<< "${EXISTING}" | "${BIN[sort]}" -nu | "${BIN[tr]}" '\n' ' ')"
for PORTNMBR in ${EXISTING}; do
[[ ${PORTLIST[*]} =~ ${PORTNMBR} ]] && continue
PRTDSCRP=$("${BIN[grep]}" "${PORTNMBR}.*--comment" <<< "${GLBLDROP}${GLBLACPT}" | "${BIN[sed]}" 's/.*comment\s*//g;s/"//g')
[[ -z ${PRTDSCRP} ]] && PRTDSCRP='unknown'
[[ ${PORTNMBR} -eq ${SYSSSHPN} ]] && PRTDSCRP='system-ssh'
XTRAPRTS+=("${PORTNMBR}_${PRTDSCRP}")
done
# Combine the known port list with the unknown
# ports found in the existing iptables.rules
LC=0; EXTRA_PN="${XTRAPRTS[${LC}]%_*}"
for PORTINFO in "${PORTLIST[@]}"; do
KNOWN_PN="${PORTINFO%_*}"
if [[ ${LC} -ge ${#XTRAPRTS[@]} ]] || [[ ${KNOWN_PN%:*} -lt ${EXTRA_PN%:*} ]]; then
CMBNPRTS+=("${PORTINFO}")
else
while [[ ${EXTRA_PN%:*} -lt ${KNOWN_PN%:*} ]] && [[ ${LC} -lt ${#XTRAPRTS[@]} ]]; do
CMBNPRTS+=("${XTRAPRTS[${LC}]}")
((LC++))
EXTRA_PN="${XTRAPRTS[${LC}]%_*}"
done
fi
done
# In order to enable FTP, two things need to exist. So test if those two
# things exist before saying the user already has FTP enabled.
{ "${BIN[grep]}" -- '^\s&-A\s*PREROUTING' <<< "${RAWSECTN}" | \
"${BIN[grep]}" -- '\s*-p\s*tcp\s*' | "${BIN[grep]}" -- '\s*--dport\s*21\s*' | \
"${BIN[grep]}" -- '\s*-j\s*CT\s*' | "${BIN[grep]}" -- '\s*--helper\s*'; } \
&& FTPROUTE=true || FTPROUTE=false
{ "${BIN[grep]}" -- '^\s&-A\s*INPUT' <<< "${STATEFUL}" | \
"${BIN[grep]}" -- '\s*-p\s*tcp\s*' | "${BIN[grep]}" -- '\s*--dport\s*21\s*' | \
"${BIN[grep]}" -- '\s*-j\s*ACCEPT\s*' | "${BIN[grep]}" -- '\s*-m\s*tcp\s*'; } \
&& FTPSTATE=true || FTPSTATE=false
##############################################################################
HELP_MSG='Choose which ports to close universally\n'
HELP_MSG+='(no source/destination restrictions):'
##############################################################################
for PORTINFO in "${CMBNPRTS[@]}"; do
DENYPRTS+=("${PORTINFO%_*}")
DENYDSCS+=("${PORTINFO#*_}")
[[ ${GLBLDROP} =~ --dport[[:blank:]]+${DENYPRTS[-1]}[[:blank:]]+ ]] \
&& DENYSELS+=(on) || DENYSELS+=(off)
done
DIALOG_MULTI_SELECT "${TITLEBAR}" "${BAKTITLE}" 'showtags' \
"${HELP_MSG}" 'DENYPRTS' 'DENYDSCS' 'DENYSELS' || return 1
DENYSLCT="$(</tmp/selection)"
##############################################################################
HELP_MSG='Choose which ports to open universally\n'
HELP_MSG+='(no source/destination restrictions):'
##############################################################################
for PORTINFO in "${CMBNPRTS[@]}"; do
[[ ${DENYSLCT} =~ ${PORTINFO%_*} ]] && continue
ALOWPRTS+=("${PORTINFO%_*}")
ALOWDSCS+=("${PORTINFO#*_}")
if [[ ${ALOWPRTS[-1]} -eq 21 ]]; then
{ ${FTPROUTE} && ${FTPSTATE}; } && ALOWSELS+=(on) || ALOWSELS+=(off)
else
[[ ${GLBLACPT} =~ --dport[[:blank:]]+${ALOWPRTS[-1]}[[:blank:]]+ ]] \
&& ALOWSELS+=(on) || ALOWSELS+=(off)
fi
done
if [[ ${#ALOWPRTS[@]} -gt 0 ]]; then
DIALOG_MULTI_SELECT "${TITLEBAR}" "${BAKTITLE}" 'showtags' \
"${HELP_MSG}" 'ALOWPRTS' 'ALOWDSCS' 'ALOWSELS' || return 1
ALOWSLCT="$(</tmp/selection)"
fi
##############################################################################
HELP_MSG='Allow communication with GitHub git IP addresses?\n'
MELP_MSG+='(Used when using SSH access to GitHub git repositories.)'
##############################################################################
if DIALOG_YESNO "${TITLEBAR}" "${BAKTITLE}" "${HELP_MSG}"; then
LC=0
while read -r GHGITIPR; do
((LC++))
GH_RULES+="-A OUTPUT -d ${GHGITIPR} -p tcp -m tcp --dport 22 -j ACCEPT -m comment --comment \"GitHub IP range ${LC}\""$'\n'
done < <("${BIN[curl]}" -s https://api.github.com/meta | "${BIN[sed]}" ':a;N;$!ba;s/.*git[^\n]\+\[//g;s/].*//g;s/\s\s\+//g;s/"//g;s/,/\n/g' | "${BIN[grep]}" -v ':')
fi
if [[ ${ALOWSLCT} =~ [[:blank:]]21[[:blank:]] ]]; then
NEWIPTBL+='*raw'$'\n'
NEWIPTBL+=':PREROUTING ACCEPT [0.0]'$'\n'
NEWIPTBL+='-A PREROUTING -p tcp --dport 21 -j CT --helper ftp'$'\n'
NEWIPTBL+='COMMIT'$'\n\n'
fi
NEWIPTBL+='*filter'$'\n'
NEWIPTBL+=':INPUT DROP [0:0]'$'\n'
NEWIPTBL+=':FORWARD DROP [0:0]'$'\n'
NEWIPTBL+=':OUTPUT ACCEPT [0:0]'$'\n'
NEWIPTBL+=':TCP - [0:0]'$'\n'
NEWIPTBL+=':UDP - [0:0]'$'\n\n'
NEWIPTBL+='# Allow traffic that belongs to established connections or new valid related traffic'$'\n'
NEWIPTBL+='-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT'$'\n'
if [[ ${ALOWSLCT} =~ [[:blank:]]21[[:blank:]] ]]; then
NEWIPTBL+='# Accept FTP connections'$'\n'
NEWIPTBL+='-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT'$'\n'
fi
NEWIPTBL+='# Accept all traffic from the "loopback" (lo) interface'$'\n'
NEWIPTBL+='-A INPUT -i lo -j ACCEPT'$'\n'
NEWIPTBL+='# Accept all new incoming ICMP echo (ping) requests'$'\n'
NEWIPTBL+='-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT'$'\n'
NEWIPTBL+='# Drop all traffic with an "INVALID" state match'$'\n'
NEWIPTBL+='-A INPUT -m conntrack --ctstate INVALID -j DROP'$'\n'
NEWIPTBL+='# Attach the UDP chains to the INPUT chain to handle all new incoming connections'$'\n'
NEWIPTBL+='-A INPUT -p udp -m conntrack --ctstate NEW -j UDP'$'\n'
NEWIPTBL+='# Attach the TCP chains to the INPUT chain to handle all new incoming connections'$'\n'
NEWIPTBL+='-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP'$'\n'
NEWIPTBL+='# Reject UDP streams with ICMP port unreachable if port is not open'$'\n'
NEWIPTBL+='-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable'$'\n'
NEWIPTBL+='# Reject TCP connections with TCP RESET packets if port is not open'$'\n'
NEWIPTBL+='-A INPUT -p tcp -j REJECT --reject-with tcp-reset'$'\n'
NEWIPTBL+='# Reject all remaining incoming traffic with icmp protocol unreachable message'$'\n'
NEWIPTBL+='-A INPUT -j REJECT --reject-with icmp-proto-unreachable'$'\n\n'
[[ -n ${GH_RULES} ]] && NEWIPTBL+='####################### GITHUB GIT IP ADDRESSES #######################'$'\n\n'
[[ -n ${GH_RULES} ]] && NEWIPTBL+="${GH_RULES}"$'\n'
[[ -n ${DENYSLCT} ]] && NEWIPTBL+='###################### UNIVERSALLY CLOSED PORTS #######################'$'\n\n'
for PORTNMBR in ${DENYSLCT}; do
PRTDSCRP=$("${BIN[sed]}" "s/.* ${PORTNMBR}_\([a-z-]*\).*/\1/g" <<< "${CMBNPRTS[@]}")
NEWIPTBL+="-A TCP -p tcp -m tcp --dport ${PORTNMBR} -j DROP -m comment --comment \"${PRTDSCRP}:tcp\""$'\n'
NEWIPTBL+="-A UDP -p udp -m udp --dport ${PORTNMBR} -j DROP -m comment --comment \"${PRTDSCRP}:udp\""$'\n'
done
[[ -n ${DENYSLCT} ]] && NEWIPTBL+=$'\n'
[[ -n ${ALOWSLCT} ]] && NEWIPTBL+='###################### UNIVERSALLY OPENED PORTS #######################'$'\n\n'
for PORTNMBR in ${ALOWSLCT}; do
[[ ${PORTNMBR} -eq 21 ]] && continue
PRTDSCRP=$("${BIN[sed]}" "s/.* ${PORTNMBR}_\([a-z-]*\).*/\1/g" <<< "${CMBNPRTS[@]}")
NEWIPTBL+="-A TCP -p tcp -m tcp --dport ${PORTNMBR} -j ACCEPT -m comment --comment \"${PRTDSCRP}:tcp\""$'\n'
NEWIPTBL+="-A UDP -p udp -m udp --dport ${PORTNMBR} -j ACCEPT -m comment --comment \"${PRTDSCRP}:udp\""$'\n'
done
[[ -n ${ALOWSLCT} ]] && NEWIPTBL+=$'\n'
[[ -n ${REMAINDR} ]] && NEWIPTBL+="${REMAINDR}"
NEWIPTBL+='COMMIT'
if [[ -e "${CFG_FILE}" ]]; then
BACKUPDT="$("${BIN[date]}" +%Y-%m-%d_%H:%M:%S)"
USE_PRIVILEGE "${BIN[mv]}" "${CFG_FILE}" "${CFG_FILE}.${BACKUPDT}"
fi
USE_PRIVILEGE sh -c "echo '${NEWIPTBL}' > '${CFG_FILE}'"
if [[ -n ${BACKUPDT} ]]; then
DIALOG_MSGBOX "${TITLEBAR}" "Configuration Backup" "Existing configuration was saved to iptables.rules.${BACKUPDT}"
fi
}
function CONFIGURE_MKINITCPIO_COMPRESSION {
local -r CFG_FILE="${OSCHROOT}/etc/mkinitcpio.conf"
[[ -e "${CFG_FILE}" ]] || return 0
local -r CFG_ITEM="COMPRESSION"
##############################################################################
local -r BAKTITLE="MkInitCPIO Compression"
local -r HELP_MSG="Choose how MkInitCPIO compresses the InitRAMFS:"
##############################################################################
local -a SUGGESTS
local SELECTED PREV_CFG="$(GET_MKINITCPIO_COMPRESSION)"
SUGGESTS=(cat bzip2 gzip lz4 lzma lzop xz zstd)
DIALOG_SINGLE_SELECT "${TITLEBAR}" "${BAKTITLE}" 'hidetags' "${PREV_CFG}" \
"${HELP_MSG}" 'SUGGESTS' 'SUGGESTS' || return 1
SELECTED="$(</tmp/selection)"
# Set all COMPRESSION options to be commented out
USE_PRIVILEGE "${BIN[sed]}" -i "s/^\s*${CFG_ITEM}=\"\([a-z0-9]\+\)\"/#${CFG_ITEM}=\"\1\"/g" "${CFG_FILE}"
if "${BIN[grep]}" -q "${CFG_ITEM}=\"${SELECTED}\"" "${CFG_FILE}"; then
# If a COMPRESSION option is found commented out, un-comment it
USE_PRIVILEGE "${BIN[sed]}" -i "s/^\s*#\s*${CFG_ITEM}=\"${SELECTED}\"/${CFG_ITEM}=\"${SELECTED}\"/g" "${CFG_FILE}"
else
# Find the First Commented-Out Compression OPTion
FCOCOPT="$("${BIN[grep]}" "^\s*#\s*${CFG_ITEM}=" "${CFG_FILE}" | "${BIN[head]}" -1)"
# Inset a new compression option above that one
USE_PRIVILEGE "${BIN[sed]}" -i "s/${FCOCOPT}/${CFG_ITEM}=\"${SELECTED}\"\n${FCOCOPT}/g" "${CFG_FILE}"
fi
}
function CONFIGURE_MKINITCPIO_HOOKS {
local -r CFG_FILE="${OSCHROOT}/etc/mkinitcpio.conf"
[[ -e "${CFG_FILE}" ]] || return 0
local -r CFG_ITEM="HOOKS"
##############################################################################
local -r BAKTITLE='MkInitCPIO Hooks'
local -r HELP_MSG='NOTE: Do NOT wantonly disable base or udev unless you know what you are doing!!!'
##############################################################################
local -a VALHOOKS SUGGESTS DESCRIPS SELSTATE
local THISHOOK HELPTEXT SELECTED PREV_CFG="$(GET_MKINITCPIO_HOOKS)"
# These are the hooks we are willing to deal with. As the systemd stuff isn't
# well documented, we won't deal with it and will stick with the busybox stuff.
# Also, not sure why Arch packages a plymouth-encrypt initcpio hook with plymouth
# when it's virtually the same as the regular encrypt hook sans a missing
# dm-integrity module that the regular encrypt hook adds.
VALHOOKS=(base udev usr resume shutdown btrfs memdisk plymouth hostdata
autodetect modconf block zfs net dmraid mdadm filesystems keyboard
keymap consolefont encrypt lvm2 fsck strip)
for THISHOOK in "${VALHOOKS[@]}"; do
[[ -e "${OSCHROOT}/usr/lib/initcpio/install/${THISHOOK}" ]] && SUGGESTS+=("${THISHOOK}")
done
for THISHOOK in "${SUGGESTS[@]}"; do
HELPTEXT="$("${BIN[sed]}" ':a;N;$!ba;
s/.*HELPEOF\n\(.*\)\nHELPEOF.*/\1/g;
s/\n\n.*//g;
s/\. .*/./g;
s/,.*/./g;
s/\n(.*/./g;
s/\n/ /g;
s/ using pata\././g;
s/ a support/ support/g;
s/Disk/disk/g;
s/This //g;
s/^hook //g;
s/^will //g' "${OSCHROOT}/usr/lib/initcpio/install/${THISHOOK}")"
DESCRIPS+=("${HELPTEXT^}")
[[ ${PREV_CFG} =~ ${THISHOOK} ]] && SELSTATE+=(on) || SELSTATE+=(off)
done
DIALOG_MULTI_SELECT "${TITLEBAR}" "${BAKTITLE}" 'showtags' \
"${HELP_MSG}" 'SUGGESTS' 'DESCRIPS' 'SELSTATE' || return 1
SELECTED="$(</tmp/selection)"
USE_PRIVILEGE "${BIN[sed]}" -i "s/^\s*${CFG_ITEM}=.*/${CFG_ITEM}=(${SELECTED})/g" "${CFG_FILE}"
}
function CONFIGURE_MKINITCPIO_MODULES {
local -r CFG_FILE="${OSCHROOT}/etc/mkinitcpio.conf"
[[ -e "${CFG_FILE}" ]] || return 0
local -r CFG_ITEM="MODULES"
##############################################################################
local -r BAKTITLE='MkInitCPIO Modules'
local HELP_MSG='You normally do not need to add modules to the InitRAMFS.\n'
HELP_MSG+='However you might want to do so under special circumstances.\n\n'
HELP_MSG+='NVIDIA Early KMS: nvidia + nvidia_drm + nvidia_modeset + nvidia_uvm\n'
HELP_MSG+='Other Early KMS: amdgpu or radeon or i915 or nouveau\n'
HELP_MSG+='QEMU Early KMS: bochs_drm or cirrus or qxl or virtio-gpu\n'
HELP_MSG+='Logitech Wireless: hid_logitech_dj + uhci_hcd + usbhid\n'