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
|
#+title: Authentication and Name Services
#+date: 2026-03-30 Mon
#+author: W. Kosior
#+email: wkosior@agh.edu.pl
* Pluggable Authentication Modules
- in many UNIX'es
- replace =/etc/shadow=
- SQL database? No problem.
- TOTP?
- smart cards?
- How about LDAP?
- =apt-cache search libpam- | grep -cE 'PAM .*module'= → 41
- SSO
- Windows equivalent: Security Support Provider Interface
* PAM — Config
#+begin_example
$ ls /etc/pam.d/
chfn common-session-noninteractive newusers su
chpasswd cron other su-l
chsh cups passwd sudo
common-account lightdm ppp sudo-i
common-auth lightdm-autologin runuser xfce4-screensaver
common-password lightdm-greeter runuser-l
common-session login sshd
#+end_example
* PAM — Config, Cont.
#+begin_example
account required pam_unix.so
account sufficient pam_succeed_if.so uid < 1000 quiet
account [default=bad success=ok user_unknown=ignore] pam_ldap.so
account required pam_permit.so
#+end_example
/source: [[https://wiki.debian.org/LDAP/PAM]]/
* PAM — Config, Cont…
=/etc/pam.d/common-auth=
#+begin_example
auth [success=2 default=ignore] pam_unix.so nullok
auth [success=1 default=ignore] pam_ldap.so minimum_uid=1000 use_first_pass
auth requisite pam_deny.so
auth required pam_permit.so
auth optional pam_cap.so
#+end_example
* PAM — Config — Management Groups
/(aka types)/
- =auth=
- =account= (access management other than auth)
- =passwd= (updating password)
- =session= (actions related to session start / end)
* PAM — Config — Control Values
- =required=
- =requisite= (immediate return)
- =sufficient= (immediate return)
- =optional=
- =include= (other file)
- =substack= (other file)
- =[success=ok new_authtok_reqd=ok ignore=ignore default=bad]=
* =get*()=
- =getpwent()=
- =getgrent()=
- =getaddrinfo()=
- =getnameinfo()=
- =getnetent()=
- …
* getent
- hosts
- passwd
- shadow
- group
- ahosts
- networks
- …
* NSS
- =/etc/nsswitch.conf=
- sample entry: =passwd: files systemd ldap=
- queries for passwd entries should use, in order:
- =/etc/passwd= file
- (=/usr/lib/x86_64-linux-gnu/libnss_files.so.2= service module)
- systemd-userdb
- (=/usr/lib/x86_64-linux-gnu/libnss_systemd.so.2= service module)
- ldap
- (=/usr/lib/x86_64-linux-gnu/libnss_ldap.so.2= service module)
* NSS, Cont.
- sample entry: =hosts: files mdns4_minimal [NOTFOUND=return] dns=
- queries for host addresses/names should use, in order:
- =/etc/hosts= file
- Multicast DNS (=*.local= names)
- terminating immediately if a =*.local= name was being queried
- dns (=/etc/resolv.conf=)
* nscd
- caching
- sometimes replaced with systemd-resolved…
- query time reduction
- DNS
- remote passwd, etc. entries
* Hostnames
How does the OS know localhost → 127.0.0.1?
- =/etc/hosts= (read by the =files= service of NSS)
- sample entry: =149.156.98.68 galaxy.agh.edu.pl galaxy home.agh.edu.pl home=
- IP address
- canonical name
- aliases
- try, say, the replacement 127.0.0.1 → 127.3.4.5 in =/etc/hosts=
* Domain & FQDN
- =/etc/hostname=
- read and stored in the kernel (=sethostname()=)
- domain & Fully Qualified Domain Name
- every network-plugged computer is in a domain and has a name
- RIGHT!?
- Debian et al. use
- =/etc/hostname= → hostname
- hostname & =/etc/hosts= → FQDN
- hostname & FQDN → domainname
* LDAP
- X.500 (Directory Access Protocol) → L(ightweight)DAP
- ports: 389, 636 (TLS)
- *directory services*
- hierarchical database
- sample uses:
- information about people
- \________"\________ assets/property
- \________"\________ groups/projects
- DNS data
- used for SSO
- both UNIX (PAM) & Windows
- (Active Directory ⊃ LDAP)
* Object Identifiers
- for: things, concepts…
- =1.3.91= — Cisco Systems
- =2.16.840.1.101.3.7.2.1.0= — X.509 Certificate for Digital Signature
- =1.3.6.1.1.1.2.0= — posixAccount Object Class (RFC 2307)
- =1.3.6.1.1.1.1.1= — gidNumber Attribute Type \____"\_____
* Directory Information Tree
#+begin_example
"" (empty)
|
dc=com
|
dc=example
/ \
/ \
ou=users ou=groups
/ | \
/ | \
cn=theodore cn=eugenia cn=students
#+end_example
(domain component, organizational unit, common name)
* Distinguished Names
- example: =cn=theodore,ou=users,dc=example,dc=com=
- Relative Distinguished Names (1 or more per level)
- example: =ou=users=
* Entities & Attributes
#+begin_example
dn: cn=theodore,ou=users,dc=example,dc=com
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: theodore
uid: theodore
uidNumber: 1041
gidNumber: 103
homeDirectory: /home/users/theodore
loginShell: /bin/bash
userPassword: {SSHA}0XMFoclVCl2DEl+lKvNgX+za5H3IdWgBVkZf
#+end_example
* Entities & Attributes — Schema
#+begin_example
( 0.9.2342.19200300.100.1.1 NAME 'uid' EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256}
X-ORIGIN 'RFC 1274' )
#+end_example
- OpenLDAP → schema itself in the directory service
- entities conform to types
- can define own object classes / attribute types
* LDIF
#+begin_example
dn: cn=theodore,ou=users,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SSHA}GcSgGl/7qsbOr4cJcwaXrNX4k52RYziVav4E
-
add: description
description: A *nix fan.
#+end_example
* LDAP Operations
- modifications
- queries
- filter example: =(&(|(cn=theodore)(cn=alexander))(gidNumber=103))=
- indexes possible (and used!)
* LDAP Security
- binding
- e.g., as =cn=admin,dc=example,dc=com=
- or =cn=theodore,ou=users,dc=example,dc=com=
- or anonymous
- ACLs
- read permission
- write permission
- authenticate permission
- in case of OpenLDAP — stored in directory service itself
* Simple Authentication and Security Layer
- authentication independent from protocol / application
- used in IMAP, SMTP, XMPP, *LDAP*
- not mandatory to be able to set up
- recognizable SASL mechanisms (do not use the first 3 (without TLS))
- LOGIN
- PLAIN
- DIGEST-MD5
- EXTERNAL (application-specific semantics)
- ldapi ("inter-process", socket)
- TLS (client cert)
- NTLM (nonstandard for Microsoft fans)
- GSSAPI
* Directory Services — Popular Software
- 389 Directory Server
- commercial version: Red Hat Directory Server
- Active Directory (Microsoft)
- OpenLDAP
- modules?
* Generic Security Services Application Programming Interface
- the SASL mechanism most useful to us
- *Kerberos* authentication
- data security included
- (unlike in other listed mechanisms)
* Kerberos
- realms (e.g., =EXAMPLE.COM=)
- principals
- people (e.g., =theodore@EXAMPLE.COM=)
- services (e.g., =nfs-server/titan@EXAMPLE.COM=)
- machines
- symmetric cryptography
- secrets shared between Kerberos servers and clients
* Kerberos Authentication
- Client (e.g., user)
- Authentication Server
- Ticket-Granting Server
- Service (e.g., NFS server; also technically a /client/)
* Kerberos Authentication, Cont.
1. C → AS: =C_name=
2. AS → C: =encrypt(TGS_session_key, C_key)=
3. AS → C: =TGT = encrypt(C_name.TGS_session_key.…, C_key)=
4. C → TGS: =TGT.S_name=
5. C → TGS: =encrypt(C_name.…, TGS_session_key)=
6. TGS → C: =encrypt(C_name.S_session_key.…, S_key)=
7. TGS → C: =encrypt(S_session_key, TGS_session_key)=
8. C → S: =encrypt(C_name.S_session_key.…, S_key)=
9. C → S: =encrypt(C_name.timestamp, S_session_key)=
10. S → C: =encrypt(C_name.incr(timestamp), S_session_key)=
* NFS Security
- sys
- dh
- krb5
- krb5i
- krb5p
|