Lines 67-72
static int ssh_gssapi_krb5_cmdok(krb5_pr
Link Here
|
67 |
int); |
67 |
int); |
68 |
|
68 |
|
69 |
static krb5_context krb_context = NULL; |
69 |
static krb5_context krb_context = NULL; |
|
|
70 |
extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *, int); |
70 |
|
71 |
|
71 |
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ |
72 |
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ |
72 |
|
73 |
|
Lines 92-97
ssh_gssapi_krb5_init(void)
Link Here
|
92 |
* Returns true if the user is OK to log in, otherwise returns 0 |
93 |
* Returns true if the user is OK to log in, otherwise returns 0 |
93 |
*/ |
94 |
*/ |
94 |
|
95 |
|
|
|
96 |
/* The purpose of the function is to find out if a Kerberos principal is |
97 |
* allowed to log in as the given local user. This is a general problem with |
98 |
* Kerberized services because by design the Kerberos principals are |
99 |
* completely independent from the local user names. This is one of the |
100 |
* reasons why Kerberos is working well on different operating systems like |
101 |
* Windows and UNIX/Linux. Nevertheless a relationship between a Kerberos |
102 |
* principal and a local user name must be established because otherwise every |
103 |
* access would be granted for every principal with a valid ticket. |
104 |
* |
105 |
* Since it is a general issue libkrb5 provides some functions for |
106 |
* applications to find out about the relationship between the Kerberos |
107 |
* principal and a local user name. They are krb5_kuserok() and |
108 |
* krb5_aname_to_localname(). |
109 |
* |
110 |
* krb5_kuserok() can be used to "Determine if a principal is authorized to |
111 |
* log in as a local user" (from the MIT Kerberos documentation of this |
112 |
* function). Which is exactly what we are looking for and should be the |
113 |
* preferred choice. It accepts the Kerberos principal and a local user name |
114 |
* and let libkrb5 or its plugins determine if they relate to each other or |
115 |
* not. |
116 |
* |
117 |
* krb5_aname_to_localname() can use used to "Convert a principal name to a |
118 |
* local name" (from the MIT Kerberos documentation of this function). It |
119 |
* accepts a Kerberos principle and returns a local name and it is up to the |
120 |
* application to do any additional checks. There are two issues using |
121 |
* krb5_aname_to_localname(). First, since POSIX user names are case |
122 |
* sensitive, the calling application in general has no other choice than |
123 |
* doing a case-sensitive string comparison between the name returned by |
124 |
* krb5_aname_to_localname() and the name used at the login prompt. When the |
125 |
* users are provided by a case in-sensitive server, e.g. Active Directory, |
126 |
* this might lead to login failures because the user typing the name at the |
127 |
* login prompt might not be aware of the right case. Another issue might be |
128 |
* caused if there are multiple alias names available for a single user. E.g. |
129 |
* the canonical name of a user is user@group.department.example.com but there |
130 |
* exists a shorter login name, e.g. user@example.com, to safe typing at the |
131 |
* login prompt. Here krb5_aname_to_localname() can only return the canonical |
132 |
* name, but if the short alias is used at the login prompt authentication |
133 |
* will fail as well. All this can be avoided by using krb5_kuserok() and |
134 |
* configuring krb5.conf or using a suitable plugin to meet the needs of the |
135 |
* given environment. |
136 |
* |
137 |
* The Fedora and RHEL version of openssh contain two patches which modify the |
138 |
* access control behavior: |
139 |
* - openssh-6.6p1-kuserok.patch |
140 |
* - openssh-6.6p1-force_krb.patch |
141 |
* |
142 |
* openssh-6.6p1-kuserok.patch adds a new option KerberosUseKuserok for |
143 |
* sshd_config which controls if krb5_kuserok() is used to check if the |
144 |
* principle is authorized or if krb5_aname_to_localname() should be used. |
145 |
* The reason to add this patch was that krb5_kuserok() by default checks if |
146 |
* a .k5login file exits in the users home-directory. With this the user can |
147 |
* give access to his account for any given principal which might be |
148 |
* in violation with company policies and it would be useful if this can be |
149 |
* rejected. Nevertheless the patch ignores the fact that krb5_kuserok() does |
150 |
* no only check .k5login but other sources as well and checking .k5login can |
151 |
* be disabled for all applications in krb5.conf as well. With this new |
152 |
* option KerberosUseKuserok set to 'no' (and this is the default for RHEL7 |
153 |
* and Fedora 21) openssh can only use krb5_aname_to_localname() with the |
154 |
* restrictions mentioned above. |
155 |
* |
156 |
* openssh-6.6p1-force_krb.patch adds a ksu like behaviour to ssh, i.e. when |
157 |
* using GSSAPI authentication only commands configured in the .k5user can be |
158 |
* executed. Here the wrong assumption that krb5_kuserok() only checks |
159 |
* .k5login is made as well. In contrast ksu checks .k5login directly and |
160 |
* does not use krb5_kuserok() which might be more useful for the given |
161 |
* purpose. Additionally this patch is not synced with |
162 |
* openssh-6.6p1-kuserok.patch. |
163 |
* |
164 |
* The current patch tries to restore the usage of krb5_kuserok() so that e.g. |
165 |
* localauth plugins can be used. It does so by adding a forth parameter to |
166 |
* ssh_krb5_kuserok() which indicates whether .k5login exists or not. If it |
167 |
* does not exists krb5_kuserok() is called even if KerberosUseKuserok is set |
168 |
* to 'no' because the intent of the option is to not check .k5login and if it |
169 |
* does not exists krb5_kuserok() returns a result without checking .k5login. |
170 |
* If .k5login does exists and KerberosUseKuserok is 'no' we fall back to |
171 |
* krb5_aname_to_localname(). This is in my point of view an acceptable |
172 |
* limitation and does not break the current behaviour. |
173 |
* |
174 |
* Additionally with this patch ssh_krb5_kuserok() is called in |
175 |
* ssh_gssapi_krb5_cmdok() instead of only krb5_aname_to_localname() is |
176 |
* neither .k5login nor .k5users exists to allow plugin evaluation via |
177 |
* krb5_kuserok() as well. |
178 |
* |
179 |
* I tried to keep the patch as minimal as possible, nevertheless I see some |
180 |
* areas for improvement which, if they make sense, have to be evaluated |
181 |
* carefully because they might change existing behaviour and cause breaks |
182 |
* during upgrade: |
183 |
* - I wonder if disabling .k5login usage make sense in sshd or if it should |
184 |
* be better disabled globally in krb5.conf |
185 |
* - if really needed openssh-6.6p1-kuserok.patch should be fixed to really |
186 |
* only disable checking .k5login and maybe .k5users |
187 |
* - the ksu behaviour should be configurable and maybe check the .k5login and |
188 |
* .k5users files directly like ksu itself does |
189 |
* - to make krb5_aname_to_localname() more useful an option for sshd to use |
190 |
* the canonical name (the one returned by getpwnam()) instead of the name |
191 |
* given at the login prompt might be useful */ |
192 |
|
95 |
static int |
193 |
static int |
96 |
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) |
194 |
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) |
97 |
{ |
195 |
{ |
Lines 116-122
ssh_gssapi_krb5_userok(ssh_gssapi_client
Link Here
|
116 |
/* NOTE: .k5login and .k5users must opened as root, not the user, |
214 |
/* NOTE: .k5login and .k5users must opened as root, not the user, |
117 |
* because if they are on a krb5-protected filesystem, user credentials |
215 |
* because if they are on a krb5-protected filesystem, user credentials |
118 |
* to access these files aren't available yet. */ |
216 |
* to access these files aren't available yet. */ |
119 |
if (krb5_kuserok(krb_context, princ, name) && k5login_exists) { |
217 |
if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists) |
|
|
218 |
&& k5login_exists) { |
120 |
retval = 1; |
219 |
retval = 1; |
121 |
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", |
220 |
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", |
122 |
name, (char *)client->displayname.value); |
221 |
name, (char *)client->displayname.value); |
Lines 171-179
ssh_gssapi_krb5_cmdok(krb5_principal pri
Link Here
|
171 |
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); |
270 |
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); |
172 |
/* If both .k5login and .k5users DNE, self-login is ok. */ |
271 |
/* If both .k5login and .k5users DNE, self-login is ok. */ |
173 |
if (!k5login_exists && (access(file, F_OK) == -1)) { |
272 |
if (!k5login_exists && (access(file, F_OK) == -1)) { |
174 |
return (krb5_aname_to_localname(krb_context, principal, |
273 |
return ssh_krb5_kuserok(krb_context, principal, luser, |
175 |
sizeof(kuser), kuser) == 0) && |
274 |
k5login_exists); |
176 |
(strcmp(kuser, luser) == 0); |
|
|
177 |
} |
275 |
} |
178 |
if ((fp = fopen(file, "r")) == NULL) { |
276 |
if ((fp = fopen(file, "r")) == NULL) { |
179 |
int saved_errno = errno; |
277 |
int saved_errno = errno; |