Skip to content

Commit 526f773

Browse files
committed
* Stephen Frost (sfrost@snowman.net) wrote:
> I've now tested this patch at home w/ 8.2HEAD and it seems to fix the > bug. I plan on testing it under 8.1.2 at work tommorow with > mod_auth_krb5, etc, and expect it'll work there. Assuming all goes > well and unless someone objects I'll forward the patch to -patches. > It'd be great to have this fixed as it'll allow us to use Kerberos to > authenticate to phppgadmin and other web-based tools which use > Postgres. While playing with this patch under 8.1.2 at home I discovered a mistake in how I manually applied one of the hunks to fe-auth.c. Basically, the base code had changed and so the patch needed to be modified slightly. This is because the code no longer either has a freeable pointer under 'name' or has 'name' as NULL. The attached patch correctly frees the string from pg_krb5_authname (where it had been strdup'd) if and only if pg_krb5_authname returned a string (as opposed to falling through and having name be set using name = pw->name;). Also added a comment to this effect. Backpatch to 8.1.X. Stephen Frost
1 parent 357cc01 commit 526f773

File tree

1 file changed

+73
-27
lines changed

1 file changed

+73
-27
lines changed

src/interfaces/libpq/fe-auth.c

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.113 2006/03/05 15:59:08 momjian Exp $
13+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.114 2006/03/06 17:59:30 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+
/*
104105
static int pg_krb5_initialised;
105106
static krb5_context pg_krb5_context;
106107
static krb5_ccache pg_krb5_ccache;
107108
static krb5_principal pg_krb5_client;
108109
static 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

111122
static int
112-
pg_krb5_init(char *PQerrormsg)
123+
pg_krb5_init(char *PQerrormsg, struct krb5_info *info)
113124
{
114125
krb5_error_code retval;
115126

116-
if (pg_krb5_initialised)
127+
if (info->pg_krb5_initialised)
117128
return STATUS_OK;
118129

119-
retval = krb5_init_context(&pg_krb5_context);
130+
retval = krb5_init_context(&(info->pg_krb5_context));
120131
if (retval)
121132
{
122133
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
@@ -125,46 +136,56 @@ pg_krb5_init(char *PQerrormsg)
125136
return 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));
129140
if (retval)
130141
{
131142
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
132143
"pg_krb5_init: krb5_cc_default: %s\n",
133144
error_message(retval));
134-
krb5_free_context(pg_krb5_context);
145+
krb5_free_context(info->pg_krb5_context);
135146
return 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));
140151
if (retval)
141152
{
142153
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
143154
"pg_krb5_init: krb5_cc_get_principal: %s\n",
144155
error_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);
147158
return 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));
151162
if (retval)
152163
{
153164
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
154165
"pg_krb5_init: krb5_unparse_name: %s\n",
155166
error_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);
159170
return 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;
165176
return 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)
173194
static const char *
174195
pg_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)
177202
return 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
192219
krb5_principal server;
193220
krb5_auth_context auth_context = NULL;
194221
krb5_error *err_ret = NULL;
222+
struct krb5_info info;
223+
info.pg_krb5_initialised = 0;
195224

196225
if (!hostname)
197226
{
@@ -200,17 +229,18 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
200229
return STATUS_ERROR;
201230
}
202231

203-
ret = pg_krb5_init(PQerrormsg);
232+
ret = pg_krb5_init(PQerrormsg, &info);
204233
if (ret != STATUS_OK)
205234
return 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,
208237
KRB5_NT_SRV_HST, &server);
209238
if (retval)
210239
{
211240
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
212241
"pg_krb5_sendauth: krb5_sname_to_principal: %s\n",
213242
error_message(retval));
243+
pg_krb5_destroy(&info);
214244
return STATUS_ERROR;
215245
}
216246

@@ -225,16 +255,17 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
225255

226256
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
227257
libpq_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);
229260
return 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,
235266
AP_OPTS_MUTUAL_REQUIRED,
236267
NULL, 0, /* no creds, use ccache instead */
237-
pg_krb5_ccache, &err_ret, NULL, NULL);
268+
info.pg_krb5_ccache, &err_ret, NULL, NULL);
238269
if (retval)
239270
{
240271
if (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

261292
if (err_ret)
262-
krb5_free_error(pg_krb5_context, err_ret);
293+
krb5_free_error(info.pg_krb5_context, err_ret);
263294

264295
ret = STATUS_ERROR;
265296
}
266297

267-
krb5_free_principal(pg_krb5_context, server);
298+
krb5_free_principal(info.pg_krb5_context, server);
268299

269300
if (!pg_set_noblock(sock))
270301
{
@@ -275,6 +306,7 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char *s
275306
pqStrerror(errno, sebuf, sizeof(sebuf)));
276307
ret = STATUS_ERROR;
277308
}
309+
pg_krb5_destroy(&info);
278310

279311
return ret;
280312
}
@@ -487,6 +519,9 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
487519
char *
488520
pg_fe_getauthname(char *PQerrormsg)
489521
{
522+
#ifdef KRB5
523+
const char *krb5_name = NULL;
524+
#endif
490525
const char *name = NULL;
491526
char *authn;
492527

@@ -511,7 +546,12 @@ pg_fe_getauthname(char *PQerrormsg)
511546
pglock_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

517557
if (!name)
@@ -527,6 +567,12 @@ pg_fe_getauthname(char *PQerrormsg)
527567

528568
authn = 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+
530576
pgunlock_thread();
531577

532578
return authn;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy