|
10 | 10 | *
|
11 | 11 | *
|
12 | 12 | * 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 $ |
14 | 14 | *
|
15 | 15 | *-------------------------------------------------------------------------
|
16 | 16 | */
|
17 | 17 | #include "postgres.h"
|
18 | 18 |
|
19 | 19 | #include <errno.h>
|
20 | 20 | #include <pwd.h>
|
21 |
| -#include <sys/types.h> |
22 | 21 | #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 |
24 | 28 | #include <netinet/in.h>
|
25 | 29 | #include <arpa/inet.h>
|
26 | 30 | #include <unistd.h>
|
@@ -876,39 +880,103 @@ ident_unix(int sock, char *ident_user)
|
876 | 880 | {
|
877 | 881 | /* We didn't get a valid credentials struct. */
|
878 | 882 | snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
879 |
| - "Could not get valid credentials from the UNIX socket: %s\n", |
| 883 | + "ident_unix: error receiving credentials: %s\n", |
880 | 884 | strerror(errno));
|
881 | 885 | fputs(PQerrormsg, stderr);
|
882 | 886 | pqdebug("%s", PQerrormsg);
|
883 | 887 | return false;
|
884 | 888 | }
|
885 | 889 |
|
886 |
| - /* Convert UID to user login name */ |
887 | 890 | pass = getpwuid(peercred.uid);
|
888 | 891 |
|
889 | 892 | if (pass == NULL)
|
890 | 893 | {
|
891 |
| - /* Error - no username with the given uid */ |
892 | 894 | 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", |
894 | 896 | fputs(PQerrormsg, stderr);
|
895 | 897 | pqdebug("%s", PQerrormsg);
|
896 | 898 | return false;
|
897 | 899 | }
|
898 | 900 |
|
899 |
| - StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX); |
| 901 | + StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX+1); |
900 | 902 |
|
901 | 903 | return true;
|
902 | 904 |
|
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); |
904 | 955 |
|
| 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 |
905 | 972 | 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"); |
907 | 974 | fputs(PQerrormsg, stderr);
|
908 | 975 | pqdebug("%s", PQerrormsg);
|
| 976 | + |
909 | 977 | return false;
|
910 | 978 |
|
911 |
| -#endif /* SO_PEERCRED */ |
| 979 | +#endif |
912 | 980 | }
|
913 | 981 |
|
914 | 982 | /*
|
|
0 commit comments