1010 * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.110 2005/12/26 14:58:05 petere Exp $
13+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.111 2006/02/12 20:04:42 momjian Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
@@ -101,22 +101,33 @@ pg_an_to_ln(char *aname)
101101 * Various krb5 state which is not connection specific, and a flag to
102102 * indicate whether we have initialised it yet.
103103 */
104+ /*
104105static intpg_krb5_initialised;
105106static krb5_context pg_krb5_context;
106107static krb5_ccache pg_krb5_ccache;
107108static krb5_principal pg_krb5_client;
108109static char *pg_krb5_name;
110+ */
111+
112+ struct krb5_info
113+ {
114+ int pg_krb5_initialised ;
115+ krb5_context pg_krb5_context ;
116+ krb5_ccache pg_krb5_ccache ;
117+ krb5_principal pg_krb5_client ;
118+ char * pg_krb5_name ;
119+ };
109120
110121
111122static int
112- pg_krb5_init (char * PQerrormsg )
123+ pg_krb5_init (char * PQerrormsg , struct krb5_info * info )
113124{
114125krb5_error_code retval ;
115126
116- if (pg_krb5_initialised )
127+ if (info -> pg_krb5_initialised )
117128return STATUS_OK ;
118129
119- retval = krb5_init_context (& pg_krb5_context );
130+ retval = krb5_init_context (& ( info -> pg_krb5_context ) );
120131if (retval )
121132{
122133snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
@@ -125,46 +136,56 @@ pg_krb5_init(char *PQerrormsg)
125136return STATUS_ERROR ;
126137}
127138
128- retval = krb5_cc_default (pg_krb5_context ,& pg_krb5_ccache );
139+ retval = krb5_cc_default (info -> pg_krb5_context ,& ( info -> pg_krb5_ccache ) );
129140if (retval )
130141{
131142snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
132143"pg_krb5_init: krb5_cc_default: %s\n" ,
133144error_message (retval ));
134- krb5_free_context (pg_krb5_context );
145+ krb5_free_context (info -> pg_krb5_context );
135146return STATUS_ERROR ;
136147}
137148
138- retval = krb5_cc_get_principal (pg_krb5_context ,pg_krb5_ccache ,
139- & pg_krb5_client );
149+ retval = krb5_cc_get_principal (info -> pg_krb5_context ,info -> pg_krb5_ccache ,
150+ & ( info -> pg_krb5_client ) );
140151if (retval )
141152{
142153snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
143154"pg_krb5_init: krb5_cc_get_principal: %s\n" ,
144155error_message (retval ));
145- krb5_cc_close (pg_krb5_context ,pg_krb5_ccache );
146- krb5_free_context (pg_krb5_context );
156+ krb5_cc_close (info -> pg_krb5_context ,info -> pg_krb5_ccache );
157+ krb5_free_context (info -> pg_krb5_context );
147158return STATUS_ERROR ;
148159}
149160
150- retval = krb5_unparse_name (pg_krb5_context ,pg_krb5_client ,& pg_krb5_name );
161+ retval = krb5_unparse_name (info -> pg_krb5_context ,info -> pg_krb5_client ,& ( info -> pg_krb5_name ) );
151162if (retval )
152163{
153164snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
154165"pg_krb5_init: krb5_unparse_name: %s\n" ,
155166error_message (retval ));
156- krb5_free_principal (pg_krb5_context ,pg_krb5_client );
157- krb5_cc_close (pg_krb5_context ,pg_krb5_ccache );
158- krb5_free_context (pg_krb5_context );
167+ krb5_free_principal (info -> pg_krb5_context ,info -> pg_krb5_client );
168+ krb5_cc_close (info -> pg_krb5_context ,info -> pg_krb5_ccache );
169+ krb5_free_context (info -> pg_krb5_context );
159170return STATUS_ERROR ;
160171}
161172
162- pg_krb5_name = pg_an_to_ln (pg_krb5_name );
173+ info -> pg_krb5_name = pg_an_to_ln (info -> pg_krb5_name );
163174
164- pg_krb5_initialised = 1 ;
175+ info -> pg_krb5_initialised = 1 ;
165176return STATUS_OK ;
166177}
167178
179+ static void
180+ pg_krb5_destroy (struct krb5_info * info )
181+ {
182+ krb5_free_principal (info -> pg_krb5_context ,info -> pg_krb5_client );
183+ krb5_cc_close (info -> pg_krb5_context ,info -> pg_krb5_ccache );
184+ krb5_free_context (info -> pg_krb5_context );
185+ free (info -> pg_krb5_name );
186+ }
187+
188+
168189
169190/*
170191 * pg_krb5_authname -- returns a pointer to static space containing whatever
@@ -173,10 +194,16 @@ pg_krb5_init(char *PQerrormsg)
173194static const char *
174195pg_krb5_authname (char * PQerrormsg )
175196{
176- if (pg_krb5_init (PQerrormsg )!= STATUS_OK )
197+ char * tmp_name ;
198+ struct krb5_info info ;
199+ info .pg_krb5_initialised = 0 ;
200+
201+ if (pg_krb5_init (PQerrormsg ,& info )!= STATUS_OK )
177202return NULL ;
203+ tmp_name = strdup (info .pg_krb5_name );
204+ pg_krb5_destroy (& info );
178205
179- return pg_krb5_name ;
206+ return tmp_name ;
180207}
181208
182209
@@ -192,6 +219,8 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
192219krb5_principal server ;
193220krb5_auth_context auth_context = NULL ;
194221krb5_error * err_ret = NULL ;
222+ struct krb5_info info ;
223+ info .pg_krb5_initialised = 0 ;
195224
196225if (!hostname )
197226{
@@ -200,17 +229,18 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
200229return STATUS_ERROR ;
201230}
202231
203- ret = pg_krb5_init (PQerrormsg );
232+ ret = pg_krb5_init (PQerrormsg , & info );
204233if (ret != STATUS_OK )
205234return ret ;
206235
207- retval = krb5_sname_to_principal (pg_krb5_context ,hostname ,servicename ,
236+ retval = krb5_sname_to_principal (info . pg_krb5_context ,hostname ,servicename ,
208237KRB5_NT_SRV_HST ,& server );
209238if (retval )
210239{
211240snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
212241"pg_krb5_sendauth: krb5_sname_to_principal: %s\n" ,
213242error_message (retval ));
243+ pg_krb5_destroy (& info );
214244return STATUS_ERROR ;
215245}
216246
@@ -225,16 +255,17 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
225255
226256snprintf (PQerrormsg ,PQERRORMSG_LENGTH ,
227257libpq_gettext ("could not set socket to blocking mode: %s\n" ),pqStrerror (errno ,sebuf ,sizeof (sebuf )));
228- krb5_free_principal (pg_krb5_context ,server );
258+ krb5_free_principal (info .pg_krb5_context ,server );
259+ pg_krb5_destroy (& info );
229260return STATUS_ERROR ;
230261}
231262
232- retval = krb5_sendauth (pg_krb5_context ,& auth_context ,
263+ retval = krb5_sendauth (info . pg_krb5_context ,& auth_context ,
233264 (krb5_pointer )& sock , (char * )servicename ,
234- pg_krb5_client ,server ,
265+ info . pg_krb5_client ,server ,
235266AP_OPTS_MUTUAL_REQUIRED ,
236267NULL ,0 ,/* no creds, use ccache instead */
237- pg_krb5_ccache ,& err_ret ,NULL ,NULL );
268+ info . pg_krb5_ccache ,& err_ret ,NULL ,NULL );
238269if (retval )
239270{
240271if (retval == KRB5_SENDAUTH_REJECTED && err_ret )
@@ -259,12 +290,12 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
259290}
260291
261292if (err_ret )
262- krb5_free_error (pg_krb5_context ,err_ret );
293+ krb5_free_error (info . pg_krb5_context ,err_ret );
263294
264295ret = STATUS_ERROR ;
265296}
266297
267- krb5_free_principal (pg_krb5_context ,server );
298+ krb5_free_principal (info . pg_krb5_context ,server );
268299
269300if (!pg_set_noblock (sock ))
270301{
@@ -275,6 +306,7 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
275306pqStrerror (errno ,sebuf ,sizeof (sebuf )));
276307ret = STATUS_ERROR ;
277308}
309+ pg_krb5_destroy (& info );
278310
279311return ret ;
280312}
@@ -487,6 +519,9 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
487519char *
488520pg_fe_getauthname (char * PQerrormsg )
489521{
522+ #ifdef KRB5
523+ const char * krb5_name = NULL ;
524+ #endif
490525const char * name = NULL ;
491526char * authn ;
492527
@@ -511,7 +546,12 @@ pg_fe_getauthname(char *PQerrormsg)
511546pglock_thread ();
512547
513548#ifdef KRB5
514- name = pg_krb5_authname (PQerrormsg );
549+ /* pg_krb5_authname gives us a strdup'd value that we need
550+ * to free later, however, we don't want to free 'name' directly
551+ * in case it's *not* a Kerberos login and we fall through to
552+ * name = pw->pw_name; */
553+ krb5_name = pg_krb5_authname (PQerrormsg );
554+ name = krb5_name ;
515555#endif
516556
517557if (!name )
@@ -527,6 +567,12 @@ pg_fe_getauthname(char *PQerrormsg)
527567
528568authn = name ?strdup (name ) :NULL ;
529569
570+ #ifdef KRB5
571+ /* Free the strdup'd string from pg_krb5_authname, if we got one */
572+ if (krb5_name )
573+ free (krb5_name );
574+ #endif
575+
530576pgunlock_thread ();
531577
532578return authn ;