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  <deeng...@anl.gov>
 Argonne National Laboratory
 9700 South Cass Avenue
 Argonne, Illinois  60439
 (630) 252-5444
/*
 * 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;
}
________________________________________________
Kerberos mailing list           Kerberos@mit.edu
https://mailman.mit.edu/mailman/listinfo/kerberos

Reply via email to