Greetings,

On Fri, Mar 11, 2022 at 18:55 Jacob Champion <pchamp...@vmware.com> wrote:

> On Mon, 2022-02-28 at 20:28 -0500, Stephen Frost wrote:
> > Will add to the CF for consideration.
>
> GSSAPI newbie here, so caveat lector.


No worries, thanks for your interest!

> diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
> > index efc53f3135..6f820a34f1 100644
> > --- a/src/backend/libpq/auth.c
> > +++ b/src/backend/libpq/auth.c
> > @@ -920,6 +920,7 @@ pg_GSS_recvauth(Port *port)
> >       int                     mtype;
> >       StringInfoData buf;
> >       gss_buffer_desc gbuf;
> > +     gss_cred_id_t proxy;
> >
> >       /*
> >        * Use the configured keytab, if there is one.  Unfortunately,
> Heimdal
> > @@ -949,6 +950,9 @@ pg_GSS_recvauth(Port *port)
> >        */
> >       port->gss->ctx = GSS_C_NO_CONTEXT;
> >
> > +     proxy = NULL;
> > +     port->gss->proxy_creds = false;
> > +
> >       /*
> >        * Loop through GSSAPI message exchange. This exchange can consist
> of
> >        * multiple messages sent in both directions. First message is
> always from
> > @@ -999,7 +1003,7 @@ pg_GSS_recvauth(Port *port)
> >
>        &port->gss->outbuf,
> >
>        &gflags,
> >
>        NULL,
> > -
>        NULL);
> > +
>        &proxy);
> >
> >               /* gbuf no longer used */
> >               pfree(buf.data);
> > @@ -1011,6 +1015,12 @@ pg_GSS_recvauth(Port *port)
> >
> >               CHECK_FOR_INTERRUPTS();
> >
> > +             if (proxy != NULL)
> > +             {
> > +                     pg_store_proxy_credential(proxy);
> > +                     port->gss->proxy_creds = true;
> > +             }
> > +
>
> Some implementation docs [1] imply that a delegated_cred_handle is only
> valid if the ret_flags include GSS_C_DELEG_FLAG. The C-binding RFC [2],
> though, says that we can rely on it being set to GSS_C_NO_CREDENTIAL if
> no handle was sent...
>
> I don't know if there are any implementation differences here, but in
> any case I think it'd be more clear to use the GSS_C_NO_CREDENTIAL
> spelling (instead of NULL) here, if we do decide not to check
> ret_flags.


Hmmm, yeah, that seems like it might be better and is something I’ll take a
look at.

[5] says we have to free the proxy credential with GSS_Release_cred();
> I don't see that happening anywhere, but I may have missed it.


I’m not sure that it’s really necessary or worthwhile to do that at process
end since … the process is about to end. I suppose we could provide a
function that a user could call to ask for it to be released sooner if we
really wanted..?

>       maj_stat = gss_init_sec_context(&min_stat,
> > -
>  GSS_C_NO_CREDENTIAL,
> > +
>  proxy,
> >
>  &conn->gctx,
> >
>  conn->gtarg_nam,
> >
>  GSS_C_NO_OID,
> > -
>  GSS_C_MUTUAL_FLAG,
> > +
>  GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG,
> >                                                                       0,
> >
>  GSS_C_NO_CHANNEL_BINDINGS,
> >
>  (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
> > diff --git a/src/interfaces/libpq/fe-secure-gssapi.c
> b/src/interfaces/libpq/fe-secure-gssapi.c
> > index 6ea52ed866..566c89f52f 100644
> > --- a/src/interfaces/libpq/fe-secure-gssapi.c
> > +++ b/src/interfaces/libpq/fe-secure-gssapi.c
> > @@ -631,7 +631,7 @@ pqsecure_open_gss(PGconn *conn)
> >        */
> >       major = gss_init_sec_context(&minor, conn->gcred, &conn->gctx,
> >
> conn->gtarg_nam, GSS_C_NO_OID,
> > -
> GSS_REQUIRED_FLAGS, 0, 0, &input, NULL,
> > +
> GSS_REQUIRED_FLAGS | GSS_C_DELEG_FLAG, 0, 0, &input, NULL,
>
> It seems like there should be significant security implications to
> allowing delegation across the board. Especially since one postgres_fdw
> might delegate to another server, and then another... Should this be
> opt-in, maybe via a connection parameter?


This is already opt-in- at kinit time a user can decide if they’d like a
proxy-able ticket or not.  I don’t know that we really need to have our own
option for it … tho I’m not really against adding such an option either.

(It also looks like there are some mechanisms for further constraining
> delegation scope, either by administrator policy or otherwise [3, 4].
> Might be a good thing for a v2 of this feature to have.)


Yes, constrained delegation is a pretty neat extension to Kerberos and one
I’d like to look at later as a future enhancement but I don’t think it
needs to be in the initial version.

Similarly, it feels a little strange that the server would allow the
> client to unilaterally force the use of a delegated credential. I think
> that should be opt-in on the server side too, unless there's some
> context I'm missing around why that's safe.


Perhaps you could explain what isn’t safe about accepting a delegated
credential from a client..?  I am not away of a risk to accepting such a
delegated credential.  Even so, I’m not against adding an option… but
exactly how would that option be configured?  Server level?  On the HBA
line?  role level..?

> +     /* Make the proxy credential only available to current process */
> > +     major = gss_store_cred_into(&minor,
> > +             cred,
> > +             GSS_C_INITIATE, /* credential only used for starting libpq
> connection */
> > +             GSS_C_NULL_OID, /* store all */
> > +             true, /* overwrite */
> > +             true, /* make default */
> > +             &ccset,
> > +             &mech,
> > +             &usage);
> > +
> > +
> > +     if (major != GSS_S_COMPLETE)
> > +     {
> > +             pg_GSS_error("gss_store_cred", major, minor);
> > +     }
> > +
> > +     /* quite strange that gss_store_cred doesn't work with
> "KRB5CCNAME=MEMORY:",
> > +      * we have to use gss_store_cred_into instead and set the env for
> later
> > +      * gss_acquire_cred calls. */
> > +     setenv("KRB5CCNAME", GSS_MEMORY_CACHE, 1);
>
> If I'm reading it right, we're resetting the default credential in the
> MEMORY cache, so if you're a libpq client doing your own GSSAPI work,
> I'm guessing you might not be happy with this behavior.


This is just done on the server side and not the client side..?

Also, we're
> globally ignoring whatever ccache was set by an administrator. Can't
> two postgres_fdw connections from the same backend process require
> different settings?


Settings..? Perhaps, but delegated credentials aren’t really settings, so
not really sure what you’re suggesting here.

I notice that gss_store_cred_into() has a companion,
> gss_acquire_cred_from(). Is it possible to use that to pull out our
> delegated credential explicitly by name, instead of stomping on the
> global setup?


Not really sure what is meant here by global setup..?  Feeling like this is
a follow on confusion from maybe mixing server vs client libpq?

Thanks,

Stephen

>

Reply via email to