summaryrefslogtreecommitdiff
path: root/backport-openssh-6.6p1-kuserok.patch
blob: 6bab715789900cdb1d1abf350dc30324631d9bd3 (plain)
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
diff -up openssh-7.4p1/auth-krb5.c.kuserok openssh-7.4p1/auth-krb5.c
--- openssh-7.4p1/auth-krb5.c.kuserok	2016-12-23 14:36:07.640465939 +0100
+++ openssh-7.4p1/auth-krb5.c	2016-12-23 14:36:07.644465936 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -56,6 +56,21 @@
 
 extern ServerOptions	 options;
 
+int
+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client,
+                 int k5login_exists)
+{
+	if (options.use_kuserok || !k5login_exists)
+		return krb5_kuserok(krb5_ctx, krb5_user, client);
+	else {
+		char kuser[65];
+
+		if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser))
+			return 0;
+		return strcmp(kuser, client) == 0;
+	}
+}
+
 static int
 krb5_init(void *context)
 {
@@ -160,8 +175,9 @@ auth_krb5_password(Authctxt *authctxt, c
 	if (problem)
 		goto out;
 
-	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
-	    authctxt->pw->pw_name)) {
+	/* Use !options.use_kuserok here to make ssh_krb5_kuserok() not
+	 * depend on the existance of .k5login */
+	if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name, !options.use_kuserok)) {
 		problem = -1;
 		goto out;
 	}
diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c
--- openssh-7.4p1/gss-serv-krb5.c.kuserok	2016-12-23 14:36:07.640465939 +0100
+++ openssh-7.4p1/gss-serv-krb5.c	2016-12-23 14:36:07.644465936 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -67,6 +67,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr
     int);
 
 static krb5_context krb_context = NULL;
+extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *, int);
 
 /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
 
@@ -92,6 +93,103 @@ ssh_gssapi_krb5_init(void)
  * Returns true if the user is OK to log in, otherwise returns 0
  */
 
