Thread: BUG #9337: SSPI/GSSAPI with mismatched user names
The following bug has been logged on the website: Bug reference: 9337 Logged by: Brian Crowell Email address: brian@fluggo.com PostgreSQL version: 9.3.3 Operating system: Linux Description: Hello. I posted this to the general discussion group, but I think it's worthwhile to call it a bug, too. I'm working with the Npgsql group on getting integrated security to "just work" in the same way SQL Server's does. I wrote a workaround for one issue, only to find out that I need more workarounds, and I finally realized that this a problem with the way Postgres handles GSSAPI/SSPI logins. You can read my full description here: https://github.com/npgsql/Npgsql/issues/162#issuecomment-35916650 The short version is that Postgres requires two user names when using GSSAPI/SSPI: one from the startup packet, and one from the Kerberos ticket, and if these don't match exactly, the login fails. It's generally impossible to determine the correct user name to send in the startup packet. I think Postgres should either not require or ignore the user name in the startup packet for these two login types.
brian@fluggo.com writes: > The short version is that Postgres requires two user names when using > GSSAPI/SSPI: one from the startup packet, and one from the Kerberos ticket, > and if these don't match exactly, the login fails. It's generally impossible > to determine the correct user name to send in the startup packet. > I think Postgres should either not require or ignore the user name in the > startup packet for these two login types. If we did that, wouldn't it mean that anyone with a working Kerberos login could log in as *any* database user? Even a superuser? I'm prepared to grant that we might need to change the behavior somehow, but it seems like not requiring any connection at all between the Kerberos principal name and the database user name would be entirely unsafe. regards, tom lane
On Mon, Feb 24, 2014 at 12:44 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > If we did that, wouldn't it mean that anyone with a working Kerberos login > could log in as *any* database user? Even a superuser? > > I'm prepared to grant that we might need to change the behavior somehow, > but it seems like not requiring any connection at all between the Kerberos > principal name and the database user name would be entirely unsafe. I don't think I'm suggesting what you're thinking. I'm saying that if the Postgres user name *has* to match the Kerberos principal name anyways, why not just take the Kerberos principal name and save us the trouble of sending a Postgres user name? Right now, I'm seeing log entries like this: 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and authenticated user name (BCrowell@REALM.COM) do not match But the Kerberos ticket is perfectly valid, and matches a Postgres user. In this case, the program attempting to log in is incapable of determining the correct Postgres user name to send (see Npgsql bug for the dirty details), so why not just accept the Kerberos principal name? --Brian
On Mon, Feb 24, 2014 at 12:50 PM, Brian Crowell <brian@fluggo.com> wrote: > 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and > authenticated user name (BCrowell@REALM.COM) do not match > > But the Kerberos ticket is perfectly valid, and matches a Postgres > user. In this case, the program attempting to log in is incapable of > determining the correct Postgres user name to send (see Npgsql bug for > the dirty details), so why not just accept the Kerberos principal > name? Or in other words, I'm trying to log in as the Postgres user "BCrowell@REALM.COM" (which is in the Kerberos ticket), and not as "Brian" (which is in the startup packet, because Npgsql doesn't know what else to do). --Brian
* Brian Crowell (brian@fluggo.com) wrote: > Right now, I'm seeing log entries like this: >=20 > 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and > authenticated user name (BCrowell@REALM.COM) do not match >=20 > But the Kerberos ticket is perfectly valid, and matches a Postgres > user. In this case, the program attempting to log in is incapable of > determining the correct Postgres user name to send (see Npgsql bug for > the dirty details), so why not just accept the Kerberos principal > name? This is what the mapping logic in pg_ident was written to address... Thanks, Stephen
On Mon, Feb 24, 2014 at 7:56 PM, Stephen Frost <sfrost@snowman.net> wrote: > * Brian Crowell (brian@fluggo.com) wrote: > > Right now, I'm seeing log entries like this: > > > > 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and > > authenticated user name (BCrowell@REALM.COM) do not match > > > > But the Kerberos ticket is perfectly valid, and matches a Postgres > > user. In this case, the program attempting to log in is incapable of > > determining the correct Postgres user name to send (see Npgsql bug for > > the dirty details), so why not just accept the Kerberos principal > > name? > > This is what the mapping logic in pg_ident was written to address... > There is also a parameter called include_realm, specifically for Kerberos, which will remove the @REALM.COM part. But I believe it does that by default. Specifically see http://www.postgresql.org/docs/9.3/static/auth-methods.html#GSSAPI-AUTH, which deals with both those. -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
* Brian Crowell (brian@fluggo.com) wrote: > On Mon, Feb 24, 2014 at 12:50 PM, Brian Crowell <brian@fluggo.com> wrote: > > 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and > > authenticated user name (BCrowell@REALM.COM) do not match > > > > But the Kerberos ticket is perfectly valid, and matches a Postgres > > user. In this case, the program attempting to log in is incapable of > > determining the correct Postgres user name to send (see Npgsql bug for > > the dirty details), so why not just accept the Kerberos principal > > name? >=20 > Or in other words, I'm trying to log in as the Postgres user > "BCrowell@REALM.COM" (which is in the Kerberos ticket), and not as > "Brian" (which is in the startup packet, because Npgsql doesn't know > what else to do). To PG, you're trying to log in as PG user 'Brian' and there's no mapping which allows the kerb princ "BCrowell@REALM.COM" to log in as that user. Also, is the PG user really "BCrowell@REALM.COM", or is it actually 'bcrowell', in which case you need a mapping for that (unless you tell PG to just strip the realm off, but I generally recommend against such since you can end up with cross-realm issues if you ever define a trust relationship to another realm with different users who might have the same princs as your local users). Thanks, Stephen
Brian Crowell <brian@fluggo.com> writes: > Right now, I'm seeing log entries like this: > 2014-02-24 11:30:40 CST LOG: provided user name (Brian) and > authenticated user name (BCrowell@REALM.COM) do not match > But the Kerberos ticket is perfectly valid, and matches a Postgres > user. In this case, the program attempting to log in is incapable of > determining the correct Postgres user name to send (see Npgsql bug for > the dirty details), so why not just accept the Kerberos principal > name? Why exactly doesn't Npgsql know what the Kerberos principal name is? How did it obtain the ticket without knowing that? regards, tom lane
On Mon, Feb 24, 2014 at 1:10 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Why exactly doesn't Npgsql know what the Kerberos principal name is? > How did it obtain the ticket without knowing that? Windows obtained the ticket, not Npgsql. It's attached to my logon token without Npgsql's help. If I'm on the domain, I _might_ have access to that information through a call to LsaGetLogonSessionData or similar. If I'm not on the domain, I definitely don't. Npgsql is just asking Windows to do GSSAPI auth on its behalf, so it never really touches that info. --Brian
Brian Crowell <brian@fluggo.com> writes: > On Mon, Feb 24, 2014 at 1:10 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Why exactly doesn't Npgsql know what the Kerberos principal name is? >> How did it obtain the ticket without knowing that? > Windows obtained the ticket, not Npgsql. It's attached to my logon > token without Npgsql's help. If I'm on the domain, I _might_ have > access to that information through a call to LsaGetLogonSessionData or > similar. If I'm not on the domain, I definitely don't. Hm, so how did Windows know what ticket to get? *Somewhere* there's got to be a mapping from "Brian" to "BCrowell". It might not be readily accessible to you though :-( As noted upthread, we can't really do what you're suggesting without a fundamental rearchitecting of our authentication scheme, which aside from being a lot of work would probably break at least as many use-cases as it improves. To take one example, it's not unreasonable at all that people might want database superusers to have to use a different auth method from ordinary users --- so just taking the username out of the auth method selection process doesn't sound workable. It's unfortunate that this doesn't fit well with the architecture you find yourself dealing with on the client side, but I doubt we can do anything to help you. regards, tom lane
* Brian Crowell (brian@fluggo.com) wrote: > On Mon, Feb 24, 2014 at 1:10 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Why exactly doesn't Npgsql know what the Kerberos principal name is? > > How did it obtain the ticket without knowing that? >=20 > Windows obtained the ticket, not Npgsql. It's attached to my logon > token without Npgsql's help. If I'm on the domain, I _might_ have > access to that information through a call to LsaGetLogonSessionData or > similar. If I'm not on the domain, I definitely don't. >=20 > Npgsql is just asking Windows to do GSSAPI auth on its behalf, so it > never really touches that info. I seem to recall that, at one point, we actually we doing this automatically in libpq- that is, grabbing the Kerberos princ and then using it to auth. That was too constrained though, as we wanted to be able to have users with names other than their princs, but perhaps we should have just made it optional instead, perhaps using an environment variable. Would that work for you and the general users? I'm on the fence about making that the default again since it's possible we would break things for existing users... Thanks, Stephen
On Mon, Feb 24, 2014 at 1:01 PM, Stephen Frost <sfrost@snowman.net> wrote: > To PG, you're trying to log in as PG user 'Brian' and there's no mapping > which allows the kerb princ "BCrowell@REALM.COM" to log in as that user. Yes, that's the problem. There will not be a mapping. > Also, is the PG user really "BCrowell@REALM.COM", or is it actually > 'bcrowell', in which case you need a mapping for that (unless you tell > PG to just strip the realm off, but I generally recommend against such > since you can end up with cross-realm issues if you ever define a trust > relationship to another realm with different users who might have the > same princs as your local users). The PG user is "BCrowell@REALM.COM". include_realm is on because we have a forest, and I don't want any crossed wires between domains. Really, this is all what I want to happen, and everything about it works. The only problem is that PG wants a user name that, in a few cases, I just don't have. I'm starting to see that this appears very differently to Postgres people. I'm coming here from SQL Server, where in our company we've now got it set up that each user's SQL Server login _is_ their domain login. Not just named the same--SQL Server understands the domain, and each user is coming in as their Windows identity. However, to Postgres, Kerberos is not about identities at all, it's just a fancy password mechanism. Really you just want to know a Postgres user, and it's never been a problem for users to specify that. I guess what I'm asking is if Kerberos can be used to specify my Postgres username as well. --Brian
On Mon, Feb 24, 2014 at 1:25 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Hm, so how did Windows know what ticket to get? *Somewhere* there's > got to be a mapping from "Brian" to "BCrowell". It might not be > readily accessible to you though :-( Yes. These are tied together on the user's login token, but I can't get to the tied information. It can even be specified before my program starts (via runas /netonly). > As noted upthread, we can't really do what you're suggesting without > a fundamental rearchitecting of our authentication scheme, which aside > from being a lot of work would probably break at least as many use-cases > as it improves. To take one example, it's not unreasonable at all that > people might want database superusers to have to use a different auth > method from ordinary users --- so just taking the username out of the > auth method selection process doesn't sound workable. Well rats. I can see that would require a change at the protocol level. You'd need to accept a ticket or password from me without knowing beforehand if that matches the auth method specified for that user. > It's unfortunate that this doesn't fit well with the architecture you > find yourself dealing with on the client side, but I doubt we can do > anything to help you. Luckily, I know we can architect a workaround for our organization, but I was trying to get it as clean as I could for future Npgsql users. Thanks for taking the time to talk it over with me anyhow :P --Brian
On Mon, Feb 24, 2014 at 1:35 PM, Brian Crowell <brian@fluggo.com> wrote: > Well rats. I can see that would require a change at the protocol > level. You'd need to accept a ticket or password from me without > knowing beforehand if that matches the auth method specified for that > user. Er, well, one last comment, and I promise I'll leave. You could accept these in the startup packet. --Brian
* Brian Crowell (brian@fluggo.com) wrote: > > Also, is the PG user really "BCrowell@REALM.COM", or is it actually > > 'bcrowell', in which case you need a mapping for that (unless you tell > > PG to just strip the realm off, but I generally recommend against such > > since you can end up with cross-realm issues if you ever define a trust > > relationship to another realm with different users who might have the > > same princs as your local users). >=20 > The PG user is "BCrowell@REALM.COM". include_realm is on because we > have a forest, and I don't want any crossed wires between domains. Ah, makes sense. Again, you could have different usernames in PG if you wanted to keep things simpler, by using pg_ident.conf, but if useing the full princ works for you then that's certainly fine too. > Really, this is all what I want to happen, and everything about it > works. The only problem is that PG wants a user name that, in a few > cases, I just don't have. It really should be possible for you to get it. I'm in flight at the moment and so the interwebs are a bit lagged or I'd go figure out what the right GSSAPI calls are, though I can understand if you'd rather just be able to ask libpq to handle that or maybe pass back what the princ is, so you don't have to deal with the Kerberos calls directly. > I'm starting to see that this appears very differently to Postgres > people. I'm coming here from SQL Server, where in our company we've > now got it set up that each user's SQL Server login _is_ their domain > login. Not just named the same--SQL Server understands the domain, and > each user is coming in as their Windows identity. I'm familiar with SQL Server and how it works there and in a lot of ways it's very similar to what happens in PG, and it has similar options for doing mapping too, as I recall, and if you want to be able to have such a mapping then you have to have both the log-me-in-as username and the Kerberos princ. > However, to Postgres, Kerberos is not about identities at all, it's > just a fancy password mechanism. Really you just want to know a > Postgres user, and it's never been a problem for users to specify > that. I guess what I'm asking is if Kerberos can be used to specify my > Postgres username as well. This is overstating it, imv. The exact same issue happens if, for example, you want to ssh to a server- you have to provide the Unix username that you want to log into the system as, along with the Kerberos ticket. Those can then be different too, by using a .k5login file. If you'd like to complain about something in this regard, it would be that we don't have any way to link PG users in directly with LDAP in the way that AD does, where the group membership is doing through LDAP. That would certainly be accurate but would be quite a bit of work to allow ad we don't get many requests for such capability. Thanks, Stephen
Brian Crowell <brian@fluggo.com> writes: > I'm starting to see that this appears very differently to Postgres > people. I'm coming here from SQL Server, where in our company we've > now got it set up that each user's SQL Server login _is_ their domain > login. Not just named the same--SQL Server understands the domain, and > each user is coming in as their Windows identity. > However, to Postgres, Kerberos is not about identities at all, it's > just a fancy password mechanism. Really you just want to know a > Postgres user, and it's never been a problem for users to specify > that. I guess what I'm asking is if Kerberos can be used to specify my > Postgres username as well. Hm. That's an interesting way of putting it, and you're right --- we don't expect Kerberos to be a source of identity. Which is not the world view Kerberos users have. I wonder whether there would be any value in an option for SSPI (and maybe other auth methods) to say "after authentication is complete, substitute the authenticated principal name for the database user name" (possibly after realm-stripping, case-folding, etc). The usage pattern would be that you'd pass say "use_kerberos_username" as the user name in the startup packet, and that would select a pg_hba.conf entry along the lines of host use_kerberos_username all samenet sspi use_principal=without_realm I'm not sure if that'd solve Npgsql's problem or not, though. As sketched here, the existence of such an auth entry, as well as the spelling of the magic username, would be at the whim of the Postgres installation's DBA. That might not be stable enough for you; I'm betting you're wishing you could hard-wire a dummy name. On the other hand, you weren't complaining about the fact that you can't use Kerberos at all without a suitable pg_hba entry; so maybe some additional constraints on its form would be OK for your use-case. regards, tom lane
On Mon, Feb 24, 2014 at 1:47 PM, Stephen Frost <sfrost@snowman.net> wrote: >> The PG user is "BCrowell@REALM.COM". include_realm is on because we >> have a forest, and I don't want any crossed wires between domains. > > Ah, makes sense. Again, you could have different usernames in PG if you > wanted to keep things simpler, by using pg_ident.conf, but if useing the > full princ works for you then that's certainly fine too. We'd be mapping several dozen users. I'd rather keep things simple :P > It really should be possible for you to get it. I'm in flight at the > moment and so the interwebs are a bit lagged or I'd go figure out what > the right GSSAPI calls are, though I can understand if you'd rather just > be able to ask libpq to handle that or maybe pass back what the princ > is, so you don't have to deal with the Kerberos calls directly. If it is possible, I'd be happy to find out. Note that I'm trying to solve the LOGON32_LOGON_NEW_CREDENTIALS case, which ADO.NET handles just fine. This discussion does not give me much hope: https://groups.google.com/forum/#!topic/microsoft.public.platformsdk.security/5L7ugO0Fc90 > I'm familiar with SQL Server and how it works there and in a lot of ways > it's very similar to what happens in PG, and it has similar options for > doing mapping too, as I recall, and if you want to be able to have such > a mapping then you have to have both the log-me-in-as username and the > Kerberos princ. I'm not sure what you mean. Our connection strings look like this: server=productiondb.realm.com;Integrated Security=SSPI;database=OURDB;Connect Timeout=500;Application Name=w00t Most of our users do not even have SQL Server logins. They get in by group permissions. They're mapped to application data by their SID. > This is overstating it, imv. The exact same issue happens if, for > example, you want to ssh to a server- you have to provide the Unix > username that you want to log into the system as, along with the > Kerberos ticket. Those can then be different too, by using a .k5login > file. If you'd like to complain about something in this regard, it > would be that we don't have any way to link PG users in directly with > LDAP in the way that AD does, where the group membership is doing > through LDAP. That would certainly be accurate but would be quite a bit > of work to allow ad we don't get many requests for such capability. Sorry, I didn't mean for it to sound like a complaint. But yes, I am looking for the Postgres account to be "tied" to the Kerberos account. It doesn't have to be through LDAP; the supplied Kerberos user name is enough. I realize I will still have to set up a mapping for each user, but that's small potatoes. --Brian
On Mon, Feb 24, 2014 at 1:58 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > I wonder whether there would be any value in an option for SSPI (and > maybe other auth methods) to say "after authentication is complete, > substitute the authenticated principal name for the database user > name" (possibly after realm-stripping, case-folding, etc). I humbly resubmit my ticket-in-the-startup-packet suggestion, which I'd hope would be easier, especially since any program not supplying it would fall back to the standard challenge auth mechanism. Like: 1. client -> server startup packet + GSSAPI="here's my ticket" 2. server -> client AuthenticationGSSContinue 3. client -> server password packet 4. server -> client AuthenticationOK But then I don't know what I'm talking about really :P (goes to read the protocol specs) --Brian
On Mon, Feb 24, 2014 at 2:09 PM, Brian Crowell <brian@fluggo.com> wrote: > I humbly resubmit my ticket-in-the-startup-packet suggestion, which > I'd hope would be easier, especially since any program not supplying > it would fall back to the standard challenge auth mechanism. Tell you what. Our company is not to the point of needing anything like this, I was just helping out the Npgsql people. But if we should get to the point that we'd want it, would you accept patches that implemented this sort of shortcut authentication? --Brian
Brian Crowell <brian@fluggo.com> writes: > On Mon, Feb 24, 2014 at 2:09 PM, Brian Crowell <brian@fluggo.com> wrote: >> I humbly resubmit my ticket-in-the-startup-packet suggestion, which >> I'd hope would be easier, especially since any program not supplying >> it would fall back to the standard challenge auth mechanism. > Tell you what. > Our company is not to the point of needing anything like this, I was > just helping out the Npgsql people. But if we should get to the point > that we'd want it, would you accept patches that implemented this sort > of shortcut authentication? As a new feature it would need discussion, and I'm not real sure that it's sensible even in theory. In our model, until you've identified the relevant pg_hba.conf entry you don't know which Kerberos server to talk to to validate the ticket. If it's possible to extract a principal name from a ticket without contacting the server, then that objection fails ... but if that were the case then I suppose you'd not be here looking for a solution. I suppose you could propose some additional configuration settings that would be looked at in advance of the pg_hba.conf lookup to allow extraction of a user name from a supplied ticket. However, that would greatly expand the potential for DOS attacks based on launching bogus startup packets at a postmaster (since the computation needed before rejecting a packet is greatly increased if we have to contact some Kerberos server). Not sure if that objection is fatal or not. regards, tom lane
On Mon, Feb 24, 2014 at 2:56 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > If it's possible to extract a principal name from a ticket without > contacting the server, then that objection fails ... but if that were > the case then I suppose you'd not be here looking for a solution. You've got a point. I do believe the principal name is in the ticket in clear text. I could generate a ticket in anticipation of needing it, extract the name, and send that. I have no idea how to get it, but I'll look into it. I still think this would be useful in the server. If I'm right, and the principal name is in clear text, the server would look at it this way: PSEUDOCODE // (server receives packet without user, but // ticket="my ticket for User@REALM.COM") if(!user_name) { if(ticket) user_name = extract_user_name(ticket) } if(!user_name) return NO_USER_NAME; auth_type = lookup_pg_hba(user_name, database, etc.) if(ticket) { if(auth_type != GSSAPI) return BAD_AUTH; accept_gssapi_packet(ticket); } else { // Do what you would normally do challenge(auth_type); } /PSEUDOCODE Something like that. --Brian
Brian Crowell <brian@fluggo.com> writes: > On Mon, Feb 24, 2014 at 2:56 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> If it's possible to extract a principal name from a ticket without >> contacting the server, then that objection fails ... but if that were >> the case then I suppose you'd not be here looking for a solution. > You've got a point. I do believe the principal name is in the ticket > in clear text. I could generate a ticket in anticipation of needing > it, extract the name, and send that. I have no idea how to get it, but > I'll look into it. > I still think this would be useful in the server. If it's possible to get a name out of a ticket without contacting a realm server, I think what you're talking about would likely be all right. IIUC this approach would also save one round trip to the client to get the ticket once we've decided to use SSPI auth, so that seems like a potential benefit independently of where the username is coming from. I'm not really the house expert on Kerberos-style auth though, so I'd defer to Stephen and some other people on whether there are hidden gotchas. One question worth asking is whether exposing the ticket in the startup packet is problematic if the startup packet is unencrypted and can be snooped by third parties. regards, tom lane
On Mon, Feb 24, 2014 at 3:40 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > If it's possible to get a name out of a ticket without contacting a > realm server, I think what you're talking about would likely be all right. > IIUC this approach would also save one round trip to the client to get > the ticket once we've decided to use SSPI auth, so that seems like a > potential benefit independently of where the username is coming from. Well, for starters, it turns out I'm wrong about the principal. Only the target principal (that of the Postgres server) is in clear text. The source principal (my user name) is in the encrypted part of the request, so that can _only_ be decrypted by the server. However, if I remember right, the server will be in direct possession of the decryption key (IIRC, its own password), and therefore should be able to determine the user name without contacting a third server. This will require more research. > One question worth asking is whether exposing the ticket in the startup > packet is problematic if the startup packet is unencrypted and can be > snooped by third parties. Kerberos takes care of encryption of the ticket. It's really just the same mechanism that's already in place, and with the same encryption, just pushed to Postgres instead of Postgres asking for it. MD5 passwords, on the other hand, have to wait for a salt from the server before they can be sent, so they can't take advantage of this shortcut. --Brian
Brian Crowell <brian@fluggo.com> writes: > On Mon, Feb 24, 2014 at 3:40 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> If it's possible to get a name out of a ticket without contacting a >> realm server, I think what you're talking about would likely be all right. > Well, for starters, it turns out I'm wrong about the principal. Only > the target principal (that of the Postgres server) is in clear text. > The source principal (my user name) is in the encrypted part of the > request, so that can _only_ be decrypted by the server. However, if I > remember right, the server will be in direct possession of the > decryption key (IIRC, its own password), and therefore should be able > to determine the user name without contacting a third server. Um. I spoke imprecisely, I see. The objection to involving a Kerberos server in determining the username is not solely about the cycles involved; it's that it requires identifying a specific Kerberos server to do it. Don't we lose multi-realm support if we have to know the server's password in advance of examining pg_hba.conf? I looked at our docs again and notice that there is no authentication server specification option for the GSSAPI auth method. I guess that that information is buried within the "server key file" or someplace; this goes beyond my knowledge of Kerberos internals I fear. I do see that there isn't any visible specification of a server password either, so even absent the multi-realm issue it's not clear to me that what you propose is practical for code outside the Kerberos libraries. regards, tom lane
All, I'll fill in more on this tomorrow, but the actual service ticket is not going to be useful on the client side, no. There is a ticket cache on the client though, normally, which should have info about the princ the cache is for. That's what klist operates against (on Windows and Linux..). Thanks, Stephen On Monday, February 24, 2014, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Brian Crowell <brian@fluggo.com <javascript:;>> writes: > > On Mon, Feb 24, 2014 at 3:40 PM, Tom Lane <tgl@sss.pgh.pa.us<javascript:;>> > wrote: > >> If it's possible to get a name out of a ticket without contacting a > >> realm server, I think what you're talking about would likely be all > right. > > > Well, for starters, it turns out I'm wrong about the principal. Only > > the target principal (that of the Postgres server) is in clear text. > > The source principal (my user name) is in the encrypted part of the > > request, so that can _only_ be decrypted by the server. However, if I > > remember right, the server will be in direct possession of the > > decryption key (IIRC, its own password), and therefore should be able > > to determine the user name without contacting a third server. > > Um. I spoke imprecisely, I see. The objection to involving a Kerberos > server in determining the username is not solely about the cycles > involved; it's that it requires identifying a specific Kerberos server > to do it. Don't we lose multi-realm support if we have to know the > server's password in advance of examining pg_hba.conf? > > I looked at our docs again and notice that there is no authentication > server specification option for the GSSAPI auth method. I guess that > that information is buried within the "server key file" or someplace; > this goes beyond my knowledge of Kerberos internals I fear. I do see > that there isn't any visible specification of a server password either, > so even absent the multi-realm issue it's not clear to me that what > you propose is practical for code outside the Kerberos libraries. > > regards, tom lane > >
On Mon, Feb 24, 2014 at 6:30 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Um. I spoke imprecisely, I see. The objection to involving a Kerberos > server in determining the username is not solely about the cycles > involved; it's that it requires identifying a specific Kerberos server > to do it. Don't we lose multi-realm support if we have to know the > server's password in advance of examining pg_hba.conf? Not as far as I know. For GSSAPI, the server determines which password to use based on the ticket, which includes the server's principal name, and it looks it up in its own key file (PG's krb_server_keyfile option). (For SSPI, I don't think you can use multiple passwords; if coming from another domain, you'd need Active Directory's assistance to cross the domain correctly.) I also went back and checked, and the server does not have to contact a Kerberos server to authenticate the client or determine its user name. So long as the ticket is encrypted with the correct password (Postgres's password), Postgres can decrypt it and know who the client is and that they're really who they say they are. The picture on this page will help: http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=WordDocuments%2Fintroductiontokerberosauthentication.htm Steps 1 and 2 in that graph are the client authenticating to the KDC. Step 3 is the client telling the KDC it wants to talk to a Postgres server, and it gives Postgres's principal name (such as "POSTGRES/mymachine.realm.com@REALM.COM"). In step 4, the KDC returns a ticket encrypted with Postgres's password. In step 5, Postgres receives the client's ticket, and decrypts it with its own password. If it decrypts properly and checks out, Postgres knows it's legit, because only the KDC should know Postgres's password. Inside will be the user's name. > I looked at our docs again and notice that there is no authentication > server specification option for the GSSAPI auth method. I guess that > that information is buried within the "server key file" or someplace; > this goes beyond my knowledge of Kerberos internals I fear. I do see > that there isn't any visible specification of a server password either, > so even absent the multi-realm issue it's not clear to me that what > you propose is practical for code outside the Kerberos libraries. Yes, the password is in the key file. Since this request has turned out to be a little more complicated than I thought, I'd like to volunteer to research it further and maybe bring it along. It's not part of my job duties right now, so I'll have to come back and visit it later, but so far I don't see anything obvious that would make it unfeasible. The GSSAPI/Kerberos case looks the easiest. SSPI/Negotiate will be harder because that requires passing data back and forth; you couldn't finish in one packet. Interesting problem. --Brian
* Brian Crowell (brian@fluggo.com) wrote: > On Mon, Feb 24, 2014 at 6:30 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Um. I spoke imprecisely, I see. The objection to involving a Kerberos > > server in determining the username is not solely about the cycles > > involved; it's that it requires identifying a specific Kerberos server > > to do it. Don't we lose multi-realm support if we have to know the > > server's password in advance of examining pg_hba.conf? >=20 > Not as far as I know. For GSSAPI, the server determines which password > to use based on the ticket, which includes the server's principal > name, and it looks it up in its own key file (PG's krb_server_keyfile > option). (For SSPI, I don't think you can use multiple passwords; if > coming from another domain, you'd need Active Directory's assistance > to cross the domain correctly.) There's two different things here- multi-realm (as in, a given server can live in multiple, independent, realms) and cross-realm (where the realms trust each other). For cross-realm, the server exists only in one realm and there's only one key for it; users from other realms will get a cross-realm ticket-granting-ticket which can then be used to request a service ticket for the server. For multi-realm, there's multiple keys because the server actually exists in multiple realms. I've not gone back to look at why we added multi-realm support, but I wonder if it might have specifically been to allow a PG server to be in both an AD realm and a Unix realm at the same time, without a cross realm trust between the two (which was problematic until AD got AES support since the only compatible encryption was quite weak). While I've seen discussion about it in the past, my recollection is that we *do* need to decide which entry in the keytab to use to decrypt the ticket first and to figure that out we need to know what we're going to use for krb_realm, krb_srvname and krb_server_hostname. Since those can be set in pg_hba.conf based on the information we're provided in the startup packet, we would be giving up some flexability in this case. =20 On the other hand, Magnus removing the krb5 auth method also removed krb_server_hostname.. I'll ask him about that because we should probably make that available under 'gss' or we may end up leaving some of our users out in the cold when 9.4 comes out and that'd be quite unfortuante. Regarding getting the username from the local credential cache, in the (recently removed) krb5 support, we were extracting the username in libpq from the credentials cache, but only needed it to pass back to the krb5 calls. Still, that is example code of how to do it using the Kerberos libraries, while you can use gss_inquire_cred() with GSSAPI. If we decide to allow an option where we use the 'default cred' in GSSAPI to also determine the PG username we are authenticating to, we'll want to think about how we support that in libpq and psql and consider what to do about the limitations of not being able to specify different krb_server_hostname depending on the user which is attempting to authenicate. > I also went back and checked, and the server does not have to contact > a Kerberos server to authenticate the client or determine its user > name. So long as the ticket is encrypted with the correct password > (Postgres's password), Postgres can decrypt it and know who the client > is and that they're really who they say they are. That's correct- a server in a Kerberos realm never directly communicates (as part of Kerberos) with the KDCs. > Since this request has turned out to be a little more complicated than > I thought, I'd like to volunteer to research it further and maybe > bring it along. It's not part of my job duties right now, so I'll have > to come back and visit it later, but so far I don't see anything > obvious that would make it unfeasible. The GSSAPI/Kerberos case looks > the easiest. SSPI/Negotiate will be harder because that requires > passing data back and forth; you couldn't finish in one packet. No complaints here, just a word of caution that we don't want to break existing setups and should consider what other systems do in this regard to avoid surprising behavior for users who are used to SSH or other Kerberos-enabled systems. Thanks, Stephen
On Tue, Feb 25, 2014 at 11:07 AM, Stephen Frost <sfrost@snowman.net> wrote: > I've not gone back to look at why we added multi-realm support, but I > wonder if it might have specifically been to allow a PG server to be in > both an AD realm and a Unix realm at the same time, without a cross > realm trust between the two (which was problematic until AD got AES > support since the only compatible encryption was quite weak). What a wacky world :P > On the other hand, Magnus removing the krb5 auth method also removed > krb_server_hostname.. I'll ask him about that because we should > probably make that available under 'gss' or we may end up leaving some > of our users out in the cold when 9.4 comes out and that'd be quite > unfortuante. I'd be interested in why the principal needs to be specified ahead of time, since it arrives in the ticket. Is it a limitation of the Kerberos APIs? Or maybe it's to prevent using a different key from the key file? > If we decide to allow an option where we use the 'default cred' in > GSSAPI to also determine the PG username we are authenticating to, we'll > want to think about how we support that in libpq and psql and consider > what to do about the limitations of not being able to specify different > krb_server_hostname depending on the user which is attempting to > authenicate. I figured this would be an optional extension, something you could request in the initial packet. You would explicitly ask for it using some special invocation of psql, like "psql -K" the way ssh does. As such, if there are going to be limitations, you could just choose to authenticate the normal way. > No complaints here, just a word of caution that we don't want to break > existing setups and should consider what other systems do in this regard > to avoid surprising behavior for users who are used to SSH or other > Kerberos-enabled systems. Agreed. I looked around, and I thought I saw setups where you could authenticate using "ssh -K hostname" without having to specify a user. I couldn't find any more details on it, though, so I'd have to research that when the time comes. --Brian
* Brian Crowell (brian@fluggo.com) wrote: > On Tue, Feb 25, 2014 at 11:07 AM, Stephen Frost <sfrost@snowman.net> wrot= e: > > On the other hand, Magnus removing the krb5 auth method also removed > > krb_server_hostname.. I'll ask him about that because we should > > probably make that available under 'gss' or we may end up leaving some > > of our users out in the cold when 9.4 comes out and that'd be quite > > unfortuante. >=20 > I'd be interested in why the principal needs to be specified ahead of > time, since it arrives in the ticket. Is it a limitation of the > Kerberos APIs? Or maybe it's to prevent using a different key from the > key file? Yeah, I'm pretty sure you have to set up the server-side stuff before you can actually pass control to GSSAPI (really, the whole thing is insane because GSSAPI actually wants to control the socket on both ends to do whatever communication it needs to with it, so that's why you set everything up, pass control of the socket to the GSSAPI library on both sides, and then check what answer you get back from it at the end). Note that the princ we're talking about here is the *server-side* princ, not the client-side one. > > If we decide to allow an option where we use the 'default cred' in > > GSSAPI to also determine the PG username we are authenticating to, we'll > > want to think about how we support that in libpq and psql and consider > > what to do about the limitations of not being able to specify different > > krb_server_hostname depending on the user which is attempting to > > authenicate. >=20 > I figured this would be an optional extension, something you could > request in the initial packet. You would explicitly ask for it using > some special invocation of psql, like "psql -K" the way ssh does. As > such, if there are going to be limitations, you could just choose to > authenticate the normal way. That sounds reasonable to me. Thanks! Stephen