8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.156 2007/09/14 15:58:02 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.157 2007/11/09 17:31:07 mha Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -42,6 +42,7 @@ char *pg_krb_server_keyfile;
42
42
char * pg_krb_srvnam ;
43
43
bool pg_krb_caseins_users ;
44
44
char * pg_krb_server_hostname = NULL ;
45
+ char * pg_krb_realm = NULL ;
45
46
46
47
#ifdef USE_PAM
47
48
#ifdef HAVE_PAM_PAM_APPL_H
@@ -102,30 +103,6 @@ static int CheckLDAPAuth(Port *port);
102
103
#include <com_err.h>
103
104
#endif
104
105
105
- /*
106
- * pg_an_to_ln -- return the local name corresponding to an authentication
107
- * name
108
- *
109
- * XXX Assumes that the first aname component is the user name. This is NOT
110
- * necessarily so, since an aname can actually be something out of your
111
- * worst X.400 nightmare, like
112
- * ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
113
- * Note that the MIT an_to_ln code does the same thing if you don't
114
- * provide an aname mapping database...it may be a better idea to use
115
- * krb5_an_to_ln, except that it punts if multiple components are found,
116
- * and we can't afford to punt.
117
- */
118
- static char *
119
- pg_an_to_ln (char * aname )
120
- {
121
- char * p ;
122
-
123
- if ((p = strchr (aname , '/' )) || (p = strchr (aname , '@' )))
124
- * p = '\0' ;
125
- return aname ;
126
- }
127
-
128
-
129
106
/*
130
107
* Various krb5 state which is not connection specfic, and a flag to
131
108
* indicate whether we have initialised it yet.
@@ -216,6 +193,7 @@ pg_krb5_recvauth(Port *port)
216
193
krb5_auth_context auth_context = NULL ;
217
194
krb5_ticket * ticket ;
218
195
char * kusername ;
196
+ char * cp ;
219
197
220
198
if (get_role_line (port -> user_name ) == NULL )
221
199
return STATUS_ERROR ;
@@ -240,8 +218,6 @@ pg_krb5_recvauth(Port *port)
240
218
* The "client" structure comes out of the ticket and is therefore
241
219
* authenticated. Use it to check the username obtained from the
242
220
* postmaster startup packet.
243
- *
244
- * I have no idea why this is considered necessary.
245
221
*/
246
222
#if defined(HAVE_KRB5_TICKET_ENC_PART2 )
247
223
retval = krb5_unparse_name (pg_krb5_context ,
@@ -263,7 +239,42 @@ pg_krb5_recvauth(Port *port)
263
239
return STATUS_ERROR ;
264
240
}
265
241
266
- kusername = pg_an_to_ln (kusername );
242
+ cp = strchr (kusername , '@' );
243
+ if (cp )
244
+ {
245
+ * cp = '\0' ;
246
+ cp ++ ;
247
+
248
+ if (pg_krb_realm != NULL && strlen (pg_krb_realm ))
249
+ {
250
+ /* Match realm against configured */
251
+ if (pg_krb_caseins_users )
252
+ ret = pg_strcasecmp (pg_krb_realm , cp );
253
+ else
254
+ ret = strcmp (pg_krb_realm , cp );
255
+
256
+ if (ret )
257
+ {
258
+ elog (DEBUG2 ,
259
+ "krb5 realm (%s) and configured realm (%s) don't match" ,
260
+ cp , pg_krb_realm );
261
+
262
+ krb5_free_ticket (pg_krb5_context , ticket );
263
+ krb5_auth_con_free (pg_krb5_context , auth_context );
264
+ return STATUS_ERROR ;
265
+ }
266
+ }
267
+ }
268
+ else if (pg_krb_realm && strlen (pg_krb_realm ))
269
+ {
270
+ elog (DEBUG2 ,
271
+ "krb5 did not return realm but realm matching was requested" );
272
+
273
+ krb5_free_ticket (pg_krb5_context , ticket );
274
+ krb5_auth_con_free (pg_krb5_context , auth_context );
275
+ return STATUS_ERROR ;
276
+ }
277
+
267
278
if (pg_krb_caseins_users )
268
279
ret = pg_strncasecmp (port -> user_name , kusername , SM_DATABASE_USER );
269
280
else
@@ -509,14 +520,42 @@ pg_GSS_recvauth(Port *port)
509
520
maj_stat , min_stat );
510
521
511
522
/*
512
- * Compare the part of the username that comes before the @
513
- * sign only (ignore realm). The GSSAPI libraries won't have
514
- * authenticated the user if he's from an invalid realm.
523
+ * Split the username at the realm separator
515
524
*/
516
525
if (strchr (gbuf .value , '@' ))
517
526
{
518
527
char * cp = strchr (gbuf .value , '@' );
519
528
* cp = '\0' ;
529
+ cp ++ ;
530
+
531
+ if (pg_krb_realm != NULL && strlen (pg_krb_realm ))
532
+ {
533
+ /*
534
+ * Match the realm part of the name first
535
+ */
536
+ if (pg_krb_caseins_users )
537
+ ret = pg_strcasecmp (pg_krb_realm , cp );
538
+ else
539
+ ret = strcmp (pg_krb_realm , cp );
540
+
541
+ if (ret )
542
+ {
543
+ /* GSS realm does not match */
544
+ elog (DEBUG2 ,
545
+ "GSSAPI realm (%s) and configured realm (%s) don't match" ,
546
+ cp , pg_krb_realm );
547
+ gss_release_buffer (& lmin_s , & gbuf );
548
+ return STATUS_ERROR ;
549
+ }
550
+ }
551
+ }
552
+ else if (pg_krb_realm && strlen (pg_krb_realm ))
553
+ {
554
+ elog (DEBUG2 ,
555
+ "GSSAPI did not return realm but realm matching was requested" );
556
+
557
+ gss_release_buffer (& lmin_s , & gbuf );
558
+ return STATUS_ERROR ;
520
559
}
521
560
522
561
if (pg_krb_caseins_users )
@@ -792,6 +831,21 @@ pg_SSPI_recvauth(Port *port)
792
831
793
832
free (tokenuser );
794
833
834
+ /*
835
+ * Compare realm/domain if requested. In SSPI, always compare case insensitive.
836
+ */
837
+ if (pg_krb_realm && strlen (pg_krb_realm ))
838
+ {
839
+ if (pg_strcasecmp (pg_krb_realm , domainname ))
840
+ {
841
+ elog (DEBUG2 ,
842
+ "SSPI domain (%s) and configured domain (%s) don't match" ,
843
+ domainname , pg_krb_realm );
844
+
845
+ return STATUS_ERROR ;
846
+ }
847
+ }
848
+
795
849
/*
796
850
* We have the username (without domain/realm) in accountname, compare
797
851
* to the supplied value. In SSPI, always compare case insensitive.
0 commit comments