+/* The purpose of the function is to find out if a Kerberos principal is
+ * allowed to log in as the given local user. This is a general problem with
+ * Kerberized services because by design the Kerberos principals are
+ * completely independent from the local user names. This is one of the
+ * reasons why Kerberos is working well on different operating systems like
+ * Windows and UNIX/Linux. Nevertheless a relationship between a Kerberos
+ * principal and a local user name must be established because otherwise every
+ * access would be granted for every principal with a valid ticket.
+ *
+ * Since it is a general issue libkrb5 provides some functions for
+ * applications to find out about the relationship between the Kerberos
+ * principal and a local user name. They are krb5_kuserok() and
+ * krb5_aname_to_localname().
+ *
+ * krb5_kuserok() can be used to "Determine if a principal is authorized to
+ * log in as a local user" (from the MIT Kerberos documentation of this
+ * function). Which is exactly what we are looking for and should be the
+ * preferred choice. It accepts the Kerberos principal and a local user name
+ * and let libkrb5 or its plugins determine if they relate to each other or
+ * not.
+ *
+ * krb5_aname_to_localname() can use used to "Convert a principal name to a
+ * local name" (from the MIT Kerberos documentation of this function). It
+ * accepts a Kerberos principle and returns a local name and it is up to the
+ * application to do any additional checks. There are two issues using
+ * krb5_aname_to_localname(). First, since POSIX user names are case
+ * sensitive, the calling application in general has no other choice than
+ * doing a case-sensitive string comparison between the name returned by
+ * krb5_aname_to_localname() and the name used at the login prompt. When the
+ * users are provided by a case in-sensitive server, e.g. Active Directory,
+ * this might lead to login failures because the user typing the name at the
+ * login prompt might not be aware of the right case. Another issue might be
+ * caused if there are multiple alias names available for a single user. E.g.
+ * the canonical name of a user is user@group.department.example.com but there
+ * exists a shorter login name, e.g. user@example.com, to safe typing at the
+ * login prompt. Here krb5_aname_to_localname() can only return the canonical
+ * name, but if the short alias is used at the login prompt authentication
+ * will fail as well. All this can be avoided by using krb5_kuserok() and
+ * configuring krb5.conf or using a suitable plugin to meet the needs of the
+ * given environment.
+ *
+ * The Fedora and RHEL version of openssh contain two patches which modify the
+ * access control behavior:
+ *  - openssh-6.6p1-kuserok.patch
+ *  - openssh-6.6p1-force_krb.patch
+ *
+ * openssh-6.6p1-kuserok.patch adds a new option KerberosUseKuserok for
+ * sshd_config which controls if krb5_kuserok() is used to check if the
+ * principle is authorized or if krb5_aname_to_localname() should be used.
+ * The reason to add this patch was that krb5_kuserok() by default checks if
+ * a .k5login file exits in the users home-directory. With this the user can
+ * give access to his account for any given principal which might be
+ * in violation with company policies and it would be useful if this can be
+ * rejected. Nevertheless the patch ignores the fact that krb5_kuserok() does
+ * no only check .k5login but other sources as well and checking .k5login can
+ * be disabled for all applications in krb5.conf as well. With this new
+ * option KerberosUseKuserok set to 'no' (and this is the default for RHEL7
+ * and Fedora 21) openssh can only use krb5_aname_to_localname() with the
+ * restrictions mentioned above.
+ *
+ * openssh-6.6p1-force_krb.patch adds a ksu like behaviour to ssh, i.e. when
+ * using GSSAPI authentication only commands configured in the .k5user can be
+ * executed. Here the wrong assumption that krb5_kuserok() only checks
+ * .k5login is made as well. In contrast ksu checks .k5login directly and
+ * does not use krb5_kuserok() which might be more useful for the given
+ * purpose. Additionally this patch is not synced with
+ * openssh-6.6p1-kuserok.patch.
+ *
+ * The current patch tries to restore the usage of krb5_kuserok() so that e.g.
+ * localauth plugins can be used. It does so by adding a forth parameter to
+ * ssh_krb5_kuserok() which indicates whether .k5login exists or not. If it
+ * does not exists krb5_kuserok() is called even if KerberosUseKuserok is set
+ * to 'no' because the intent of the option is to not check .k5login and if it
+ * does not exists krb5_kuserok() returns a result without checking .k5login.
+ * If .k5login does exists and KerberosUseKuserok is 'no' we fall back to
+ * krb5_aname_to_localname(). This is in my point of view an acceptable
+ * limitation and does not break the current behaviour.
+ *
+ * Additionally with this patch ssh_krb5_kuserok() is called in
+ * ssh_gssapi_krb5_cmdok() instead of only krb5_aname_to_localname() is
+ * neither .k5login nor .k5users exists to allow plugin evaluation via
+ * krb5_kuserok() as well.
+ *
+ * I tried to keep the patch as minimal as possible, nevertheless I see some
+ * areas for improvement which, if they make sense, have to be evaluated
+ * carefully because they might change existing behaviour and cause breaks
+ * during upgrade:
+ * - I wonder if disabling .k5login usage make sense in sshd or if it should
+ *   be better disabled globally in krb5.conf
+ * - if really needed openssh-6.6p1-kuserok.patch should be fixed to really
+ *   only disable checking .k5login and maybe .k5users
+ * - the ksu behaviour should be configurable and maybe check the .k5login and
+ *   .k5users files directly like ksu itself does
+ * - to make krb5_aname_to_localname() more useful an option for sshd to use
+ *   the canonical name (the one returned by getpwnam()) instead of the name
+ *   given at the login prompt might be useful */
+
 static int
 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
 {
@@ -116,7 +214,8 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
 	/* NOTE: .k5login and .k5users must opened as root, not the user,
 	 * because if they are on a krb5-protected filesystem, user credentials
 	 * to access these files aren't available yet. */
-	if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
+	if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)
+			&& k5login_exists) {
 		retval = 1;
 		logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
 		    name, (char *)client->displayname.value);
