Skip to content

Commit bca9d0c

Browse files
committed
Add SCM_CREDS to get owner of unix-domain socket on BSD-like systems.
1 parent 04fdf73 commit bca9d0c

File tree

9 files changed

+1019
-783
lines changed

9 files changed

+1019
-783
lines changed

doc/FAQ_japanese

Lines changed: 701 additions & 653 deletions
Large diffs are not rendered by default.

doc/src/FAQ/FAQ_japanese.html

Lines changed: 125 additions & 104 deletions
Large diffs are not rendered by default.

src/backend/libpq/auth.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.62 2001/08/17 15:44:17 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.63 2001/08/21 00:33:27 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515

1616
#include "postgres.h"
1717

18-
#include <sys/types.h> /* needed by in.h on Ultrix */
18+
#include <sys/types.h>
19+
#include <sys/socket.h> /* for SCM_CREDS */
20+
#ifdef SCM_CREDS
21+
#include <sys/uio.h> /* for struct iovec */
22+
#include <sys/ucred.h>
23+
#include <errno.h>
24+
#endif
1925
#include <netinet/in.h>
2026
#include <arpa/inet.h>
21-
2227
#include "libpq/auth.h"
2328
#include "libpq/crypt.h"
2429
#include "libpq/hba.h"
@@ -28,12 +33,10 @@
2833
#include "miscadmin.h"
2934

3035
static void sendAuthRequest(Port *port, AuthRequest areq);
31-
3236
static int checkPassword(Port *port, char *user, char *password);
3337
static int old_be_recvauth(Port *port);
3438
static int map_old_to_new(Port *port, UserAuth old, int status);
3539
static void auth_failed(Port *port);
36-
3740
static int recv_and_check_password_packet(Port *port);
3841
static int recv_and_check_passwordv0(Port *port);
3942

@@ -493,6 +496,26 @@ ClientAuthentication(Port *port)
493496
break;
494497

495498
case uaIdent:
499+
#if !defined(SO_PEERCRED) && defined(SCM_CREDS)
500+
/*
501+
* If we are doing ident on unix-domain sockets,
502+
* use SCM_CREDS only if it is defined and SO_PEERCRED isn't.
503+
*/
504+
#ifdef fc_uid
505+
/* Receive credentials on next message receipt, BSD/OS */
506+
{
507+
int on = 1;
508+
if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
509+
{
510+
elog(FATAL,
511+
"pg_local_sendauth: can't do setsockopt: %s\n", strerror(errno));
512+
return;
513+
}
514+
}
515+
#endif
516+
if (port->raddr.sa.sa_family == AF_UNIX)
517+
sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
518+
#endif
496519
status = authident(port);
497520
break;
498521

@@ -676,3 +699,4 @@ map_old_to_new(Port *port, UserAuth old, int status)
676699

677700
return status;
678701
}
702+

src/backend/libpq/hba.c

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.64 2001/08/16 16:24:15 momjian Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.65 2001/08/21 00:33:27 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
1717
#include "postgres.h"
1818

1919
#include <errno.h>
2020
#include <pwd.h>
21-
#include <sys/types.h>
2221
#include <fcntl.h>
23-
#include <sys/socket.h>
22+
#include <sys/types.h>
23+
#include <sys/socket.h> /* for SCM_CREDS */
24+
#ifdef SCM_CREDS
25+
#include <sys/uio.h> /* for struct iovec */
26+
#include <sys/ucred.h>
27+
#endif
2428
#include <netinet/in.h>
2529
#include <arpa/inet.h>
2630
#include <unistd.h>
@@ -876,39 +880,103 @@ ident_unix(int sock, char *ident_user)
876880
{
877881
/* We didn't get a valid credentials struct. */
878882
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
879-
"Could not get valid credentials from the UNIX socket: %s\n",
883+
"ident_unix: error receiving credentials: %s\n",
880884
strerror(errno));
881885
fputs(PQerrormsg, stderr);
882886
pqdebug("%s", PQerrormsg);
883887
return false;
884888
}
885889

886-
/* Convert UID to user login name */
887890
pass = getpwuid(peercred.uid);
888891

889892
if (pass == NULL)
890893
{
891-
/* Error - no username with the given uid */
892894
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
893-
"There is no entry in /etc/passwd with the socket's uid\n");
895+
"ident_unix: unknown local user with uid %d\n",
894896
fputs(PQerrormsg, stderr);
895897
pqdebug("%s", PQerrormsg);
896898
return false;
897899
}
898900

899-
StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX);
901+
StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX+1);
900902

901903
return true;
902904

