Index: src/auth.c =================================================================== --- src/auth.c.orig +++ src/auth.c @@ -480,9 +480,13 @@ pam_sm_setcred(pam_handle_t *pamh, int f return pam_sm_open_session(pamh, flags, argc, argv); } if (flags & (PAM_REINITIALIZE_CRED | PAM_REFRESH_CRED)) { - if (_pam_krb5_sly_looks_unsafe() == 0) { + int unsave = _pam_krb5_sly_looks_unsafe(); + + /* unsave == 2 or 3 can be fixed inside of + _pam_krb5_sly_maybe_refresh */ + if (unsave == 0 || unsave == 2 || unsave == 3) { return _pam_krb5_sly_maybe_refresh(pamh, flags, - argc, argv); + argc, argv); } else { return PAM_IGNORE; } Index: src/sly.c =================================================================== --- src/sly.c.orig +++ src/sly.c @@ -148,6 +148,21 @@ _pam_krb5_sly_looks_unsafe(void) return 0; } +/* restore dropped privileges */ +int +_restore_privs(uid_t save_euid, gid_t save_egid) +{ + int retuid = 0, retgid = 0; + + retuid = setresuid(getuid(), save_euid, getuid()); + retgid = setresgid(getgid(), save_egid, getgid()); + + /* debug("restore privileges: UID = %u, EUID = %u\n", getuid(), geteuid()); */ + /* debug("restore privileges: GID = %u, EGID = %u\n", getgid(), getegid()); */ + + return (retuid == -1 || retgid == -1)?-1:0; +} + int _pam_krb5_sly_maybe_refresh(pam_handle_t *pamh, int flags, int argc, PAM_KRB5_MAYBE_CONST char **argv) @@ -163,6 +178,23 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t gid_t gid; char *v5ccname, *v5filename, *v4tktfile; + uid_t save_euid = geteuid(); + gid_t save_egid = getegid(); + + + if(_pam_krb5_sly_looks_unsafe() == 2 || _pam_krb5_sly_looks_unsafe() == 3) + { + /* debug("current privileges: UID = %u, EUID = %u\n", getuid(), geteuid()); */ + /* debug("current privileges: GID = %u, EGID = %u\n", getgid(), getegid()); *( + + /* drop privileges temporarily; restore them on every return from this function */ + setresuid(getuid(), getuid(), geteuid()); + setresgid(getgid(), getgid(), getegid()); + + /* debug("drop privileges temporarily: UID = %u, EUID = %u\n", getuid(), geteuid()); */ + /* debug("drop privileges temporarily: GID = %u, EGID = %u\n", getgid(), getegid()); */ + } + /* Inexpensive checks. */ switch (_pam_krb5_sly_looks_unsafe()) { case 0: @@ -170,18 +202,22 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t break; case 1: warn("won't refresh credentials while running under sudo"); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; break; case 2: warn("won't refresh credentials while running setuid"); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; break; case 3: warn("won't refresh credentials while running setgid"); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; break; default: warn("not safe to refresh credentials"); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; break; } @@ -189,6 +225,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t /* Initialize Kerberos. */ if (_pam_krb5_init_ctx(&ctx, argc, argv) != 0) { warn("error initializing Kerberos"); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; } @@ -197,6 +234,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t if (i != PAM_SUCCESS) { warn("could not identify user name"); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return i; } @@ -205,6 +243,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t if (options == NULL) { warn("error parsing options (shouldn't happen)"); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; } if (options->debug) { @@ -226,6 +265,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t } _pam_krb5_options_free(pamh, ctx, options); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return retval; } @@ -238,6 +278,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t _pam_krb5_user_info_free(ctx, userinfo); _pam_krb5_options_free(pamh, ctx, options); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return PAM_IGNORE; } @@ -249,6 +290,7 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t _pam_krb5_user_info_free(ctx, userinfo); _pam_krb5_options_free(pamh, ctx, options); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return PAM_SERVICE_ERR; } @@ -360,5 +402,6 @@ _pam_krb5_sly_maybe_refresh(pam_handle_t _pam_krb5_options_free(pamh, ctx, options); krb5_free_context(ctx); + _restore_privs(save_euid, save_egid); return retval; }