Re: [PATCHES] krb_match_realm
On Nov 9, 2007, at 5:24 AM, Magnus Hagander wrote: On Tue, 2007-11-06 at 18:10 -0800, Henry B. Hotz wrote: On Nov 6, 2007, at 6:27 AM, Magnus Hagander wrote: On Fri, Nov 02, 2007 at 11:23:30AM -0700, Henry B. Hotz wrote: I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Yeah. Not many people put spaces inside usernames. I think we can easily get away with not covering that case. *sigh* Yeah, maybe we have to live with it. Yeah, that's kind of where I'm going - it's certainly not perfect, but it's the least bad one. Given this, I'll go ahead with the current version of the patch, and we can consider making better changes at a later time assuming we figure them out. It's still a lot better than what's in there now, and it *will* cover the vast majority of cases. I'll address Stephens comments separately. It's guaranteed to produce a unique, canonicalized name based on the specific mechanism in use. It is suitable for memcmp(). The exported name will re-import. Section 3.10 of rfc 2744 describes all this, and appears to be clearer than the Sun document I pointed you at. Certainly it's more concise. YMMV. Hmm. But it doesn't serve our purpose. Well, it *might* work to do a memcmp() of tolower() of the blobs. Right, but if they're defined as blobs, that's even less safe than we did before. No gss_compare_name() is case sensitive. I think the way to do it is to know what case Microsoft is going to use and pre-map everything to that case (before you do a gss_import_name()). I *think* Microsoft will use upper case for the service name so we will need to change from postgres to POSTGRES as the default name in service principals. I've seen places where they may be using lower case realm names (which makes *NO* sense to me). No. Microsoft will send you whatever case the user put into the login box when he logged into windows. It's case-*preserving*, but case- insensitive. That can't be entirely true. Maybe it's true for Microsoft's RC4 enctype, but it can't be true for the des-cbc-md5 enctype. The protocol runs with some case, and the question is what case it uses when it matters. Haven't protocol-traced it, but our systems use des-cbc-md5. It's the only one I managed to get working with pg server running on Linux and clients running on Windows. And in this case, the case insensitive/ case preserving behavior is a fact. I was thinking that the case of the principal affects the protocol, but actually I guess that's only true for the string-to-key function. That would affect a user's ability to get the initial tgt, but not how service tickets are handled. Given case preservation, that would guarantee the correct case for a non-Windows client (for both Windows and Unix servers), but nowhere else. Kind of blows the SSPI/GSSAPI compatibility that's supposed to exist. I think I may start a discussion of this on an IETF list in case people want to update the GSSAPI standard. I suppose you win. Just do a gss_display_name() and do a case insensitive compare. I can't do any independent verification. *bleah* Can you leave the compare inside gssapi if it's not case insensitive though? I assume in AD you can't create both smith and Smith, but can you create the latter at all? If you do, does AD remember the case for display purposes? Here at JPL usernames are lower case, and I don't think we allow anything special but hyphens in them, so I'm not likely to see a lot of the possible corner cases. You can and it remembers. But it has no effect on what is sent ni the kerberos packets - what's sent there is what the user typed in. Yes, that sucks bad, but that's how it is. Hmmm. See above. It isn't possible to make it irrelevant everywhere, unless you only use RC4. Vista uses AES so it looses that loophole though. Yeah, I
Re: [PATCHES] krb_match_realm
On Tue, 2007-11-06 at 18:10 -0800, Henry B. Hotz wrote: On Nov 6, 2007, at 6:27 AM, Magnus Hagander wrote: On Fri, Nov 02, 2007 at 11:23:30AM -0700, Henry B. Hotz wrote: I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Yeah. Not many people put spaces inside usernames. I think we can easily get away with not covering that case. *sigh* Yeah, maybe we have to live with it. Yeah, that's kind of where I'm going - it's certainly not perfect, but it's the least bad one. Given this, I'll go ahead with the current version of the patch, and we can consider making better changes at a later time assuming we figure them out. It's still a lot better than what's in there now, and it *will* cover the vast majority of cases. I'll address Stephens comments separately. It's guaranteed to produce a unique, canonicalized name based on the specific mechanism in use. It is suitable for memcmp(). The exported name will re-import. Section 3.10 of rfc 2744 describes all this, and appears to be clearer than the Sun document I pointed you at. Certainly it's more concise. YMMV. Hmm. But it doesn't serve our purpose. Well, it *might* work to do a memcmp() of tolower() of the blobs. Right, but if they're defined as blobs, that's even less safe than we did before. No gss_compare_name() is case sensitive. I think the way to do it is to know what case Microsoft is going to use and pre-map everything to that case (before you do a gss_import_name()). I *think* Microsoft will use upper case for the service name so we will need to change from postgres to POSTGRES as the default name in service principals. I've seen places where they may be using lower case realm names (which makes *NO* sense to me). No. Microsoft will send you whatever case the user put into the login box when he logged into windows. It's case-*preserving*, but case- insensitive. That can't be entirely true. Maybe it's true for Microsoft's RC4 enctype, but it can't be true for the des-cbc-md5 enctype. The protocol runs with some case, and the question is what case it uses when it matters. Haven't protocol-traced it, but our systems use des-cbc-md5. It's the only one I managed to get working with pg server running on Linux and clients running on Windows. And in this case, the case insensitive/case preserving behavior is a fact. I assume in AD you can't create both smith and Smith, but can you create the latter at all? If you do, does AD remember the case for display purposes? Here at JPL usernames are lower case, and I don't think we allow anything special but hyphens in them, so I'm not likely to see a lot of the possible corner cases. You can and it remembers. But it has no effect on what is sent ni the kerberos packets - what's sent there is what the user typed in. Yes, that sucks bad, but that's how it is. Hmmm. See above. It isn't possible to make it irrelevant everywhere, unless you only use RC4. Vista uses AES so it looses that loophole though. Yeah, I haven't tried Vista at all. I've only done 2000, XP and 2003. I wonder if case conversion is the right way to create compatibility with GSSAPI though. If the user always comes in with a specific case then shouldn't we instead find a way to make sure the PG user is created with the corresponding case? There are several ways you can test for the existence of a user in a Kerberos service, for example kinit with a garbage password will give different errors. That's why we have krb5_caseninsens_users - to let the user choose it. //Magnus ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [PATCHES] krb_match_realm
On Fri, Nov 02, 2007 at 11:23:30AM -0700, Henry B. Hotz wrote: I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Yeah. Not many people put spaces inside usernames. I think we can easily get away with not covering that case. Is there some other way to actually get the username from gss? I mean, if we *didn't* get it from the startup packet, how would we ever be able to determine what user logged in? gss_export_name(), but what it returns is supposed to be an opaque binary blob. It's guaranteed to produce a unique, canonicalized name based on the specific mechanism in use. It is suitable for memcmp(). The exported name will re-import. Section 3.10 of rfc 2744 describes all this, and appears to be clearer than the Sun document I pointed you at. Certainly it's more concise. YMMV. Hmm. But it doesn't serve our purpose. memcmp() on exported names will only be true if everyone uses the same gss mechanism. (OK, the only one we care about is kerberos.) In contrast it's possible that gss_compare_name() would say that uid=smith,ou=People,dc=example,dc=com is the same as [EMAIL PROTECTED] No, memcmp()ing two separate strings (userid + match realm) with an opaque binary blob certainly won't help us at all. The standard defines two ways to do comparisons for access control. We should use one of them. Anything else is going to be more work and less reliable. What's the other way then? Last I checked there was no way to do case insensitive matching on gss_compare_name() but I could be on the wrong docs? Finding any kind of consistent docs for this stuff isn't exactly easy. Because we *must* have the ability to do case insensitive matching, or it *will* break on Windows. No gss_compare_name() is case sensitive. I think the way to do it is to know what case Microsoft is going to use and pre-map everything to that case (before you do a gss_import_name()). I *think* Microsoft will use upper case for the service name so we will need to change from postgres to POSTGRES as the default name in service principals. I've seen places where they may be using lower case realm names (which makes *NO* sense to me). No. Microsoft will send you whatever case the user put into the login box when he logged into windows. It's case-*preserving*, but case-insensitive. However, AD itself requires uppercase service name, but that's a different thing. Absent an environment where I can actually look at all these things, my only point of reference is mod_auth_kerb, and the issues reported with it. I know an upper case HTTP is needed to interoperate with windows clients. An upper case realm name seems to be OK, as is a lower case server name in the second component. The actual usernames seem to be lower case, but that's not the concern of the mod_auth_kerb developers since the deployer just needs to put in whatever matches. The usernames depend on what the client puts in. It's generally a big problem because a lot of krb-aware applications can't deal with it. I assume in AD you can't create both smith and Smith, but can you create the latter at all? If you do, does AD remember the case for display purposes? Here at JPL usernames are lower case, and I don't think we allow anything special but hyphens in them, so I'm not likely to see a lot of the possible corner cases. You can and it remembers. But it has no effect on what is sent ni the kerberos packets - what's sent there is what the user typed in. Yes, that sucks bad, but that's how it is. I think you can upper case the service name, lower case the server name, upper case the realm name, and lower case the user name. If you can create Smith in AD and the user gets authenticated as [EMAIL PROTECTED]
Re: [PATCHES] krb_match_realm
On Nov 6, 2007, at 6:27 AM, Magnus Hagander wrote: On Fri, Nov 02, 2007 at 11:23:30AM -0700, Henry B. Hotz wrote: I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Yeah. Not many people put spaces inside usernames. I think we can easily get away with not covering that case. *sigh* Yeah, maybe we have to live with it. Is there some other way to actually get the username from gss? I mean, if we *didn't* get it from the startup packet, how would we ever be able to determine what user logged in? gss_export_name(), but what it returns is supposed to be an opaque binary blob. It's guaranteed to produce a unique, canonicalized name based on the specific mechanism in use. It is suitable for memcmp(). The exported name will re-import. Section 3.10 of rfc 2744 describes all this, and appears to be clearer than the Sun document I pointed you at. Certainly it's more concise. YMMV. Hmm. But it doesn't serve our purpose. Well, it *might* work to do a memcmp() of tolower() of the blobs. memcmp() on exported names will only be true if everyone uses the same gss mechanism. (OK, the only one we care about is kerberos.) In contrast it's possible that gss_compare_name() would say that uid=smith,ou=People,dc=example,dc=com is the same as [EMAIL PROTECTED] No, memcmp()ing two separate strings (userid + match realm) with an opaque binary blob certainly won't help us at all. The standard defines two ways to do comparisons for access control. We should use one of them. Anything else is going to be more work and less reliable. What's the other way then? Last I checked there was no way to do case insensitive matching on gss_compare_name() but I could be on the wrong docs? Finding any kind of consistent docs for this stuff isn't exactly easy. Because we *must* have the ability to do case insensitive matching, or it *will* break on Windows. No gss_compare_name() is case sensitive. I think the way to do it is to know what case Microsoft is going to use and pre-map everything to that case (before you do a gss_import_name()). I *think* Microsoft will use upper case for the service name so we will need to change from postgres to POSTGRES as the default name in service principals. I've seen places where they may be using lower case realm names (which makes *NO* sense to me). No. Microsoft will send you whatever case the user put into the login box when he logged into windows. It's case-*preserving*, but case- insensitive. That can't be entirely true. Maybe it's true for Microsoft's RC4 enctype, but it can't be true for the des-cbc-md5 enctype. The protocol runs with some case, and the question is what case it uses when it matters. However, AD itself requires uppercase service name, but that's a different thing. OK. Absent an environment where I can actually look at all these things, my only point of reference is mod_auth_kerb, and the issues reported with it. I know an upper case HTTP is needed to interoperate with windows clients. An upper case realm name seems to be OK, as is a lower case server name in the second component. The actual usernames seem to be lower case, but that's not the concern of the mod_auth_kerb developers since the deployer just needs to put in whatever matches. The usernames depend on what the client puts in. It's generally a big problem because a lot of krb-aware applications can't deal with it. I'd bet that the authenticated username in the service ticket is always a specific case. I'd also bet that it's whatever case the username was created with, e.g. Smith. Without being able to inspect packets myself I'm only guessing though. I assume in AD you can't create both smith and Smith, but can you create the latter at all? If you do, does AD remember the case for display purposes? Here at JPL usernames are lower case, and I
Re: [PATCHES] krb_match_realm
Henry B. Hotz wrote: On Nov 1, 2007, at 1:40 PM, Magnus Hagander wrote: Henry B. Hotz wrote: Thank you very much. This helps, but I'm still evaluating how much. I *can* point at one problem though: you do a strchr(gbuf.value, '@') and then error out if there isn't a Kerberos realm there. In fact that is exactly the default username of at least one of the GSSAPI implementations I've tested if the realm is the same as the local default realm. Eh, so how do we then determine the difference between local realm and no realm given? Well, what I've seen is: no realm given if and only if the default local realm matches the realm for the GSSAPI username. I don't think that's guaranteed. Irrk. Very much irrk. I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Is there some other way to actually get the username from gss? I mean, if we *didn't* get it from the startup packet, how would we ever be able to determine what user logged in? The standard defines two ways to do comparisons for access control. We should use one of them. Anything else is going to be more work and less reliable. What's the other way then? Last I checked there was no way to do case insensitive matching on gss_compare_name() but I could be on the wrong docs? Finding any kind of consistent docs for this stuff isn't exactly easy. Because we *must* have the ability to do case insensitive matching, or it *will* break on Windows. Well, it's not a high priority for me, but there is a GSSAPI mechanism called SPKM which uses X500-syle names (X509 certificate subject names to be precise). If we use gss_name_compare() properly then it should just work. I'm unsure if PostgreSQL in general is prepared to deal with such usernames. You'd certainly have to verify that stuff before anything would just work. //Magnus ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [PATCHES] krb_match_realm
On Nov 1, 2007, at 6:33 AM, Tom Lane wrote: Magnus Hagander [EMAIL PROTECTED] writes: Tom Lane wrote: Also the elog message texts need a bit of copy-editing. Probably ;-) Got any specific hints, so I don't have to go through the iteration twice? The one that caught my eye was SSPI domain (%s) does and configured domain (%s) don't match, regards, tom lane s/does // I assume that's your point? The opinions expressed in this message are mine, not those of Caltech, JPL, NASA, or the US Government. [EMAIL PROTECTED], or [EMAIL PROTECTED] ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [PATCHES] krb_match_realm
On Nov 2, 2007, at 8:38 AM, Magnus Hagander wrote: Henry B. Hotz wrote: On Nov 1, 2007, at 1:40 PM, Magnus Hagander wrote: Henry B. Hotz wrote: Thank you very much. This helps, but I'm still evaluating how much. I *can* point at one problem though: you do a strchr (gbuf.value, '@') and then error out if there isn't a Kerberos realm there. In fact that is exactly the default username of at least one of the GSSAPI implementations I've tested if the realm is the same as the local default realm. Eh, so how do we then determine the difference between local realm and no realm given? Well, what I've seen is: no realm given if and only if the default local realm matches the realm for the GSSAPI username. I don't think that's guaranteed. Irrk. Very much irrk. I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. Ok. I can see that point. However, if you have those characters in your username, you may have other problems as well :-) Yeah. Not many people put spaces inside usernames. Is there some other way to actually get the username from gss? I mean, if we *didn't* get it from the startup packet, how would we ever be able to determine what user logged in? gss_export_name(), but what it returns is supposed to be an opaque binary blob. It's guaranteed to produce a unique, canonicalized name based on the specific mechanism in use. It is suitable for memcmp(). The exported name will re-import. Section 3.10 of rfc 2744 describes all this, and appears to be clearer than the Sun document I pointed you at. Certainly it's more concise. YMMV. memcmp() on exported names will only be true if everyone uses the same gss mechanism. (OK, the only one we care about is kerberos.) In contrast it's possible that gss_compare_name() would say that uid=smith,ou=People,dc=example,dc=com is the same as [EMAIL PROTECTED] The standard defines two ways to do comparisons for access control. We should use one of them. Anything else is going to be more work and less reliable. What's the other way then? Last I checked there was no way to do case insensitive matching on gss_compare_name() but I could be on the wrong docs? Finding any kind of consistent docs for this stuff isn't exactly easy. Because we *must* have the ability to do case insensitive matching, or it *will* break on Windows. No gss_compare_name() is case sensitive. I think the way to do it is to know what case Microsoft is going to use and pre-map everything to that case (before you do a gss_import_name()). I *think* Microsoft will use upper case for the service name so we will need to change from postgres to POSTGRES as the default name in service principals. I've seen places where they may be using lower case realm names (which makes *NO* sense to me). Absent an environment where I can actually look at all these things, my only point of reference is mod_auth_kerb, and the issues reported with it. I know an upper case HTTP is needed to interoperate with windows clients. An upper case realm name seems to be OK, as is a lower case server name in the second component. The actual usernames seem to be lower case, but that's not the concern of the mod_auth_kerb developers since the deployer just needs to put in whatever matches. I assume in AD you can't create both smith and Smith, but can you create the latter at all? If you do, does AD remember the case for display purposes? Here at JPL usernames are lower case, and I don't think we allow anything special but hyphens in them, so I'm not likely to see a lot of the possible corner cases. I think you can upper case the service name, lower case the server name, upper case the realm name, and lower case the user name. If you can create Smith in AD and the user gets authenticated as [EMAIL PROTECTED] at the protocol level then that won't work though. I'm actually trying to write some Kerberos principal to X500
Re: [PATCHES] krb_match_realm
Henry B. Hotz wrote: On Nov 1, 2007, at 6:33 AM, Tom Lane wrote: Magnus Hagander [EMAIL PROTECTED] writes: Tom Lane wrote: Also the elog message texts need a bit of copy-editing. Probably ;-) Got any specific hints, so I don't have to go through the iteration twice? The one that caught my eye was SSPI domain (%s) does and configured domain (%s) don't match, regards, tom lane s/does // I assume that's your point? Yup, thanks. I fixed that per Toms earlier comment. I'll get back to you on the other email tomorrow, it's becoming late friday evening here now :-) //Magnus ---(end of broadcast)--- TIP 6: explain analyze is your friend
[PATCHES] krb_match_realm
Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Working on documentation which will of course be ready when it's committed :) Oh, and it changes the krb username handling to be the same as the gssapi one. I've never heard of anybody actually using the other version that it used to support, and the comment clearly states that it was broken for the really complex scenarios anyway - something nobody has complained about. //Magnus Index: backend/libpq/auth.c === RCS file: /cvsroot/pgsql/src/backend/libpq/auth.c,v retrieving revision 1.156 diff -c -r1.156 auth.c *** backend/libpq/auth.c 14 Sep 2007 15:58:02 - 1.156 --- backend/libpq/auth.c 1 Nov 2007 11:28:54 - *** *** 42,47 --- 42,48 char *pg_krb_srvnam; bool pg_krb_caseins_users; char *pg_krb_server_hostname = NULL; + char *pg_krb_match_realm = NULL; #ifdef USE_PAM #ifdef HAVE_PAM_PAM_APPL_H *** *** 103,132 #endif /* - * pg_an_to_ln -- return the local name corresponding to an authentication - * name - * - * XXX Assumes that the first aname component is the user name. This is NOT - * necessarily so, since an aname can actually be something out of your - * worst X.400 nightmare, like - * ORGANIZATION=U. C. Berkeley/NAME=Paul M. [EMAIL PROTECTED] - * Note that the MIT an_to_ln code does the same thing if you don't - * provide an aname mapping database...it may be a better idea to use - * krb5_an_to_ln, except that it punts if multiple components are found, - * and we can't afford to punt. - */ - static char * - pg_an_to_ln(char *aname) - { - char *p; - - if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) - *p = '\0'; - return aname; - } - - - /* * Various krb5 state which is not connection specfic, and a flag to * indicate whether we have initialised it yet. */ --- 104,109 *** *** 216,221 --- 193,199 krb5_auth_context auth_context = NULL; krb5_ticket *ticket; char *kusername; + char *cp; if (get_role_line(port-user_name) == NULL) return STATUS_ERROR; *** *** 240,247 * The client structure comes out of the ticket and is therefore * authenticated. Use it to check the username obtained from the * postmaster startup packet. - * - * I have no idea why this is considered necessary. */ #if defined(HAVE_KRB5_TICKET_ENC_PART2) retval = krb5_unparse_name(pg_krb5_context, --- 218,223 *** *** 263,269 return STATUS_ERROR; } ! kusername = pg_an_to_ln(kusername); if (pg_krb_caseins_users) ret = pg_strncasecmp(port-user_name, kusername, SM_DATABASE_USER); else --- 239,280 return STATUS_ERROR; } ! cp = strchr(kusername, '@'); ! if (cp) ! { ! *cp = '\0'; ! cp++; ! ! if (pg_krb_match_realm != NULL strlen(pg_krb_match_realm)) ! { ! /* Match realm against configured */ ! if (pg_krb_caseins_users) ! ret = pg_strcasecmp(pg_krb_match_realm, cp); ! else ! ret = strcmp(pg_krb_match_realm, cp); ! ! if (ret) ! { ! elog(DEBUG2, ! krb5 realm (%s) and configured realm (%s) don't match, ! cp, pg_krb_match_realm); ! ! krb5_free_ticket(pg_krb5_context, ticket); ! krb5_auth_con_free(pg_krb5_context, auth_context); ! return STATUS_ERROR; ! } ! } ! } ! else if (pg_krb_match_realm strlen(pg_krb_match_realm)) ! { ! elog(DEBUG2, ! krb5 did not return realm but realm matching was requested); ! ! krb5_free_ticket(pg_krb5_context, ticket); ! krb5_auth_con_free(pg_krb5_context, auth_context); ! return STATUS_ERROR; ! } ! if (pg_krb_caseins_users) ret = pg_strncasecmp(port-user_name, kusername, SM_DATABASE_USER); else *** *** 509,522 maj_stat, min_stat); /* ! * Compare the part of the username that comes before the @ ! * sign only (ignore realm). The GSSAPI libraries won't have ! * authenticated the user if he's from an invalid realm. */ if (strchr(gbuf.value, '@')) { char *cp = strchr(gbuf.value, '@'); *cp = '\0'; } if (pg_krb_caseins_users) --- 520,561 maj_stat, min_stat); /* ! * Split the username at the realm separator */ if (strchr(gbuf.value, '@')) { char *cp = strchr(gbuf.value, '@'); *cp = '\0'; + cp++; + + if (pg_krb_match_realm != NULL strlen(pg_krb_match_realm)) + { + /* + * Match the realm part of the name first + */ + if (pg_krb_caseins_users) + ret = pg_strcasecmp(pg_krb_match_realm, cp); + else + ret = strcmp(pg_krb_match_realm, cp); + + if (ret) + { + /* GSS realm does not match */ + elog(DEBUG2, + GSSAPI realm (%s) and configured realm (%s) don't match, + cp, pg_krb_match_realm); +
Re: [PATCHES] krb_match_realm
Magnus Hagander [EMAIL PROTECTED] writes: Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Minor gripe: krb_match_realm sounds like it should be a boolean: do or don't check the realm. Would just krb_realm be sensible? Also the elog message texts need a bit of copy-editing. regards, tom lane ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster
Re: [PATCHES] krb_match_realm
Tom Lane wrote: Magnus Hagander [EMAIL PROTECTED] writes: Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Minor gripe: krb_match_realm sounds like it should be a boolean: do or don't check the realm. Would just krb_realm be sensible? Yeah, probably. I'll change it to that. Also the elog message texts need a bit of copy-editing. Probably ;-) Got any specific hints, so I don't have to go through the iteration twice? //Magnus ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings
Re: [PATCHES] krb_match_realm
Magnus Hagander [EMAIL PROTECTED] writes: Tom Lane wrote: Also the elog message texts need a bit of copy-editing. Probably ;-) Got any specific hints, so I don't have to go through the iteration twice? The one that caught my eye was SSPI domain (%s) does and configured domain (%s) don't match, regards, tom lane ---(end of broadcast)--- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
Re: [PATCHES] krb_match_realm
Tom Lane wrote: Magnus Hagander [EMAIL PROTECTED] writes: Tom Lane wrote: Also the elog message texts need a bit of copy-editing. Probably ;-) Got any specific hints, so I don't have to go through the iteration twice? The one that caught my eye was SSPI domain (%s) does and configured domain (%s) don't match, Wow, I need a break from the monitor, I think. I read over them all again, and missed it again :-( Will fix. //Magnus ---(end of broadcast)--- TIP 7: You can help support the PostgreSQL project by donating at http://www.postgresql.org/about/donate
Re: [PATCHES] krb_match_realm
Henry B. Hotz wrote: Thank you very much. This helps, but I'm still evaluating how much. I *can* point at one problem though: you do a strchr(gbuf.value, '@') and then error out if there isn't a Kerberos realm there. In fact that is exactly the default username of at least one of the GSSAPI implementations I've tested if the realm is the same as the local default realm. Eh, so how do we then determine the difference between local realm and no realm given? I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? (FWIW, it works perfectly fine in my test setups, so I'd really like to know why this won't work) I also notice you have some code to do case insensitive name matching. I assume this is to take care of the fact that Microsoft Kerberos does case insensitive name matching (contrary to the standard and the other Kerberos implementations out there). I suspect issues there, but it will be 3-6 months before I will have an environment where I can easily test this. Most likely, the way to handle this is by figuring out what case Microsoft uses for each name inside the protocol and then pre-mapping to that case before feeding things to (non-Microsoft) GSSAPI. Yes, it's for supporting Active Directory. It's there in the same way it's there for krb5. I don't regard the case mapping issues as serious. We may not have the intended level of Windows/Unix compatibility, but I don't expect other issues. In other words I'm not even going to think about it until it's easy for me to investigate. Note that it's turned *off* by default, so it shouldn't even affect you. Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Working on documentation which will of course be ready when it's committed :) Oh, and it changes the krb username handling to be the same as the gssapi one. I've never heard of anybody actually using the other version that it used to support, and the comment clearly states that it was broken for the really complex scenarios anyway - something nobody has complained about. Well, *I* complained about it. ;-) Um, not sure we're talking about the same thing. I know you complained about the inability to match realm, but did you complain about the inability to use things like full X.500 names as usernames? //Magnus ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [PATCHES] krb_match_realm
Thank you very much. This helps, but I'm still evaluating how much. I *can* point at one problem though: you do a strchr(gbuf.value, '@') and then error out if there isn't a Kerberos realm there. In fact that is exactly the default username of at least one of the GSSAPI implementations I've tested if the realm is the same as the local default realm. I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name () the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. I also notice you have some code to do case insensitive name matching. I assume this is to take care of the fact that Microsoft Kerberos does case insensitive name matching (contrary to the standard and the other Kerberos implementations out there). I suspect issues there, but it will be 3-6 months before I will have an environment where I can easily test this. Most likely, the way to handle this is by figuring out what case Microsoft uses for each name inside the protocol and then pre-mapping to that case before feeding things to (non-Microsoft) GSSAPI. I don't regard the case mapping issues as serious. We may not have the intended level of Windows/Unix compatibility, but I don't expect other issues. In other words I'm not even going to think about it until it's easy for me to investigate. On Nov 1, 2007, at 5:27 AM, Magnus Hagander wrote: Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Working on documentation which will of course be ready when it's committed :) Oh, and it changes the krb username handling to be the same as the gssapi one. I've never heard of anybody actually using the other version that it used to support, and the comment clearly states that it was broken for the really complex scenarios anyway - something nobody has complained about. Well, *I* complained about it. ;-) Sorry if I'm the only one, but I can't change the deployment environment I'm going to have to deal with. //Magnus Index: backend/libpq/auth.c === RCS file: /cvsroot/pgsql/src/backend/libpq/auth.c,v retrieving revision 1.156 diff -c -r1.156 auth.c *** backend/libpq/auth.c14 Sep 2007 15:58:02 - 1.156 --- backend/libpq/auth.c1 Nov 2007 11:28:54 - *** *** 42,47 --- 42,48 char *pg_krb_srvnam; bool pg_krb_caseins_users; char *pg_krb_server_hostname = NULL; + char *pg_krb_match_realm = NULL; #ifdef USE_PAM #ifdef HAVE_PAM_PAM_APPL_H *** *** 103,132 #endif /* - * pg_an_to_ln -- return the local name corresponding to an authentication - * name - * - * XXX Assumes that the first aname component is the user name. This is NOT - * necessarily so, since an aname can actually be something out of your - * worst X.400 nightmare, like - * ORGANIZATION=U. C. Berkeley/NAME=Paul M. [EMAIL PROTECTED] - * Note that the MIT an_to_ln code does the same thing if you don't - * provide an aname mapping database...it may be a better idea to use - * krb5_an_to_ln, except that it punts if multiple components are found, - * and we can't afford to punt. - */ - static char * - pg_an_to_ln(char *aname) - { - char *p; - - if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) - *p = '\0'; - return aname; - } - - - /* * Various krb5 state which is not connection specfic, and a flag to * indicate whether we have initialised it yet. */ --- 104,109 *** *** 216,221 --- 193,199 krb5_auth_context auth_context = NULL; krb5_ticket *ticket; char *kusername; + char *cp; if (get_role_line(port-user_name) == NULL) return STATUS_ERROR; *** *** 240,247 * The client structure comes out of the ticket and is therefore * authenticated. Use it to check the username obtained from the * postmaster startup packet. -* -* I have no idea why this is considered necessary. */ #if defined(HAVE_KRB5_TICKET_ENC_PART2) retval = krb5_unparse_name(pg_krb5_context, --- 218,223 *** *** 263,269 return STATUS_ERROR; } ! kusername = pg_an_to_ln(kusername); if (pg_krb_caseins_users) ret = pg_strncasecmp(port-user_name, kusername, SM_DATABASE_USER); else --- 239,280 return STATUS_ERROR; } ! cp =
Re: [PATCHES] krb_match_realm
On Nov 1, 2007, at 1:40 PM, Magnus Hagander wrote: Henry B. Hotz wrote: Thank you very much. This helps, but I'm still evaluating how much. I *can* point at one problem though: you do a strchr(gbuf.value, '@') and then error out if there isn't a Kerberos realm there. In fact that is exactly the default username of at least one of the GSSAPI implementations I've tested if the realm is the same as the local default realm. Eh, so how do we then determine the difference between local realm and no realm given? Well, what I've seen is: no realm given if and only if the default local realm matches the realm for the GSSAPI username. I don't think that's guaranteed. I'm not entirely sure what the intended semantics of krb_match_realm are, but if you're trying to match the GSSAPI-authenticated name against value_of(PGUSER)@value_of(krb_match_realm) then you need to construct that string, gss_import_name() it, and then gss_compare_name() the imported name with the authenticated name that GSSAPI already gave you. I know the API overhead of doing that is a PITA, but that's what's going to work. Why? Because if we're using the GSSAPI then we need to use the properties defined by the GSSAPI, and not depend on observed behavior of specific implementations of specific mechanisms. Otherwise things will be non-portable or unreliable in ways that may be non-obvious. In particular gss_display_name() produces a character string intended for display to a human being. It is *NOT* intended for access control. As another example, Heimdal gss_display_name() puts '\' escapes in front of special characters in the username. I don't think it's worth writing special case code for that either. The standard defines two ways to do comparisons for access control. We should use one of them. Anything else is going to be more work and less reliable. (FWIW, it works perfectly fine in my test setups, so I'd really like to know why this won't work) I may be able to flag specific failures, as I've done here, but I'm sure I can't imagine all the ways that evading the standard might cause problems. Perhaps that's not helpful or not what you want, but it's all I can do. I also notice you have some code to do case insensitive name matching. I assume this is to take care of the fact that Microsoft Kerberos does case insensitive name matching (contrary to the standard and the other Kerberos implementations out there). I suspect issues there, but it will be 3-6 months before I will have an environment where I can easily test this. Most likely, the way to handle this is by figuring out what case Microsoft uses for each name inside the protocol and then pre-mapping to that case before feeding things to (non-Microsoft) GSSAPI. Yes, it's for supporting Active Directory. It's there in the same way it's there for krb5. I don't regard the case mapping issues as serious. We may not have the intended level of Windows/Unix compatibility, but I don't expect other issues. In other words I'm not even going to think about it until it's easy for me to investigate. Note that it's turned *off* by default, so it shouldn't even affect you. Not my current concern. If I find a problem, then I'll be in a position to define how it ought to be done (*IF* it needs to be done differently). Attached patch implements krb_match_realm for krb5, gssapi and sspi per complaint from Henry. Comments welcome. Working on documentation which will of course be ready when it's committed :) Oh, and it changes the krb username handling to be the same as the gssapi one. I've never heard of anybody actually using the other version that it used to support, and the comment clearly states that it was broken for the really complex scenarios anyway - something nobody has complained about. Well, *I* complained about it. ;-) Um, not sure we're talking about the same thing. I know you complained about the inability to match realm, but did you complain about the inability to use things like full X.500 names as usernames? //Magnus Well, it's not a high priority for me, but there is a GSSAPI mechanism called SPKM which uses X500-syle names (X509 certificate subject names to be precise). If we use gss_name_compare() properly then it should just work. ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings