Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9500b35

Browse files
committed
Patch for Kerberos V.
Most (nearly all) of the work was done by David Wragg <dpw@doc.ic.ac.uk> He patched 6.5.3. I've updated it for 7.0RC5. It works for MIT kerberos 1.1.1 (and previously for 1.0.6 as well). I've got the patch against 6.5.3, plus kerberized RPMS. Mike Wyer <mw@doc.ic.ac.uk> || "Woof?"
1 parent ddae527 commit 9500b35

File tree

5 files changed

+238
-266
lines changed

5 files changed

+238
-266
lines changed

src/Makefile.global.in

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
#
99
# IDENTIFICATION
10-
# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.71 2000/05/23 02:12:46 tgl Exp $
10+
# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.72 2000/05/27 03:39:31 momjian Exp $
1111
#
1212
# NOTES
1313
# Essentially all Postgres make files include this file and use the
@@ -120,7 +120,7 @@ ENFORCE_ALIGNMENT= true
120120
# Set KRBVERS to "4" for Kerberos v4, "5" for Kerberos v5.
121121
# XXX Edit the default Kerberos variables below!
122122
#
123-
#KRBVERS= 5
123+
KRBVERS=5
124124

125125
# Globally pass Kerberos file locations.
126126
# these are used in the postmaster and all libpq applications.
@@ -132,18 +132,18 @@ ENFORCE_ALIGNMENT= true
132132
# PG_KRB_SRVTAB is the location of the server's keytab file.
133133
#
134134
ifdef KRBVERS
135-
KRBINCS= -I/usr/athena/include
136-
KRBLIBS= -L/usr/athena/lib
137-
KRBFLAGS+= $(KRBINCS) -DPG_KRB_SRVNAM='"postgres_dbms"'
135+
KRBINCS= -I/usr/krb5/include
136+
KRBLIBS= -L/usr/krb5/lib
137+
KRBFLAGS+= $(KRBINCS) -DPG_KRB_SRVNAM='"postgres"'
138138
ifeq ($(KRBVERS), 4)
139139
KRBFLAGS+= -DKRB4
140140
KRBFLAGS+= -DPG_KRB_SRVTAB='"/etc/srvtab"'
141141
KRBLIBS+= -lkrb -ldes
142142
else
143143
ifeq ($(KRBVERS), 5)
144144
KRBFLAGS+= -DKRB5
145-
KRBFLAGS+= -DPG_KRB_SRVTAB='"FILE:/krb5/srvtab.postgres"'
146-
KRBLIBS+= -lkrb5 -lcrypto -lcom_err -lisode
145+
KRBFLAGS+= -DPG_KRB_SRVTAB='"FILE:/usr/local/postgres/krb5.keytab"'
146+
KRBLIBS+= -lkrb5 -lcrypto -lcom_err
147147
endif
148148
endif
149149
endif

src/backend/libpq/auth.c

+104-99
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.44 2000/04/12 17:15:13 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.45 2000/05/27 03:39:31 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -149,7 +149,8 @@ pg_krb4_recvauth(Port *port)
149149
*----------------------------------------------------------------
150150
*/
151151

152-
#include "krb5/krb5.h"
152+
#include <krb5.h>
153+
#include <com_err.h>
153154