@@ -190,9 +289,8 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
 	snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
 	/* If both .k5login and .k5users DNE, self-login is ok. */
 	if (!k5login_exists && (access(file, F_OK) == -1)) {
-		return (krb5_aname_to_localname(krb_context, principal,
-		    sizeof(kuser), kuser) == 0) &&
-		    (strcmp(kuser, luser) == 0);
+                return ssh_krb5_kuserok(krb_context, principal, luser,
+                                        k5login_exists);
 	}
 	if ((fp = fopen(file, "r")) == NULL) {
 		int saved_errno = errno;
diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.kuserok	2016-12-23 14:36:07.630465944 +0100
+++ openssh-7.4p1/servconf.c	2016-12-23 15:11:52.278133344 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -116,6 +116,7 @@ initialize_server_options(ServerOptions
 	options->gss_strict_acceptor = -1;
 	options->gss_store_rekey = -1;
 	options->gss_kex_algorithms = NULL;
+	options->use_kuserok = -1;
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
	options->permit_empty_passwd = -1;
@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption
 	if (options->gss_kex_algorithms == NULL)
 		options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
 #endif
+	if (options->use_kuserok == -1)
+		options->use_kuserok = 1;
 	if (options->password_authentication == -1)
 		options->password_authentication = 1;
 	if (options->kbd_interactive_authentication == -1)
@@ -399,7 +402,7 @@ typedef enum {
	sPort, sHostKeyFile, sLoginGraceTime,
	sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
-	sKerberosGetAFSToken, sKerberosUniqueCCache,
+	sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok,
 	sPasswordAuthentication,
 	sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
@@ -478,12 +481,14 @@ static struct {
 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
 #endif
 	{ "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
+	{ "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
 #else
 	{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
 	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
 	{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
 	{ "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
+	{ "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
 #endif
 	{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
@@ -1644,6 +1649,10 @@ process_server_config_line(ServerOptions
		}
		break;

+	case sKerberosUseKuserok:
+		intptr = &options->use_kuserok;
+		goto parse_flag;
+
	case sMatch:
		if (cmdline)
			fatal("Match directive not supported as a command-line "
@@ -2016,6 +2025,7 @@ copy_set_server_options(ServerOptions *d
 	M_CP_INTOPT(client_alive_interval);
 	M_CP_INTOPT(ip_qos_interactive);
 	M_CP_INTOPT(ip_qos_bulk);
+	M_CP_INTOPT(use_kuserok);
 	M_CP_INTOPT(rekey_limit);
 	M_CP_INTOPT(rekey_interval);
 	M_CP_INTOPT(log_level);
@@ -2309,6 +2319,7 @@ dump_config(ServerOptions *o)
 	dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
 # endif
 	dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
+	dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
 #endif
 #ifdef GSSAPI
	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h
--- openssh-7.4p1/servconf.h.kuserok	2016-12-23 14:36:07.630465944 +0100
+++ openssh-7.4p1/servconf.h	2016-12-23 14:36:07.645465936 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -118,6 +118,7 @@ typedef struct {
 						 * authenticated with Kerberos. */
 	int     kerberos_unique_ccache;		/* If true, the acquired ticket will
 						 * be stored in per-session ccache */
+	int	use_kuserok;
 	int     gss_authentication;	/* If true, permit GSSAPI authentication */
 	int     gss_keyex;		/* If true, permit GSSAPI key exchange */
 	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.kuserok	2016-12-23 14:36:07.637465940 +0100
+++ openssh-7.4p1/sshd_config.5	2016-12-23 15:14:03.117162222 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -850,6 +850,10 @@ Specifies whether to automatically destr
 .Cm no
 can lead to overwriting previous tickets by subseqent connections to the same
 user account.
+.It Cm KerberosUseKuserok
+Specifies whether to look at .k5login file for user's aliases.
+The default is
+.Cm yes .
 .It Cm KexAlgorithms
 Specifies the available KEX (Key Exchange) algorithms.
 Multiple algorithms must be comma-separated.
@@ -1078,6 +1082,7 @@ Available keywords are
 .Cm IPQoS ,
 .Cm KbdInteractiveAuthentication ,
 .Cm KerberosAuthentication ,
+.Cm KerberosUseKuserok ,
 .Cm LogLevel ,
 .Cm MaxAuthTries ,
 .Cm MaxSessions ,
diff -up openssh-7.4p1/sshd_config.kuserok openssh-7.4p1/sshd_config
--- openssh-7.4p1/sshd_config.kuserok	2016-12-23 14:36:07.631465943 +0100
+++ openssh-7.4p1/sshd_config	2016-12-23 14:36:07.646465935 +0100
Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/backport-openssh-6.6p1-kuserok.patch
@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no
 #KerberosOrLocalPasswd yes
 #KerberosTicketCleanup yes
 #KerberosGetAFSToken no
+#KerberosUseKuserok yes
 
 # GSSAPI options
 #GSSAPIAuthentication no