Bugzilla – Attachment 2044 Details for
Bug 1867
add support for ~/.kusers ala ksu(1)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
kusers patch
GSSAPI-08-openssh-5.8p1-kusers.patch (text/plain), 9.42 KB, created by
Frank Cusack
on 2011-05-11 06:52:09 AEST
(
hide
)
Description:
kusers patch
Filename:
MIME Type:
Creator:
Frank Cusack
Created:
2011-05-11 06:52:09 AEST
Size:
9.42 KB
patch
obsolete
># This patch adds ksu(1) .k5users support. It allows command restrictions ># for remote users, similar to the command= restrictions in authorized_keys ># files. The difference is that command= are forced commands whereas ># .k5users are allowed commands. With authorized_keys, when a user logs in ># the forced command is run, no matter what. With .k5users, the user has ># to include an allowed command as part of their ssh command line. We don't ># want to force the command like authorized_keys does, because a) we want ># to maintain ksu(1) semantics and b) with multiple commands how would we ># choose one to force? >diff -uNrp openssh-5.8p1.orig/gss-serv-krb5.c openssh-5.8p1/gss-serv-krb5.c >--- openssh-5.8p1.orig/gss-serv-krb5.c 2011-02-10 15:17:54.000000000 -0800 >+++ openssh-5.8p1/gss-serv-krb5.c 2011-02-10 15:19:22.000000000 -0800 >@@ -32,7 +32,9 @@ > #include <sys/types.h> > > #include <stdarg.h> >+#include <stdio.h> > #include <string.h> >+#include <unistd.h> > > #include "xmalloc.h" > #include "key.h" >@@ -40,12 +42,11 @@ > #include "auth.h" > #include "log.h" > #include "servconf.h" >+#include "misc.h" > > #include "buffer.h" > #include "ssh-gss.h" > >-extern ServerOptions options; >- > #ifdef HEIMDAL > # include <krb5.h> > #else >@@ -56,6 +57,16 @@ extern ServerOptions options; > # endif > #endif > >+extern Authctxt *the_authctxt; >+extern ServerOptions options; >+ >+/* all commands are allowed by default */ >+char **k5users_allowed_cmds = NULL; >+ >+static int ssh_gssapi_k5login_exists(); >+static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *, >+ int); >+ > static krb5_context krb_context = NULL; > > /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ >@@ -83,10 +94,11 @@ ssh_gssapi_krb5_init(void) > */ > > static int >-ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) >+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *luser) > { > krb5_principal princ; > int retval; >+ int k5login_exists; > > if (ssh_gssapi_krb5_init() == 0) > return 0; >@@ -97,10 +109,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client > krb5_get_err_text(krb_context, retval)); > return 0; > } >- if (krb5_kuserok(krb_context, princ, name)) { >+ /* krb5_kuserok() returns 1 if .k5login DNE and this is self-login. >+ * We have to make sure to check .k5users in that case. */ >+ k5login_exists = ssh_gssapi_k5login_exists(); >+ /* 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, luser) && k5login_exists) { > retval = 1; > logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", >- name, (char *)client->displayname.value); >+ luser, (char *)client->displayname.value); >+ } else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value, >+ luser, k5login_exists)) { >+ retval = 1; >+ logit("Authorized to %s, krb5 principal %s " >+ "(ssh_gssapi_krb5_cmdok)", >+ luser, (char *)client->displayname.value); > } else > retval = 0; > >@@ -108,6 +132,134 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client > return retval; > } > >+/* Test for existence of .k5login. >+ * We need this as part of our .k5users check, because krb5_kuserok() >+ * returns success if .k5login DNE and user is logging in as himself. >+ * With .k5login absent and .k5users present, we don't want absence >+ * of .k5login to authorize self-login. (absence of both is required) >+ * Returns 1 if .k5login is available, 0 otherwise. >+ */ >+static int >+ssh_gssapi_k5login_exists() >+{ >+ char file[MAXPATHLEN]; >+ struct passwd *pw = the_authctxt->pw; >+ >+ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); >+ return access(file, F_OK) == 0; >+} >+ >+/* check .k5users for login or command authorization >+ * Returns 1 if principal is authorized, 0 otherwise. >+ * If principal is authorized, (global) k5users_allowed_cmds may be populated. >+ */ >+static int >+ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, >+ const char *luser, int k5login_exists) >+{ >+ FILE *fp; >+ char file[MAXPATHLEN]; >+ char line[BUFSIZ]; >+ char kuser[65]; /* match krb5_kuserok() */ >+ struct stat st; >+ struct passwd *pw = the_authctxt->pw; >+ int found_principal = 0; >+ int ncommands = 0, allcommands = 0; >+ u_long linenum; >+ >+ 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); >+ } >+ if ((fp = fopen(file, "r")) == NULL) { >+ int saved_errno = errno; >+ /* 2nd access check to ease debugging if file perms are wrong. >+ * But we don't want to report this if .k5users simply DNE. */ >+ if (access(file, F_OK) == 0) { >+ logit("User %s fopen %s failed: %s", >+ pw->pw_name, file, strerror(saved_errno)); >+ } >+ return 0; >+ } >+ /* .k5users must be owned either by the user or by root */ >+ if (fstat(fileno(fp), &st) == -1) { >+ /* can happen, but very wierd error so report it */ >+ logit("User %s fstat %s failed: %s", >+ pw->pw_name, file, strerror(errno)); >+ fclose(fp); >+ return 0; >+ } >+ if (!(st.st_uid == pw->pw_uid || st.st_uid == 0)) { >+ logit("User %s %s is not owned by root or user", >+ pw->pw_name, file); >+ fclose(fp); >+ return 0; >+ } >+ /* .k5users must be a regular file. krb5_kuserok() doesn't do this >+ * check, but we don't want to be deficient if they add a check. */ >+ if (!S_ISREG(st.st_mode)) { >+ logit("User %s %s is not a regular file", pw->pw_name, file); >+ fclose(fp); >+ return 0; >+ } >+ /* file exists; initialize k5users_allowed_cmds (to none!) */ >+ k5users_allowed_cmds = xcalloc(++ncommands, >+ sizeof(*k5users_allowed_cmds)); >+ >+ /* Check each line. ksu allows unlimited length lines. We don't. */ >+ while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line), >+ &linenum) != -1) { >+ char *token; >+ >+ /* we parse just like ksu, even though we could do better */ >+ token = strtok(line, " \t\n"); >+ if (strcmp(name, token) == 0) { >+ /* we matched on client principal */ >+ found_principal = 1; >+ if ((token = strtok(NULL, " \t\n")) == NULL) { >+ /* only shell is allowed */ >+ k5users_allowed_cmds[ncommands-1] = >+ xstrdup(pw->pw_shell); >+ k5users_allowed_cmds = >+ xrealloc(k5users_allowed_cmds, ++ncommands, >+ sizeof(*k5users_allowed_cmds)); >+ break; >+ } >+ /* process the allowed commands */ >+ while (token) { >+ if (strcmp(token, "*") == 0) { >+ allcommands = 1; >+ break; >+ } >+ k5users_allowed_cmds[ncommands-1] = >+ xstrdup(token); >+ k5users_allowed_cmds = >+ xrealloc(k5users_allowed_cmds, ++ncommands, >+ sizeof(*k5users_allowed_cmds)); >+ token = strtok(NULL, " \t\n"); >+ } >+ } >+ } >+ if (k5users_allowed_cmds) { >+ /* terminate vector */ >+ k5users_allowed_cmds[ncommands-1] = NULL; >+ /* if all commands are allowed, free vector */ >+ if (allcommands) { >+ int i; >+ for (i = 0; i < ncommands; i++) { >+ free(k5users_allowed_cmds[i]); >+ } >+ free(k5users_allowed_cmds); >+ k5users_allowed_cmds = NULL; >+ } >+ } >+ fclose(fp); >+ return found_principal; >+} >+ > > /* This writes out any forwarded credentials from the structure populated > * during userauth. Called after we have setuid to the user */ >diff -uNrp openssh-5.8p1.orig/session.c openssh-5.8p1/session.c >--- openssh-5.8p1.orig/session.c 2010-11-30 17:02:59.000000000 -0800 >+++ openssh-5.8p1/session.c 2011-02-10 15:18:28.000000000 -0800 >@@ -807,6 +807,28 @@ do_exec(Session *s, const char *command) > s->is_subsystem = SUBSYSTEM_EXT; > debug("Forced command (key option) '%.900s'", command); > } >+#ifdef GSSAPI >+#ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */ >+ else if (k5users_allowed_cmds) { >+ const char *match = command; >+ int allowed = 0, i = 0; >+ >+ if (!match) >+ match = s->pw->pw_shell; >+ while (k5users_allowed_cmds[i]) { >+ if (strcmp(match, k5users_allowed_cmds[i++]) == 0) { >+ debug("Allowed command '%.900s'", match); >+ allowed = 1; >+ break; >+ } >+ } >+ if (!allowed) { >+ debug("command '%.900s' not allowed", match); >+ return 1; >+ } >+ } >+#endif >+#endif > > #ifdef SSH_AUDIT_EVENTS > if (command != NULL) >diff -uNrp openssh-5.8p1.orig/ssh-gss.h openssh-5.8p1/ssh-gss.h >--- openssh-5.8p1.orig/ssh-gss.h 2011-02-10 15:17:54.000000000 -0800 >+++ openssh-5.8p1/ssh-gss.h 2011-02-10 15:18:28.000000000 -0800 >@@ -48,6 +48,10 @@ > #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name > #endif /* GSS_C_NT_... */ > #endif /* !HEIMDAL */ >+ >+/* .k5users support */ >+extern char **k5users_allowed_cmds; >+ > #endif /* KRB5 */ > > /* draft-ietf-secsh-gsskeyex-06 */ >diff -uNrp openssh-5.8p1.orig/sshd.8 openssh-5.8p1/sshd.8 >--- openssh-5.8p1.orig/sshd.8 2010-11-04 16:20:14.000000000 -0700 >+++ openssh-5.8p1/sshd.8 2011-02-10 15:18:28.000000000 -0800 >@@ -320,6 +320,7 @@ Finally, the server and the client enter > The client tries to authenticate itself using > host-based authentication, > public key authentication, >+GSSAPI authentication, > challenge-response authentication, > or password authentication. > .Pp >@@ -788,6 +789,12 @@ This file is used in exactly the same wa > but allows host-based authentication without permitting login with > rlogin/rsh. > .Pp >+.It Pa ~/.k5login >+.It Pa ~/.k5users >+These files enforce GSSAPI/Kerberos authentication access control. >+Further details are described in >+.Xr ksu 1 . >+.Pp > .It Pa ~/.ssh/ > This directory is the default location for all user-specific configuration > and authentication information.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1867
: 2044