154155
/*
155156
* pg_an_to_ln -- return the local name corresponding to an authentication
@@ -174,130 +175,134 @@ pg_an_to_ln(char *aname)
174175
return aname;
175176
}
176177

178+
177179
/*
178-
* pg_krb5_recvauth -- server routine to receive authentication information
179-
* from the client
180-
*
181-
* We still need to compare the username obtained from the client's setup
182-
* packet to the authenticated name, as described in pg_krb4_recvauth. This
183-
* is a bit more problematic in v5, as described above in pg_an_to_ln.
184-
*
185-
* In addition, as described above in pg_krb5_sendauth, we still need to
186-
* canonicalize the server name v4-style before constructing a principal
187-
* from it. Again, this is kind of iffy.
188-
*
189-
* Finally, we need to tangle with the fact that v5 doesn't let you explicitly
190-
* set server keytab file names -- you have to feed lower-level routines a
191-
* function to retrieve the contents of a keytab, along with a single argument
192-
* that allows them to open the keytab. We assume that a server keytab is
193-
* always a real file so we can allow people to specify their own filenames.
194-
* (This is important because the POSTGRES keytab needs to be readable by
195-
* non-root users/groups; the v4 tools used to force you do dump a whole
196-
* host's worth of keys into a file, effectively forcing you to use one file,
197-
* but kdb5_edit allows you to select which principals to dump. Yay!)
180+
* Various krb5 state which is not connection specfic, and a flag to
181+
* indicate whether we have initialised it yet.
198182
*/
183+
static int pg_krb5_initialised;
184+
static krb5_context pg_krb5_context;
185+
static krb5_keytab pg_krb5_keytab;
186+
static krb5_principal pg_krb5_server;
187+
188+
199189
static int
200-
pg_krb5_recvauth(Port *port)
190+
pg_krb5_init(void)
201191
{
202-
char servbuf[MAXHOSTNAMELEN + 1 +
203-
sizeof(PG_KRB_SRVNAM)];
204-
char *hostp,
205-
*kusername = (char *) NULL;
206-
krb5_error_code code;
207-
krb5_principal client,
208-
server;
209-
krb5_address sender_addr;
210-
krb5_rdreq_key_proc keyproc = (krb5_rdreq_key_proc) NULL;
211-
krb5_pointer keyprocarg = (krb5_pointer) NULL;
192+
krb5_error_code retval;
212193

213-
/*
214-
* Set up server side -- since we have no ticket file to make this
215-
* easy, we construct our own name and parse it. See note on
216-
* canonicalization above.
217-
*/
218-
strcpy(servbuf, PG_KRB_SRVNAM);
219-
*(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/';
220-
if (gethostname(++hostp, MAXHOSTNAMELEN) < 0)
221-
strcpy(hostp, "localhost");
222-
if (hostp = strchr(hostp, '.'))
223-
*hostp = '\0';
224-
if (code = krb5_parse_name(servbuf, &server))
225-
{
194+
if (pg_krb5_initialised)
195+
return STATUS_OK;
196+
197+
retval = krb5_init_context(&pg_krb5_context);
198+
if (retval) {
226199
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
227-
"pg_krb5_recvauth: Kerberos error %d in krb5_parse_name\n", code);
228-
com_err("pg_krb5_recvauth", code, "in krb5_parse_name");
200+
"pg_krb5_init: krb5_init_context returned"
201+
" Kerberos error %d\n", retval);
202+
com_err("postgres", retval, "while initializing krb5");
229203
return STATUS_ERROR;
230204
}
231205

232-
/*
233-
* krb5_sendauth needs this to verify the address in the client
234-
* authenticator.
235-
*/
236-
sender_addr.addrtype = port->raddr.in.sin_family;
237-
sender_addr.length = sizeof(port->raddr.in.sin_addr);
238-
sender_addr.contents = (krb5_octet *) & (port->raddr.in.sin_addr);
239-
240-
if (strcmp(PG_KRB_SRVTAB, ""))
241-
{
242-
keyproc = krb5_kt_read_service_key;
243-
keyprocarg = PG_KRB_SRVTAB;
206+
retval = krb5_kt_resolve(pg_krb5_context, PG_KRB_SRVTAB, &pg_krb5_keytab);
207+
if (retval) {
208+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
209+
"pg_krb5_init: krb5_kt_resolve returned"
210+
" Kerberos error %d\n", retval);
211+
com_err("postgres", retval, "while resolving keytab file %s",
212+
PG_KRB_SRVTAB);
213+
krb5_free_context(pg_krb5_context);
214+
return STATUS_ERROR;
244215
}
245216

246-
if (code = krb5_recvauth((krb5_pointer) & port->sock,
247-
PG_KRB5_VERSION,
248-
server,
249-
&sender_addr,
250-
(krb5_pointer) NULL,
251-
keyproc,
252-
keyprocarg,
253-
(char *) NULL,
254-
(krb5_int32 *) NULL,
255-
&client,
256-
(krb5_ticket **) NULL,
257-
(krb5_authenticator **) NULL))
258-
{
217+
retval = krb5_sname_to_principal(pg_krb5_context, NULL, PG_KRB_SRVNAM,
218+
KRB5_NT_SRV_HST, &pg_krb5_server);
219+
if (retval) {
259220
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
260-
"pg_krb5_recvauth: Kerberos error %d in krb5_recvauth\n", code);
261-
com_err("pg_krb5_recvauth", code, "in krb5_recvauth");
262-
krb5_free_principal(server);
221+
"pg_krb5_init: krb5_sname_to_principal returned"
222+
" Kerberos error %d\n", retval);
223+
com_err("postgres", retval,
224+
"while getting server principal for service %s",
225+
PG_KRB_SRVTAB);
226+
krb5_kt_close(pg_krb5_context, pg_krb5_keytab);
227+
krb5_free_context(pg_krb5_context);
263228
return STATUS_ERROR;
264229
}
265-
krb5_free_principal(server);
230+
231+
pg_krb5_initialised = 1;
232+
return STATUS_OK;
233+
}
234+
235+
236+
/*
237+
* pg_krb5_recvauth -- server routine to receive authentication information
238+
* from the client
239+
*
240+
* We still need to compare the username obtained from the client's setup
241+
* packet to the authenticated name, as described in pg_krb4_recvauth. This
242+
* is a bit more problematic in v5, as described above in pg_an_to_ln.
243+
*
244+
* We have our own keytab file because postgres is unlikely to run as root,
245+
* and so cannot read the default keytab.
246+
*/
247+
static int
248+
pg_krb5_recvauth(Port *port)
249+
{
250+
krb5_error_code retval;
251+
int ret;
252+
krb5_auth_context auth_context = NULL;
253+
krb5_ticket *ticket;
254+
char *kusername;
255+
256+
ret = pg_krb5_init();
257+
if (ret != STATUS_OK)
258+
return ret;
259+
260+
retval = krb5_recvauth(pg_krb5_context, &auth_context,
261+
(krb5_pointer)&port->sock, PG_KRB_SRVNAM,
262+
pg_krb5_server, 0, pg_krb5_keytab, &ticket);
263+
if (retval) {
264+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
265+
"pg_krb5_recvauth: krb5_recvauth returned"
266+
" Kerberos error %d\n", retval);
267+
com_err("postgres", retval, "from krb5_recvauth");
268+
return STATUS_ERROR;
269+
}
266270

