View | Details | Raw Unified | Return to bug 225451 | Differences between
and this patch

Collapse All | Expand All

(-)b/gss-serv-krb5.c (-1 / +153 lines)
Lines 32-38 Link Here
32
#include <sys/types.h>
32
#include <sys/types.h>
33
33
34
#include <stdarg.h>
34
#include <stdarg.h>
35
#include <stdio.h>
35
#include <string.h>
36
#include <string.h>
37
#include <unistd.h>
36
38
37
#include "xmalloc.h"
39
#include "xmalloc.h"
38
#include "key.h"
40
#include "key.h"
Lines 40-45 Link Here
40
#include "buffer.h"
42
#include "buffer.h"
41
#include "ssh-gss.h"
43
#include "ssh-gss.h"
42
44
45
extern Authctxt *the_authctxt;
43
extern ServerOptions options;
46
extern ServerOptions options;
44
47
45
#ifdef HEIMDAL
48
#ifdef HEIMDAL
Lines 55-60 extern ServerOptions options; Link Here
55
# include <gssapi/gssapi_krb5.h>
59
# include <gssapi/gssapi_krb5.h>
56
#endif
60
#endif
57
61
62
/* all commands are allowed by default */
63
char **k5users_allowed_cmds = NULL;
64
65
static int ssh_gssapi_k5login_exists();
66
static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *,
67
    int);
68
58
static krb5_context krb_context = NULL;
69
static krb5_context krb_context = NULL;
59
70
60
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
71
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
Lines 87-92 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) Link Here
87
	krb5_principal princ;
98
	krb5_principal princ;
88
	int retval;
99
	int retval;
89
	const char *errmsg;
100
	const char *errmsg;
101
	int k5login_exists;
90
102
91
	if (ssh_gssapi_krb5_init() == 0)
103
	if (ssh_gssapi_krb5_init() == 0)
92
		return 0;
104
		return 0;
Lines 98-107 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) Link Here
98
		krb5_free_error_message(krb_context, errmsg);
110
		krb5_free_error_message(krb_context, errmsg);
99
		return 0;
111
		return 0;
100
	}
112
	}
101
	if (krb5_kuserok(krb_context, princ, name)) {
113
	/* krb5_kuserok() returns 1 if .k5login DNE and this is self-login.
114
	 * We have to make sure to check .k5users in that case. */
115
	k5login_exists = ssh_gssapi_k5login_exists();
116
	/* NOTE: .k5login and .k5users must opened as root, not the user,
117
	 * because if they are on a krb5-protected filesystem, user credentials
118
	 * to access these files aren't available yet. */
119
	if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
102
		retval = 1;
120
		retval = 1;
103
		logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
121
		logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
104
		    name, (char *)client->displayname.value);
122
		    name, (char *)client->displayname.value);
123
	} else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value,
124
		name, k5login_exists)) {
125
		retval = 1;
126
		logit("Authorized to %s, krb5 principal %s "
127
		    "(ssh_gssapi_krb5_cmdok)",
128
		    name, (char *)client->displayname.value);
105
	} else
129
	} else
106
		retval = 0;
130
		retval = 0;
107
131
Lines 109-114 ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) Link Here
109
	return retval;
133
	return retval;
110
}
134
}
111
135
136
/* Test for existence of .k5login.
137
 * We need this as part of our .k5users check, because krb5_kuserok()
138
 * returns success if .k5login DNE and user is logging in as himself.
139
 * With .k5login absent and .k5users present, we don't want absence
140
 * of .k5login to authorize self-login.  (absence of both is required)
141
 * Returns 1 if .k5login is available, 0 otherwise.
142
 */
143
static int
144
ssh_gssapi_k5login_exists()
145
{
146
	char file[MAXPATHLEN];
147
	struct passwd *pw = the_authctxt->pw;
148
149
	snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir);
150
	return access(file, F_OK) == 0;
