[31788] in Kerberos
Re: Kerberos tickets, SSH public key auth, AFS tokens
daemon@ATHENA.MIT.EDU (Douglas E. Engert)
Thu Dec 17 10:48:06 2009
Message-ID: <4B2A5288.2080705@anl.gov>
Date: Thu, 17 Dec 2009 09:47:20 -0600
From: "Douglas E. Engert" <deengert@anl.gov>
MIME-Version: 1.0
To: Jeff Blaine <jblaine@stage-infinity.com>
In-Reply-To: <4B297B85.4000305@stage-infinity.com>
Content-Type: multipart/mixed; boundary="------------060702070100010707020301"
Cc: kerberos@mit.edu
Errors-To: kerberos-bounces@mit.edu
This is a multi-part message in MIME format.
--------------060702070100010707020301
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Jeff Blaine wrote:
> On 12/16/2009 5:39 PM, Douglas E. Engert wrote:
>> Jeff Blaine wrote:
>>> Long ago, we evaluated the facilities within OS-provided
>>> sshd for handling our Kerberos + OpenAFS authentication
>>> needs. That is, things like the Kerberos* settings,
>>> GetAFSToken or whatever it was called, etc.
>>>
>>> We found it to be an unusable mismatched moving target.
>>>
>>> We decided to do everything via PAM, with the exception
>>> of ssh public key auth for those who choose to use it
>>> and not get OpenAFS tokens automatically.
>>>
>>> It works great thanks to pam_krb5 and pam_afs_session
>>> from Russ Alberry.
>>>
>>> Our problem now is, of course, that people are complaining
>>> about the number of times they have to type a password.
>>>
>>> Can some of you hint to me what I should be researching
>>> as a solution to this? Essentially we need a non-interactive
>>> way to get OpenAFS tokens via krb5 creds, and I am pretty
>>> clueless about such things. More specifically, this has
>>> all come about from users complaining about CVS-via-SSH
>>> requiring a password in order to get tokens.
>> ssh could use "GSSAPIDelegateCredentials yes" to forward
>> Krb5 tickets, and the sshd could then use pam_afs_session
>> to get the token, even for CVS.
>>
>> But this won't work with ssh public keys. If its winCVS
>> on Windows you are interested in, it too can support GSSAPI.
>
> Thanks for the reply Doug
>
> Well, public keys aren't a requirement. I probably didn't
> make that clear, as it's a long story, so I apologize.
>
> Ignoring public keys, and after configuring a 'host'
> service principal, then extracting it, this does in fact
> work between two Solaris 10 boxes. Cool.
>
> Now I just need to figure out the pam_afs_session part.
>
> With some sshd-gssapi service lines in /etc/pam.conf,
> I'm stuck here (pam_krb5 is Russ'):
>
> # these first 4 lines seem unnecessary for sshd-gssapi here, no?
> sshd-gssapi auth requisite pam_authtok_get.so.1
> sshd-gssapi auth sufficient pam_krb5RA.so try_first_pass
> forwardable minimum_uid=92 debug
> sshd-gssapi auth required pam_unix_auth.so.1
> sshd-gssapi auth required pam_unix_cred.so.1
> sshd-gssapi auth optional pam_afs_session.so minimum_uid=92 debug
> sshd-gssapi session optional pam_krb5RA.so minimum_uid=92 debug
> sshd-gssapi session optional pam_afs_session.so minimum_uid=92 debug
>
> sshd[20489]: [ID 800047 auth.info] Accepted gssapi-keyex for jblaine
> from 1xx.xx.10.14 port 60103 ssh2
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi):
> pam_sm_open_session: entry (0x0)
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi): no context
> found, creating one
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi):
> pam_sm_open_session: entry (0x0)
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi): no context
> found, creating one
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi): (user
> jblaine) unable to get PAM_KRB5CCNAME, assuming non-Kerberos login
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi):
> pam_sm_open_session: exit (ignore)
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi): (user
> jblaine) unable to get PAM_KRB5CCNAME, assuming non-Kerberos login
> sshd[20489]: [ID 366013 auth.debug] pam_krb5(sshd-gssapi):
> pam_sm_open_session: exit (ignore)
> sshd[20489]: [ID 237248 auth.debug] (pam_afs_session):
> pam_sm_open_session: entry (0x0)
> sshd[20489]: [ID 237248 auth.debug] (pam_afs_session): skipping tokens,
> no Kerberos ticket cache
With Solaris 10 using their sshd and pam_krb5 with Russ's pam_afs_session
Note that only the account and session are used:
# Used by GSS, but ssh has bug about saving creds, so we use session based creds.
sshd-gssapi account requisite pam_roles.so.1
sshd-gssapi account required pam_unix_account.so.1
sshd-gssapi account required /krb5/lib/security/pam_krb5_ccache.so.1 ccache=/tmp/krb5cc_%u_%p
sshd-gssapi session required pam_unix_session.so.1
sshd-gssapi session required /krb5/lib/security/pam_afs_session.so
sshd-gssapi session required /krb5/lib/security/pam_krb5_ccache.so.1 clean
Note the pam_krb5_ccache.so.1 is a local module, that can be used with sshd
to use a session based ticket cache. (But this may not work will with NFSv4 and its
gssd which is expecting the default cache names.)
I have attached the source code for this. I can send you a tar.gz file with configure
and Makefile.in etc. if you are interested.
> ________________________________________________
> Kerberos mailing list Kerberos@mit.edu
> https://mailman.mit.edu/mailman/listinfo/kerberos
>
>
--
Douglas E. Engert <DEEngert@anl.gov>
Argonne National Laboratory
9700 South Cass Avenue
Argonne, Illinois 60439
(630) 252-5444
--------------060702070100010707020301
Content-Type: text/plain;
name="pam_krb5_ccache.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="pam_krb5_ccache.c"
/*
* Pam routine to set KRB5CCNAME to force Solaris to
* use session based caches
*/
#define DEBLOG(A,B) \
if (debug) \
syslog(LOG_NOTICE,"pam_krb5_ccache:%d %s:%s", __LINE__, A, B)
#include <stdio.h>
#include <pam_appl.h>
#include <pam_modules.h>
#include <syslog.h>
#include <pwd.h>
int
do_krb5_ccache_routine(pam_handle_t *pamh, int flags, int argc,
const char **argv);
/***************************************************************/
int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int i;
int ret;
int do_krb5_ccache= 0;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
else if (strcmp(argv[i], "force") == 0) {
do_krb5_ccache = 1;
}
}
#ifdef DEBUG
fprintf(stderr,"pam_sm_authenticate flag=%d\n",flags);
#endif
DEBLOG("pam_sm_authenticate","called");
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
if (do_krb5_ccache) {
ret = do_krb5_ccache_routine(pamh, flags, argc, argv);
if (ret == PAM_SUCCESS) {
ret = PAM_IGNORE; /* we did not really authenticate */
}
} else {
ret = PAM_IGNORE;
}
return ret;
}
/***************************************************************/
int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int i;
int ret;
int do_krb5_ccache = 1; /* default if called do it */
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
}
#ifdef DEBUG
fprintf(stderr,"pam_sm_account flag=%d\n",flags);
#endif
DEBLOG("pam_sm_account","called");
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
if (do_krb5_ccache) {
ret = do_krb5_ccache_routine(pamh, flags, argc, argv);
if (ret == PAM_SUCCESS) {
ret = PAM_IGNORE; /* we did not really authenticate */
}
} else {
ret = PAM_IGNORE;
}
return ret;
}
/********************************************************/
int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int ret;
int i;
int do_krb5_ccache = 1; /* default to doing the cache stuff */
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
else if (strcmp(argv[i], "force" ) == 0) {
do_krb5_ccache = 0; /* authenticate would have done this */
}
}
DEBLOG("pam_sm_setcred", "called");
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
if (do_krb5_ccache) {
ret = do_krb5_ccache_routine(pamh, flags, argc, argv);
} else {
ret = PAM_SUCCESS;
}
return ret;
}
/********************************************************/
int
pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int i;
int ret;
int do_krb5_ccache = 0;
#ifdef DEBUG
fprintf(stderr,"pam_sm_open_session flag=%d\n",flags);
#endif
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
if (strcmp(argv[i], "force") == 0) {
do_krb5_ccache = 1;
}
}
DEBLOG("pam_sm_open_session", "called");
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
if (do_krb5_ccache) {
ret = do_krb5_ccache_routine(pamh, flags, argc, argv);
} else {
ret = PAM_SUCCESS;
}
return ret;
}
/********************************************************/
int
pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int ret;
int i;
int clean = 0;
char * cache_name = NULL;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
else if (strcmp(argv[i], "clean") == 0) {
clean = 1;
}
}
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
if (clean) {
if ((cache_name = getenv("KRB5CCNAME"))
|| (cache_name = pam_getenv(pamh,"KRB5CCNAME"))) {
if (!strncmp(cache_name, "FILE:", 5)) {
cache_name = cache_name + 5;
}
remove(cache_name);
DEBLOG("remvoing ccache" ,cache_name);
}
}
DEBLOG("pam_sm_close_session", "called");
return PAM_SUCCESS;
}
/********************************************************/
int
do_krb5_ccache_routine(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int debug = 0;
int set_pag = 1;
int i;
int ret;
char * username = NULL;
char ** env;
char * pgm_name = NULL;
struct passwd *pw = NULL;
char *p;
char *q;
char *cache_name = NULL;
char cache_name_buf[1024];
char cache_name_env_buf[2048];
char *hpenv_path = "PATH=/krb5/sbin:/usr/bin:/bin";
char *hpenv[] = {0,0,0};
#ifdef DEBUG
fprintf(stderr,"do_krb5_ccache_routine flag=%d\n",flags);
#endif
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0) {
debug++;
}
else if (strncmp(argv[i], "ccache=", 7) == 0) {
cache_name = &argv[i][7]; /* save for later */
}
}
DEBLOG("do_krb5_ccache_routine", "called");
#if 0
if (!(flags & PAM_ESTABLISH_CRED)) {
ret = PAM_SUCCESS;
DEBLOG("do_krb5_ccache_routine", "no PAM_ESTABLISH_CRED");
goto err;
}
#endif
if (pam_get_item(pamh, PAM_USER, (void **) &username)) {
ret = PAM_SERVICE_ERR;
goto err;
}
if (strncmp(username,"root",4) == 0) {
ret = PAM_IGNORE; /* no tokens for root */
DEBLOG("do_krb5_ccache_routine ignoring ",username);
goto err;
}
DEBLOG("do_krb5_ccache_routine user", username);
if (!(pw = getpwnam(username))) {
ret = PAM_IGNORE;
DEBLOG("do_krb5_ccache_routine" , "user not known");
goto err;
}
/* HP does not have the pam_env routines */
/* will look for ccache as set in krb5 pam routines */
/* Get the cache name */
if (!cache_name) {
cache_name = "FILE:/tmp/krb5cc_%u";
}
strcpy(cache_name_env_buf,"KRB5CCNAME=");
p = cache_name_env_buf + strlen(cache_name_env_buf);
q = cache_name;
/* convert %u and %p */
while (*q) {
if (*q == '%') {
q++;
if (*q == 'u') {
sprintf(p, "%ld", pw->pw_uid);
p += strlen(p);
} else if (*q == 'n') {
sprintf(p, "%s", username);
p += strlen(p);
} else if (*q == 'p') {
sprintf(p, "%ld", getpid());
p += strlen(p);
} else {
/* Not a special token */
*p++ = '%';
q--;
}
q++;
} else {
*p++ = *q++;
}
}
#ifdef DEBUG
fprintf(stderr,"do_krb5_ccache_routine pid=%d uid=%d euid=%d\n",
getpid(),getuid(),geteuid());
fprintf(stderr,"do_krb5_ccache_routine, pw_dir=%s\n",
pw->pw_dir);
fprintf(stderr,"do_krb5_ccache_routine Kenv=%s\n",
pam_getenv(pamh,"KRB5CCNAME")?
pam_getenv(pamh,"KRB5CCNAME"):"(none)");
#endif
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
DEBLOG("do_krb5_ccache_routine","calling get_krb5_ccache_token");
pam_putenv(pamh, cache_name_env_buf);
putenv(cache_name_env_buf);
if (debug) {
if (pam_getenv(pamh,"KRB5CCNAME"))
DEBLOG("pam_getenv KRB5CCNAME",
pam_getenv(pamh,"KRB5CCNAME"));
if (getenv("KRB5CCNAME"))
DEBLOG("getenv KRB5CCNAME",
getenv("KRB5CCNAME"));
}
ret = PAM_SUCCESS;
err:
return ret;
}
--------------060702070100010707020301
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
________________________________________________
Kerberos mailing list Kerberos@mit.edu
https://mailman.mit.edu/mailman/listinfo/kerberos
--------------060702070100010707020301--