903-
#else /* not SO_PEERCRED */
905+
#elif defined(SCM_CREDS)
906+
struct msghdr msg;
907+
908+
/* Credentials structure */
909+
#ifndef fc_uid
910+
typedef struct cmsgcred Cred;
911+
#define cruid cmcred_uid
912+
#else
913+
typedef struct fcred Cred;
914+
#define cruid fc_uid
915+
#endif
916+
Cred *cred;
917+
918+
/* Compute size without padding */
919+
char cmsgmem[sizeof(struct cmsghdr) + sizeof(Cred)];
920+
/* Point to start of first structure */
921+
struct cmsghdr *cmsg = (struct cmsghdr *)cmsgmem;
922+
923+
struct iovec iov;
924+
char buf;
925+
struct passwd *pw;
926+
927+
memset(&msg, 0, sizeof(msg));
928+
msg.msg_iov = &iov;
929+
msg.msg_iovlen = 1;
930+
msg.msg_control = (char *)cmsg;
931+
msg.msg_controllen = sizeof(cmsgmem);
932+
memset(cmsg, 0, sizeof(cmsgmem));
933+
934+
/*
935+
* The one character which is received here is not meaningful;
936+
* its purposes is only to make sure that recvmsg() blocks
937+
* long enough for the other side to send its credentials.
938+
*/
939+
iov.iov_base = &buf;
940+
iov.iov_len = 1;
941+
942+
if (recvmsg(sock, &msg, 0) < 0 ||
943+
cmsg->cmsg_len < sizeof(cmsgmem) ||
944+
cmsg->cmsg_type != SCM_CREDS)
945+
{
946+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
947+
"ident_unix: error receiving credentials: %s\n",
948+
strerror(errno));
949+
fputs(PQerrormsg, stderr);
950+
pqdebug("%s", PQerrormsg);
951+
return false;
952+
}
953+
954+
cred = (Cred *)CMSG_DATA(cmsg);
904955

956+
pw = getpwuid(cred->fc_uid);
957+
if (pw == NULL)
958+
{
959+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
960+
"ident_unix: unknown local user with uid %d\n",
961+
cred->fc_uid);
962+
fputs(PQerrormsg, stderr);
963+
pqdebug("%s", PQerrormsg);
964+
return false;
965+
}
966+
967+
StrNCpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX+1);
968+
969+
return true;
970+
971+
#else
905972
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
906-
"IDENT auth is not supported on local connections on this platform\n");
973+
"'ident' auth is not supported on local connections on this platform\n");
907974
fputs(PQerrormsg, stderr);
908975
pqdebug("%s", PQerrormsg);
976+
909977
return false;
910978

911-
#endif /* SO_PEERCRED */
979+
#endif
912980
}
913981

914982
/*

src/backend/libpq/pg_hba.conf.sample

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@
127127
# ident: For TCP/IP connections, authentication is done by contacting
128128
# the ident server on the client host. (CAUTION: this is only
129129
# as secure as the client machine!) On machines that support
130-
# SO_PEERCRED socket requests, this method also works for
131-
# local Unix-domain connections. AUTH_ARGUMENT is required:
132-
# it determines how to map remote user names to Postgres user
133-
# names. The AUTH_ARGUMENT is a map name found in the
134-
# $PGDATA/pg_ident.conf file. The connection is accepted if
135-
# that file contains an entry for this map name with the
130+
# SO_PEERCRED or SCM_CREDS socket requests, this method also
131+
# works for local Unix-domain connections. AUTH_ARGUMENT is
132+
# required: it determines how to map remote user names to
133+
# Postgres user names. The AUTH_ARGUMENT is a map name found
134+
# in the $PGDATA/pg_ident.conf file. The connection is accepted
135+
# if that file contains an entry for this map name with the
136136
# ident-supplied username and the requested Postgres username.
137137
# The special map name "sameuser" indicates an implied map
138138
# (not in pg_ident.conf) that maps each ident username to the

src/include/libpq/pqcomm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $Id: pqcomm.h,v 1.57 2001/08/16 04:27:18 momjian Exp $
12+
* $Id: pqcomm.h,v 1.58 2001/08/21 00:33:27 momjian Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -133,6 +133,7 @@ typedef struct StartupPacket
133133
#define AUTH_REQ_PASSWORD 3 /* Password */
134134
#define AUTH_REQ_CRYPT 4 /* crypt password */
135135
#define AUTH_REQ_MD5 5 /* md5 password */
136+
#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */
136137

137138
typedef uint32 AuthRequest;
138139

src/interfaces/libpq/fe-auth.c

Lines changed: 71 additions & 3 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-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.55 2001/08/17 15:40:07 momjian Exp $
13+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.56 2001/08/21 00:33:27 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -30,6 +30,7 @@
3030