151
}
152
153
/* check .k5users for login or command authorization
154
 * Returns 1 if principal is authorized, 0 otherwise.
155
 * If principal is authorized, (global) k5users_allowed_cmds may be populated.
156
 */
157
static int
158
ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name,
159
    const char *luser, int k5login_exists)
160
{
161
	FILE *fp;
162
	char file[MAXPATHLEN];
163
	char line[BUFSIZ];
164
	char kuser[65]; /* match krb5_kuserok() */
165
	struct stat st;
166
	struct passwd *pw = the_authctxt->pw;
167
	int found_principal = 0;
168
	int ncommands = 0, allcommands = 0;
169
	u_long linenum;
170
171
	snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
172
	/* If both .k5login and .k5users DNE, self-login is ok. */
173
	if (!k5login_exists && (access(file, F_OK) == -1)) {
174
		return (krb5_aname_to_localname(krb_context, principal,
175
		    sizeof(kuser), kuser) == 0) &&
176
		    (strcmp(kuser, luser) == 0);
177
	}
178
	if ((fp = fopen(file, "r")) == NULL) {
179
		int saved_errno = errno;
180
		/* 2nd access check to ease debugging if file perms are wrong.
181
		 * But we don't want to report this if .k5users simply DNE. */
182
		if (access(file, F_OK) == 0) {
183
			logit("User %s fopen %s failed: %s",
184
			    pw->pw_name, file, strerror(saved_errno));
185
		}
186
		return 0;
187
	}
188
	/* .k5users must be owned either by the user or by root */
189
	if (fstat(fileno(fp), &st) == -1) {
190
		/* can happen, but very wierd error so report it */
191
		logit("User %s fstat %s failed: %s",
192
		    pw->pw_name, file, strerror(errno));
193
		fclose(fp);
194
		return 0;
195
	}
196
	if (!(st.st_uid == pw->pw_uid || st.st_uid == 0)) {
197
		logit("User %s %s is not owned by root or user",
198
		    pw->pw_name, file);
199
		fclose(fp);
200
		return 0;
201
	}
202
	/* .k5users must be a regular file.  krb5_kuserok() doesn't do this
203
	  * check, but we don't want to be deficient if they add a check. */
204
	if (!S_ISREG(st.st_mode)) {
205
		logit("User %s %s is not a regular file", pw->pw_name, file);
206
		fclose(fp);
207
		return 0;
208
	}
209
	/* file exists; initialize k5users_allowed_cmds (to none!) */
210
	k5users_allowed_cmds = xcalloc(++ncommands,
211
	    sizeof(*k5users_allowed_cmds));
212
213
	/* Check each line.  ksu allows unlimited length lines.  We don't. */
214
	while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line),
215
	    &linenum) != -1) {
216
		char *token;
217
218
		/* we parse just like ksu, even though we could do better */
219
		if ((token = strtok(line, " \t\n")) == NULL)
220
			continue;
221
		if (strcmp(name, token) == 0) {
222
			/* we matched on client principal */
223
			found_principal = 1;
224
			if ((token = strtok(NULL, " \t\n")) == NULL) {
225
				/* only shell is allowed */
226
				k5users_allowed_cmds[ncommands-1] =
227
				    xstrdup(pw->pw_shell);
228
				k5users_allowed_cmds =
229
				    xreallocarray(k5users_allowed_cmds, ++ncommands,
230
					sizeof(*k5users_allowed_cmds));
231
				break;
232
			}
233
			/* process the allowed commands */
234
			while (token) {
235
				if (strcmp(token, "*") == 0) {
236
					allcommands = 1;
237
					break;
238
				}
239
				k5users_allowed_cmds[ncommands-1] =
240
				    xstrdup(token);
241
				k5users_allowed_cmds =
242
				    xreallocarray(k5users_allowed_cmds, ++ncommands,
243
					sizeof(*k5users_allowed_cmds));
244
				token = strtok(NULL, " \t\n");
245
			}
246
		}
247
       }
248
	if (k5users_allowed_cmds) {
249
		/* terminate vector */
250
		k5users_allowed_cmds[ncommands-1] = NULL;
251
		/* if all commands are allowed, free vector */
252
		if (allcommands) {
253
			int i;
254
			for (i = 0; i < ncommands; i++) {
255
				free(k5users_allowed_cmds[i]);
256
			}
257
			free(k5users_allowed_cmds);
258
			k5users_allowed_cmds = NULL;
259
		}
260
	}
261
	fclose(fp);
262
	return found_principal;
263
}
264
 
112
265
113
/* This writes out any forwarded credentials from the structure populated
266
/* This writes out any forwarded credentials from the structure populated
114
 * during userauth. Called after we have setuid to the user */
267
 * during userauth. Called after we have setuid to the user */
(-)b/session.c (+23 lines)
Lines 806-811 do_exec(Session *s, const char *command) Link Here
806
		command = forced_command;
806
		command = forced_command;
807
		forced = "(key-option)";
807
		forced = "(key-option)";
808
	}
808
	}
809
#ifdef GSSAPI
810
#ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */
811
	else if (k5users_allowed_cmds) {
812
		const char *match = command;
813
		int allowed = 0, i = 0;
814
815
		if (!match)
816
			match = s->pw->pw_shell;
817
		while (k5users_allowed_cmds[i]) {
818
			if (strcmp(match, k5users_allowed_cmds[i++]) == 0) {
819
				debug("Allowed command '%.900s'", match);
820
				allowed = 1;
821
				break;
822
			}
823
		}
824
		if (!allowed) {
825
			debug("command '%.900s' not allowed", match);
826
			return 1;
827
		}
828
	}
829
#endif
830
#endif
831
809
	if (forced != NULL) {
832
	if (forced != NULL) {
810
		if (IS_INTERNAL_SFTP(command)) {
833
		if (IS_INTERNAL_SFTP(command)) {
811
			s->is_subsystem = s->is_subsystem ?
834
			s->is_subsystem = s->is_subsystem ?
(-)b/ssh-gss.h (+4 lines)
Lines 49-54 Link Here
49
#  endif /* !HAVE_DECL_GSS_C_NT_... */
49
#  endif /* !HAVE_DECL_GSS_C_NT_... */
50
50
51
# endif /* !HEIMDAL */
51
# endif /* !HEIMDAL */
52
53
/* .k5users support */
54
extern char **k5users_allowed_cmds;
55
52
#endif /* KRB5 */
56
#endif /* KRB5 */
53
57
54
/* draft-ietf-secsh-gsskeyex-06 */
58
/* draft-ietf-secsh-gsskeyex-06 */
(-)b/sshd.8 (+7 lines)
Lines 327-332 Finally, the server and the client enter an authentication dialog. Link Here
327
The client tries to authenticate itself using
327
The client tries to authenticate itself using
328
host-based authentication,
328
host-based authentication,
329
public key authentication,
329
public key authentication,
330
GSSAPI authentication,
330
challenge-response authentication,
331
challenge-response authentication,
331
or password authentication.
332
or password authentication.
332
.Pp
333
.Pp
Lines 800-805 This file is used in exactly the same way as Link Here
800
but allows host-based authentication without permitting login with
801
but allows host-based authentication without permitting login with
801
rlogin/rsh.
802
rlogin/rsh.
802
.Pp
803
.Pp
804
.It Pa ~/.k5login
805
.It Pa ~/.k5users
806
These files enforce GSSAPI/Kerberos authentication access control.
807
Further details are described in
808
.Xr ksu 1 .
809
.Pp
803
.It Pa ~/.ssh/
810
.It Pa ~/.ssh/
804
This directory is the default location for all user-specific configuration
811
This directory is the default location for all user-specific configuration
805
and authentication information.
812
and authentication information.

Return to bug 225451