267271
/*
268272
* The "client" structure comes out of the ticket and is therefore
269273
* authenticated. Use it to check the username obtained from the
270274
* postmaster startup packet.
275+
*
276+
* I have no idea why this is considered necessary.
271277
*/
272-
if ((code = krb5_unparse_name(client, &kusername)))
273-
{
278+
retval = krb5_unparse_name(pg_krb5_context,
279+
ticket->enc_part2->client, &kusername);
280+
if (retval) {
274281
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
275-
"pg_krb5_recvauth: Kerberos error %d in krb5_unparse_name\n", code);
276-
com_err("pg_krb5_recvauth", code, "in krb5_unparse_name");
277-
krb5_free_principal(client);
278-
return STATUS_ERROR;
279-
}
280-
krb5_free_principal(client);
281-
if (!kusername)
282-
{
283-
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
284-
"pg_krb5_recvauth: could not decode username\n");
285-
fputs(PQerrormsg, stderr);
286-
pqdebug("%s", PQerrormsg);
282+
"pg_krb5_recvauth: krb5_unparse_name returned"
283+
" Kerberos error %d\n", retval);
284+
com_err("postgres", retval, "while unparsing client name");
285+
krb5_free_ticket(pg_krb5_context, ticket);
286+
krb5_auth_con_free(pg_krb5_context, auth_context);
287287
return STATUS_ERROR;
288288
}
289+
289290
kusername = pg_an_to_ln(kusername);
290-
if (strncmp(username, kusername, SM_USER))
291+
if (strncmp(port->user, kusername, SM_USER))
291292
{
292293
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
293-
"pg_krb5_recvauth: name \"%s\" != \"%s\"\n", port->user, kusername);
294-
fputs(PQerrormsg, stderr);
295-
pqdebug("%s", PQerrormsg);
296-
pfree(kusername);
297-
return STATUS_ERROR;
294+
"pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"\n",
295+
port->user, kusername);
296+
ret = STATUS_ERROR;
298297
}
299-
pfree(kusername);
300-
return STATUS_OK;
298+
else
299+
ret = STATUS_OK;
300+
301+
krb5_free_ticket(pg_krb5_context, ticket);
302+
krb5_auth_con_free(pg_krb5_context, auth_context);
303+
free(kusername);
304+
305+
return ret;
301306
}
302307

303308
#else

src/interfaces/libpq/Makefile.in

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# Copyright (c) 1994, Regents of the University of California
77
#
88
# IDENTIFICATION
9-
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.54 2000/04/14 00:42:06 tgl Exp $
9+
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.55 2000/05/27 03:39:33 momjian Exp $
1010
#
1111
#-------------------------------------------------------------------------
1212

@@ -21,6 +21,7 @@ CFLAGS+= -DFRONTEND
2121

2222
ifdef KRBVERS
2323
CFLAGS+= $(KRBFLAGS)
24+
SHLIB_LINK += $(KRBLIBS)
2425
endif
2526

2627
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \

0 commit comments

Comments
 (0)