3131
#include "postgres_fe.h"
3232

33+
/* XXX is there a reason these appear before the system defines? */
3334
#include "libpq-fe.h"
3435
#include "libpq-int.h"
3536
#include "fe-auth.h"
@@ -40,6 +41,13 @@
4041
#else
4142
#include <unistd.h>
4243
#include <fcntl.h>
44+
#include <errno.h>
45+
#include <sys/types.h>
46+
#include <sys/socket.h> /* for SCM_CREDS */
47+
#ifdef SCM_CREDS
48+
#include <sys/uio.h> /* for struct iovec */
49+
#include <sys/ucred.h>
50+
#endif
4351
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
4452
#ifndef MAXHOSTNAMELEN
4553
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
@@ -428,6 +436,53 @@ pg_krb5_sendauth(char *PQerrormsg, int sock,
428436

429437
#endif /* KRB5 */
430438

439+
#ifdef SCM_CREDS
440+
static int
441+
pg_local_sendauth(char *PQerrormsg, PGconn *conn)
442+
{
443+
char buf;
444+
struct iovec iov;
445+
struct msghdr msg;
446+
#ifndef fc_uid
447+
/* Prevent padding */
448+
char cmsgmem[sizeof(struct cmsghdr) + sizeof(struct cmsgcred)];
449+
/* Point to start of first structure */
450+
struct cmsghdr *cmsg = (struct cmsghdr *)cmsgmem;
451+
#endif
452+
453+
/*
454+
* The backend doesn't care what we send here, but it wants
455+
* exactly one character to force recvmsg() to block and wait
456+
* for us.
457+
*/
458+
buf = '\0';
459+
iov.iov_base = &buf;
460+
iov.iov_len = 1;
461+
462+
memset(&msg, 0, sizeof(msg));
463+
msg.msg_iov = &iov;
464+
msg.msg_iovlen = 1;
465+
466+
#ifndef fc_uid
467+
/* Create control header, FreeBSD */
468+
msg.msg_control = cmsg;
469+
msg.msg_controllen = sizeof(cmsgmem);
470+
memset(cmsg, 0, sizeof(cmsgmem));
471+
cmsg.hdr.cmsg_len = sizeof(cmsgmem);
472+
cmsg.hdr.cmsg_level = SOL_SOCKET;
473+
cmsg.hdr.cmsg_type = SCM_CREDS;
474+
#endif
475+
476+
if (sendmsg(conn->sock, &msg, 0) == -1)
477+
{
478+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
479+
"pg_local_sendauth: sendmsg: %s\n", strerror(errno));
480+
return STATUS_ERROR;
481+
}
482+
return STATUS_OK;
483+
}
484+
#endif
485+
431486
static int
432487
pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
433488
{
@@ -473,12 +528,13 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
473528
crypt_pwd = crypt(password, salt);
474529
break;
475530
}
476-
default:
531+
case AUTH_REQ_PASSWORD:
477532
/* discard const so we can assign it */
478533
crypt_pwd = (char *)password;
479534
break;
535+
default:
536+
return STATUS_ERROR;
480537
}
481-
482538
ret = pqPacketSend(conn, crypt_pwd, strlen(crypt_pwd) + 1);
483539
if (areq == AUTH_REQ_MD5)
484540
free(crypt_pwd);
@@ -551,6 +607,18 @@ fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
551607
return STATUS_ERROR;
552608
}
553609
break;
610+
611+
case AUTH_REQ_SCM_CREDS:
612+
#ifdef SCM_CREDS
613+
if (pg_local_sendauth(PQerrormsg, conn) != STATUS_OK)
614+
return STATUS_ERROR;
615+
#else
616+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
617+
libpq_gettext("SCM_CRED authentication method not supported\n"));
618+
return STATUS_ERROR;
619+
#endif
620+
break;
621+
554622
default:
555623
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
556624
libpq_gettext("authentication method %u not supported\n"), areq);

src/interfaces/odbc/connection.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,11 @@ CC_connect(ConnectionClass *self, char do_password)
726726
self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
727727
return 0;
728728

729+
case AUTH_REQ_SCM_CREDS:
730+
self->errormsg = "Unix socket credential authentication not supported";
731+
self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
732+
return 0;
733+
729734
default:
730735
self->errormsg = "Unknown authentication type";
731736
self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;

src/interfaces/odbc/connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ typedef enum
9494
#define AUTH_REQ_PASSWORD 3
9595
#define AUTH_REQ_CRYPT 4
9696
#define AUTH_REQ_MD5 5
97+
#define AUTH_REQ_SCM_CREDS 6
9798

9899
/* Startup Packet sizes */
99100
#define SM_DATABASE 64

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