diff options
author | Simo Sorce <simo@redhat.com> | 2013-04-19 13:02:36 -0400 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2013-04-22 12:47:20 -0400 |
commit | 302de786930a2c533068f9d8909a817b40f07c32 (patch) | |
tree | de4a5fda75cbae6f3df282d1e2a222033b729cae /utils/gssd/krb5_util.c | |
parent | 85352dd5ffd0d9a451b79fa61d24a518b553d280 (diff) | |
download | nfs-utils-302de786930a2c533068f9d8909a817b40f07c32.tar.gz nfs-utils-302de786930a2c533068f9d8909a817b40f07c32.tar.xz nfs-utils-302de786930a2c533068f9d8909a817b40f07c32.zip |
gssd: Allow GSSAPI to try to acquire credentials first.
GSSAPI can be given a uid number as a special name, and then
gss_acquire_cred() can use the name to try to find credentials for
the user.
Give GSSAPI a chance to do it on its own, then fallback to the classic
method of trolling through the file system to find a credential cache.
This patch uses a little know feature of GSSAPI that permits to acquire
crdentials specifying the user's UID. Normally GSSAPI will simply
perform a getpwuid() call and use the user name to generate a principal name and
then see if it can find a TGT for that principal in the local ccache.
This feature is vital to allow the GSS-Proxy to be able to initiate
crdentials on behalf of rpc.gssd using client keytabs stored in the filsystem.
GSS-Proxy works through an interposer-type plugin (new feature in MIT 1.11)
that allows to intercept all GSSAPI requestes and relay them to a system
daemon via a socket. This daemon (GSS-Proxy) then can perform operations
on behalf of other applications with additional logic.
In the rpc.gssd case the GSS-Proxy daemon allows applications running as
system users to properly access krb5 protected shares by creating a
credential cache on the fly when necessary.
This way all applications that need access to krb5 protected shares do not need
to be taught how to initiate crdentials on their own, nor they need to be
wrapped in additional init scripts like k5start or use wasteful cronjobs to
keep credentials fresh. All is needed is to drop a keytab with the right keys
in a special location on the system and gss-proxy will do the rest.
Signed-off-by: Simo Sorce <simo@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'utils/gssd/krb5_util.c')
-rw-r--r-- | utils/gssd/krb5_util.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index 20b55b3..6275dd8 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -1350,6 +1350,57 @@ gssd_k5_get_default_realm(char **def_realm) krb5_free_context(context); } +static int +gssd_acquire_krb5_cred(gss_name_t name, gss_cred_id_t *gss_cred) +{ + OM_uint32 maj_stat, min_stat; + gss_OID_set_desc desired_mechs = { 1, &krb5oid }; + + maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, + &desired_mechs, GSS_C_INITIATE, + gss_cred, NULL, NULL); + + if (maj_stat != GSS_S_COMPLETE) { + if (get_verbosity() > 0) + pgsserr("gss_acquire_cred", + maj_stat, min_stat, &krb5oid); + return -1; + } + + return 0; +} + +int +gssd_acquire_user_cred(uid_t uid, gss_cred_id_t *gss_cred) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc name_buf; + gss_name_t name; + char buf[11]; + int ret; + + ret = snprintf(buf, 11, "%u", uid); + if (ret < 1 || ret > 10) { + return -1; + } + name_buf.value = buf; + name_buf.length = ret + 1; + + maj_stat = gss_import_name(&min_stat, &name_buf, + GSS_C_NT_STRING_UID_NAME, &name); + if (maj_stat != GSS_S_COMPLETE) { + if (get_verbosity() > 0) + pgsserr("gss_import_name", + maj_stat, min_stat, &krb5oid); + return -1; + } + + ret = gssd_acquire_krb5_cred(name, gss_cred); + + maj_stat = gss_release_name(&min_stat, &name); + return ret; +} + #ifdef HAVE_SET_ALLOWABLE_ENCTYPES /* * this routine obtains a credentials handle via gss_acquire_cred() @@ -1368,28 +1419,18 @@ int limit_krb5_enctypes(struct rpc_gss_sec *sec) { u_int maj_stat, min_stat; - gss_cred_id_t credh; - gss_OID_set_desc desired_mechs; krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4 }; int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); extern int num_krb5_enctypes; extern krb5_enctype *krb5_enctypes; + int err = -1; - /* We only care about getting a krb5 cred */ - desired_mechs.count = 1; - desired_mechs.elements = &krb5oid; - - maj_stat = gss_acquire_cred(&min_stat, NULL, 0, - &desired_mechs, GSS_C_INITIATE, - &credh, NULL, NULL); - - if (maj_stat != GSS_S_COMPLETE) { - if (get_verbosity() > 0) - pgsserr("gss_acquire_cred", - maj_stat, min_stat, &krb5oid); - return -1; + if (sec->cred == GSS_C_NO_CREDENTIAL) { + err = gssd_acquire_krb5_cred(GSS_C_NO_NAME, &sec->cred); + if (err) + return -1; } /* @@ -1397,19 +1438,17 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec) * list of supported enctypes, use local default here. */ if (krb5_enctypes == NULL || limit_to_legacy_enctypes) - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, + maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred, &krb5oid, num_enctypes, enctypes); else - maj_stat = gss_set_allowable_enctypes(&min_stat, credh, + maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred, &krb5oid, num_krb5_enctypes, krb5_enctypes); if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_set_allowable_enctypes", maj_stat, min_stat, &krb5oid); - gss_release_cred(&min_stat, &credh); return -1; } - sec->cred = credh; return 0; } |