Re: [PATCHES] krb_match_realm

2007-11-14 Thread Henry B. Hotz


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

2007-11-09 Thread Magnus Hagander

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

2007-11-06 Thread Magnus Hagander
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

2007-11-06 Thread Henry B. Hotz


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

2007-11-02 Thread Magnus Hagander
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

2007-11-02 Thread Henry B. Hotz


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

2007-11-02 Thread Henry B. Hotz


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

2007-11-02 Thread Magnus Hagander
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

2007-11-01 Thread Magnus Hagander
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

2007-11-01 Thread Tom Lane
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

2007-11-01 Thread Magnus Hagander
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

2007-11-01 Thread Tom Lane
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

2007-11-01 Thread Magnus Hagander
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

2007-11-01 Thread Magnus Hagander
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

2007-11-01 Thread Henry B. Hotz

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

2007-11-01 Thread Henry B. Hotz


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