summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclarkzjw <[email protected]>2023-02-08 00:40:09 -0800
committerclarkzjw <[email protected]>2023-02-08 00:40:09 -0800
commit1204730924436ef9e1c7c49c9557837f9a5ed0e8 (patch)
tree129d79dfd11245751cee6d4082ff5d2f6e941610 /ansible/roles/common/files
parent9635ac4dedf69de5bff65785bcc16bef80b52d75 (diff)
downloadmail-master.tar.gz
fork https://github.com/mattsta/mailwebHEADmaster
Diffstat (limited to 'ansible/roles/common/files')
-rw-r--r--ansible/roles/common/files/ffdhe2048.pem8
-rw-r--r--ansible/roles/common/files/ffdhe3072.pem11
-rw-r--r--ansible/roles/common/files/ffdhe4096.pem13
-rw-r--r--ansible/roles/common/files/inputrc61
-rwxr-xr-xansible/roles/common/files/net-listeners.py334
-rwxr-xr-xansible/roles/common/files/ssh-transfer-only.sh11
-rw-r--r--ansible/roles/common/files/vimrc.local25
7 files changed, 463 insertions, 0 deletions
diff --git a/ansible/roles/common/files/ffdhe2048.pem b/ansible/roles/common/files/ffdhe2048.pem
new file mode 100644
index 0000000..9b182b7
--- /dev/null
+++ b/ansible/roles/common/files/ffdhe2048.pem
@@ -0,0 +1,8 @@
1-----BEGIN DH PARAMETERS-----
2MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
3+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
487VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
5YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
67MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
7ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
8-----END DH PARAMETERS-----
diff --git a/ansible/roles/common/files/ffdhe3072.pem b/ansible/roles/common/files/ffdhe3072.pem
new file mode 100644
index 0000000..fb31ccd
--- /dev/null
+++ b/ansible/roles/common/files/ffdhe3072.pem
@@ -0,0 +1,11 @@
1-----BEGIN DH PARAMETERS-----
2MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
3+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
487VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
5YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
67MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
7ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
87lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
9nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu
10N///////////AgEC
11-----END DH PARAMETERS-----
diff --git a/ansible/roles/common/files/ffdhe4096.pem b/ansible/roles/common/files/ffdhe4096.pem
new file mode 100644
index 0000000..3cf0fcb
--- /dev/null
+++ b/ansible/roles/common/files/ffdhe4096.pem
@@ -0,0 +1,13 @@
1-----BEGIN DH PARAMETERS-----
2MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
3+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
487VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
5YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
67MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
7ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
87lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
9nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
108W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
11iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
12zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
13-----END DH PARAMETERS-----
diff --git a/ansible/roles/common/files/inputrc b/ansible/roles/common/files/inputrc
new file mode 100644
index 0000000..47e7275
--- /dev/null
+++ b/ansible/roles/common/files/inputrc
@@ -0,0 +1,61 @@
1# do not bell on tab-completion
2#set bell-style none
3
4set meta-flag on
5set input-meta on
6set convert-meta off
7set output-meta on
8
9# Completed names which are symbolic links to
10# directories have a slash appended.
11set mark-symlinked-directories on
12
13$if mode=emacs
14
15# for linux console and RH/Debian xterm
16"\e[1~": beginning-of-line
17"\e[4~": end-of-line
18# commented out keymappings for pgup/pgdown to reach begin/end of history
19#"\e[5~": beginning-of-history
20#"\e[6~": end-of-history
21"\e[5~": history-search-backward
22"\e[6~": history-search-forward
23"\e[3~": delete-char
24"\e[2~": quoted-insert
25"\e[5C": forward-word
26"\e[5D": backward-word
27"\e[1;5C": forward-word
28"\e[1;5D": backward-word
29
30# for rxvt
31"\e[8~": end-of-line
32"\eOc": forward-word
33"\eOd": backward-word
34
35# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
36"\eOH": beginning-of-line
37"\eOF": end-of-line
38
39# for freebsd console
40"\e[H": beginning-of-line
41"\e[F": end-of-line
42$endif
43
44# cd d<TAB> will match documents or Documents
45set completion-ignore-case on
46
47# front-of-command up and down completion
48"\e[A":history-search-backward
49"\e[B":history-search-forward
50
51# This is the magic command.
52# Enables sane tcsh-like ctrl-d completion showing.
53Control-d:delete-char-or-list
54
55# oddly, menu-complete makes the menu *not* appear
56# just cycle through each option
57Tab:menu-complete
58
59# stop asking if I "Really want to see 102 completions"
60set completion-query-items 350
61set page-completions off
diff --git a/ansible/roles/common/files/net-listeners.py b/ansible/roles/common/files/net-listeners.py
new file mode 100755
index 0000000..f8b39cd
--- /dev/null
+++ b/ansible/roles/common/files/net-listeners.py
@@ -0,0 +1,334 @@
1#!/usr/bin/env python3
2
3""" Output a colorized list of listening addresses with owners.
4
5This tool parses files in /proc directly to obtain the list
6of IPv4 and IPv6 addresses listening on tcp, tcp6, udp, and udp6 ports
7also with pids of processes responsible for the listening.
8
9Due to permission restrictions on Linux, script must be run as root
10to determine which pids match which listening sockets.
11
12This is also something like:
13 osqueryi "select po.pid, rtrim(p.cmdline), po.family, po.local_address, po.local_port from process_open_sockets as po JOIN processes as p ON po.pid=p.pid WHERE po.state='LISTEN';"
14
15"""
16
17import collections
18import subprocess
19import codecs
20import socket
21import struct
22import glob
23import sys
24import re
25import os
26
27TERMINAL_WIDTH = "/usr/bin/tput cols" # could also be "stty size"
28
29ONLY_LOWEST_PID = False
30
31# oooh, look, a big dirty global dict collecting all our data without being
32# passed around! call the programming police!
33inodes = {}
34
35
36class Color:
37 HEADER = '\033[95m'
38 OKBLUE = '\033[94m'
39 OKGREEN = '\033[92m'
40 WARNING = '\033[93m'
41 FAIL = '\033[91m'
42 BOLD = '\033[1m'
43 UNDERLINE = '\033[4m'
44 END = '\033[0m'
45
46
47COLOR_HEADER = Color.HEADER
48COLOR_OKAY = Color.OKBLUE
49COLOR_WARNING = Color.FAIL
50COLOR_END = Color.END
51
52# This should capture:
53# 127.0.0.0/8
54# 192.168.0.0/16
55# 10.0.0.0/8
56# 169.254.0.0/16
57# 172.16.0.0/12
58# ::1
59# fe80::/10
60# fc00::/7
61# fd00::/8
62NON_ROUTABLE_REGEX = r"""^((127\.) |
63 (192\.168\.) |
64 (10\.) |
65 (169\.254\.) |
66 (172\.1[6-9]\.) |
67 (172\.2[0-9]\.) |
68 (172\.3[0-1]\.) |
69 (::1) |
70 ([fF][eE]80)
71 ([fF][cCdD]))"""
72likelyLocalOnly = re.compile(NON_ROUTABLE_REGEX, re.VERBOSE)
73
74
75def run(thing):
76 """ Run any string as an async command invocation. """
77 # We don't use subprocess.check_output because we want to run all
78 # processes async
79 return subprocess.Popen(thing.split(), stdout=subprocess.PIPE)
80
81
82def readOutput(ranCommand):
83 """ Return array of rows split by newline from previous invocation. """
84 stdout, stderr = ranCommand.communicate()
85 return stdout.decode('utf-8').strip().splitlines()
86
87
88def procListeners():
89 """ Wrapper to parse all IPv4 tcp udp, and, IPv6 tcp6 udp6 listeners. """
90
91 def processProc(name):
92 """ Process IPv4 and IPv6 versions of listeners based on ``name``.
93
94 ``name`` is either 'udp' or 'tcp' so we parse, for each ``name``:
95 - /proc/net/[name]
96 - /proc/net/[name]6
97
98 As in:
99 - /proc/net/tcp
100 - /proc/net/tcp6
101 - /proc/net/udp
102 - /proc/net/udp6
103 """
104
105 def ipv6(addr):
106 """ Convert /proc IPv6 hex address into standard IPv6 notation. """
107 # turn ASCII hex address into binary
108 addr = codecs.decode(addr, "hex")
109
110 # unpack into 4 32-bit integers in big endian / network byte order
111 addr = struct.unpack('!LLLL', addr)
112
113 # re-pack as 4 32-bit integers in system native byte order
114 addr = struct.pack('@IIII', *addr)
115
116 # now we can use standard network APIs to format the address
117 addr = socket.inet_ntop(socket.AF_INET6, addr)
118 return addr
119
120 def ipv4(addr):
121 """ Convert /proc IPv4 hex address into standard IPv4 notation. """
122 # Instead of codecs.decode(), we can just convert a 4 byte hex
123 # string to an integer directly using python radix conversion.
124 # Basically, int(addr, 16) EQUALS:
125 # aOrig = addr
126 # addr = codecs.decode(addr, "hex")
127 # addr = struct.unpack(">L", addr)
128 # assert(addr == (int(aOrig, 16),))
129 addr = int(addr, 16)
130
131 # system native byte order, 4-byte integer
132 addr = struct.pack("=L", addr)
133 addr = socket.inet_ntop(socket.AF_INET, addr)
134 return addr
135
136 isUDP = name == "udp"
137
138 # Iterate four files: /proc/net/{tcp,udp}{,6}
139 # ipv4 has no prefix, while ipv6 has 6 appended.
140 for ver in ["", "6"]:
141 with open(f"/proc/net/{name}{ver}", 'r') as proto:
142 proto = proto.read().splitlines()
143 proto = proto[1:] # drop header row
144
145 for cxn in proto:
146 cxn = cxn.split()
147
148 # /proc/net/udp{,6} uses different constants for LISTENING
149 if isUDP:
150 # These constants are based on enum offsets inside
151 # the Linux kernel itself. They aren't likely to ever
152 # change since they are hardcoded in utilities.
153 isListening = cxn[3] == "07"
154 else:
155 isListening = cxn[3] == "0A"
156
157 # Right now this is a single-purpose tool so if process is
158 # not listening, we avoid further processing of this row.
159 if not isListening:
160 continue
161
162 ip, port = cxn[1].split(':')
163 if ver:
164 ip = ipv6(ip)
165 else:
166 ip = ipv4(ip)
167
168 port = int(port, 16)
169 inode = cxn[9]
170
171 # We just use a list here because creating a new sub-dict
172 # for each entry was noticably slower than just indexing
173 # into lists.
174 inodes[int(inode)] = [ip, port, f"{name}{ver}"]
175
176 processProc("tcp")
177 processProc("udp")
178
179
180def appendToInodePidMap(fd, inodePidMap):
181 """ Take a full path to /proc/[pid]/fd/[fd] for reading.
182
183 Populates both pid and full command line of pid owning an inode we
184 are interested in.
185
186 Basically finds if any inodes on this pid is a listener we previously
187 recorded into our ``inodes`` dict. """
188 _, _, pid, _, _ = fd.split('/')
189 try:
190 target = os.readlink(fd)
191 except FileNotFoundError:
192 # file vanished, can't do anything else
193 return
194
195 if target.startswith("socket"):
196 ostype, inode = target.split(':')
197 # strip brackets from fd string (it looks like: [fd])
198 inode = int(inode[1:-1])
199 inodePidMap[inode].append(int(pid))
200
201
202def addProcessNamesToInodes():
203 """ Loop over every fd in every process in /proc.
204
205 The only way to map an fd back to a process is by looking
206 at *every* processes fd and extracting backing inodes.
207
208 It's basically like a big awkward database join where you don't
209 have an index on the field you want.
210
211 Also, due to Linux permissions (and Linux security concerns),
212 only the root user can read fd listing of processes not owned
213 by the current user. """
214
215 # glob glob glob it all
216 allFDs = glob.iglob("/proc/*/fd/*")
217 inodePidMap = collections.defaultdict(list)
218
219 for fd in allFDs:
220 appendToInodePidMap(fd, inodePidMap)
221
222 for inode in inodes:
223 if inode in inodePidMap:
224 for pid in inodePidMap[inode]:
225 try:
226 with open(f"/proc/{pid}/cmdline", 'r') as cmd:
227 # /proc command line arguments are delimited by
228 # null bytes, so undo that here...
229 cmdline = cmd.read().split('\0')
230 inodes[inode].append((pid, cmdline))
231 except BaseException:
232 # files can vanish on us at any time (and that's okay!)
233 # But, since the file is gone, we want the entire fd
234 # entry gone too:
235 pass # del inodes[inode]
236
237
238def checkListenersProc():
239 terminalWidth = run(TERMINAL_WIDTH)
240
241 procListeners()
242 addProcessNamesToInodes()
243 tried = inodes
244
245 try:
246 cols = readOutput(terminalWidth)[0]
247 cols = int(cols)
248 except BaseException:
249 cols = 80
250
251 # Print our own custom output header...
252 proto = "Proto"
253 addr = "Listening"
254 pid = "PID"
255 process = "Process"
256 print(f"{COLOR_HEADER}{proto:^5} {addr:^25} {pid:>5} {process:^30}")
257
258 # Could sort by anything: ip, port, proto, pid, command name
259 # (or even the fd integer if that provided any insight whatsoever)
260 def compareByPidOrPort(what):
261 k, v = what
262 # v = [ip, port, proto, pid, cmd]
263 # - OR -
264 # v = [ip, port, proto]
265
266 # If we're not running as root we can't pid and command mappings for
267 # the processes of other users, so sort the pids we did find at end
268 # of list and show UNKNOWN entries first
269 # (because the lines will be shorter most likely so the bigger visual
270 # weight should be lower in the display table)
271 try:
272 # Pid available! Sort by first pid, subsort by IP then port.
273 return (1, v[3], v[0], v[1])
274 except BaseException:
275 # No pid available! Sort by port number then IP then... port again.
276 return (0, v[1], v[0], v[1])
277
278 # Sort results by pid...
279 for name, vals in sorted(tried.items(), key=compareByPidOrPort):
280 attachedPids = vals[3:]
281 if attachedPids:
282 desc = [f"{pid:5} {' '.join(cmd)}" for pid, cmd in vals[3:]]
283 else:
284 # If not running as root, we won't have pid or process, so use
285 # defaults
286 desc = ["UNKNOWN (must be root for global pid mappings)"]
287
288 port = vals[1]
289 try:
290 # Convert port integer to service name if possible
291 port = socket.getservbyport(port)
292 except BaseException:
293 # If no match, just use port number directly.
294 pass
295
296 addr = f"{vals[0]}:{port}"
297 proto = vals[2]
298
299 # If IP address looks like it could be visible to the world,
300 # throw up a color.
301 # Note: due to port forwarding and NAT and other issues,
302 # this clearly isn't exhaustive.
303 if re.match(likelyLocalOnly, addr):
304 colorNotice = COLOR_OKAY
305 else:
306 colorNotice = COLOR_WARNING
307
308 isFirstLine = True
309 for line in desc:
310 if isFirstLine:
311 output = f"{colorNotice}{proto:5} {addr:25} {line}"
312 isFirstLine = False
313 else:
314 output = f"{' ':31} {line}"
315
316 # Be a polite terminal citizen by limiting our width to user's width
317 # (colors take up non-visible space, so add it to our col count)
318 print(output[:cols + (len(colorNotice) if isFirstLine else 0)])
319
320 if ONLY_LOWEST_PID:
321 break
322
323 print(COLOR_END)
324
325
326if __name__ == "__main__":
327 # cheap hack garbage way of setting one option
328 # if we need more options, obviously pull in argparse
329 if len(sys.argv) > 1:
330 ONLY_LOWEST_PID = True
331 else:
332 ONLY_LOWEST_PID = False
333
334 checkListenersProc()
diff --git a/ansible/roles/common/files/ssh-transfer-only.sh b/ansible/roles/common/files/ssh-transfer-only.sh
new file mode 100755
index 0000000..c1f0624
--- /dev/null
+++ b/ansible/roles/common/files/ssh-transfer-only.sh
@@ -0,0 +1,11 @@
1#!/usr/bin/env bash
2
3# Only allow ssh commands starting with 'scp' or 'rsync'
4case $SSH_ORIGINAL_COMMAND in
5 scp*)
6 $SSH_ORIGINAL_COMMAND ;;
7 rsync*)
8 $SSH_ORIGINAL_COMMAND ;;
9 *)
10 echo "Not allowed with this key: $SSH_ORIGINAL_COMMAND" ;;
11esac
diff --git a/ansible/roles/common/files/vimrc.local b/ansible/roles/common/files/vimrc.local
new file mode 100644
index 0000000..378d91e
--- /dev/null
+++ b/ansible/roles/common/files/vimrc.local
@@ -0,0 +1,25 @@
1set encoding=utf-8
2
3set ignorecase
4set smartcase
5
6set title
7
8set backupdir=~/.vim-tmp,/tmp
9set directory=~/.vim-tmp,/tmp
10
11set ruler
12
13filetype plugin indent on
14
15set ai
16set expandtab
17set tabstop=4
18set shiftwidth=4
19
20autocmd BufEnter * :syntax sync fromstart
21
22set hlsearch
23colorscheme peachpuff
24
25set wildignore+=*/tmp/*,*.so,*.swp,*.zip,*.o,*.dSYM,tags
Powered by cgit v1.2.3 (git 2.41.0)