*) inet_(client|server)_(addr|port)() and necessary documentation for
the four functions.
*) area(PATH) and documentation.
*) Checks for TEMP privs when creating objects in the temp schema
(checks for any object created in a temp namespace).
*) With the above change, current_user is now being used to check if
CREATE TEMP TABLE should succeed.
[ and it gets weirder from there ]

Er, what?

Could we possibly have this separated into multiple patches with some
coherent purpose to each?

Sure.

patch-network.txt contains the following bits:

*) inet_(client|server)_(addr|port)() and necessary documentation for the four functions.


Also, please justify the temp-related changes.  I was not aware that we
had any breakage there.

patch-tmp-schema.txt contains the following bits:

*) Changes pg_namespace_aclmask() so that the superuser is always able to create objects in the temp namespace.
*) Changes pg_namespace_aclmask() so that if this is a temp namespace, objects are only allowed to be created in the temp namespace if the user has TEMP privs on the database. This encompasses all object creation, not just TEMP tables.
*) InitTempTableNamespace() checks to see if the current user, not the session user, has access to create a temp namespace.


The first two changes are necessary to support the third change. Now it's possible to revoke all temp table privs from non-super users and limiting all creation of temp tables/schemas via a function that's executed with elevated privs (security definer). Before this change, it was not possible to have a setuid function to create a temp table/schema if the session user had no TEMP privs.

Originally you'd brought up some concerns about security problems, but this patch I believe addresses all of your prior concerns.


patch-area-path.txt contains:

*) Can now determine the area of a closed path.


patch-dfmgr.txt contains:

*) Small tweak to add the library path that's being expanded.

I was using $lib/foo.so and couldn't easily figure out what the error message, "invalid macro name in dynamic library path" meant without looking through the source code. With the path in there, at least I know where to start looking in my config file.


-sc

Index: src/backend/utils/adt/geo_ops.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/geo_ops.c,v
retrieving revision 1.84
diff -u -r1.84 geo_ops.c
--- src/backend/utils/adt/geo_ops.c     12 May 2004 22:38:44 -0000      1.84
+++ src/backend/utils/adt/geo_ops.c     18 May 2004 18:59:40 -0000
@@ -1313,6 +1313,27 @@
  *---------------------------------------------------------*/
 
 Datum
+path_area(PG_FUNCTION_ARGS)
+{
+       PATH    *path = PG_GETARG_PATH_P(0);
+       double  area = 0.0;
+       int i,j;
+
+       if (!path->closed)
+               PG_RETURN_NULL();
+
+       for (i = 0; i < path->npts; i++) {
+               j = (i + 1) % path->npts;
+               area += path->p[i].x * path->p[j].y;
+               area -= path->p[i].y * path->p[j].x;
+       }
+
+       area *= 0.5;
+       PG_RETURN_FLOAT8(area < 0.0 ? -area : area);
+}
+
+
+Datum
 path_in(PG_FUNCTION_ARGS)
 {
        char       *str = PG_GETARG_CSTRING(0);
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.329
diff -u -r1.329 pg_proc.h
--- src/include/catalog/pg_proc.h       14 May 2004 21:42:28 -0000      1.329
+++ src/include/catalog/pg_proc.h       18 May 2004 18:59:41 -0000
@@ -1259,6 +1259,8 @@
 DESCR("box height");
 DATA(insert OID = 978 (  box_distance     PGNSP PGUID 12 f f t f i 2 701 "603 603" 
_null_  box_distance - _null_ ));
 DESCR("distance between boxes");
+DATA(insert OID = 979 (  area                     PGNSP PGUID 12 f f t f i 1 701 
"602" _null_  path_area - _null_ ));
+DESCR("area of a closed path");
 DATA(insert OID = 980 (  box_intersect    PGNSP PGUID 12 f f t f i 2 603 "603 603" 
_null_  box_intersect - _null_ ));
 DESCR("box intersection (another box)");
 DATA(insert OID = 981 (  diagonal                 PGNSP PGUID 12 f f t f i 1 601 
"603" _null_  box_diagonal - _null_ ));
Index: src/include/utils/geo_decls.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/geo_decls.h,v
retrieving revision 1.43
diff -u -r1.43 geo_decls.h
--- src/include/utils/geo_decls.h       29 Nov 2003 22:41:15 -0000      1.43
+++ src/include/utils/geo_decls.h       18 May 2004 18:59:41 -0000
@@ -305,6 +305,7 @@
 extern Datum box_div(PG_FUNCTION_ARGS);
 
 /* public path routines */
+extern Datum path_area(PG_FUNCTION_ARGS);
 extern Datum path_in(PG_FUNCTION_ARGS);
 extern Datum path_out(PG_FUNCTION_ARGS);
 extern Datum path_recv(PG_FUNCTION_ARGS);
Index: src/backend/utils/fmgr/dfmgr.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/fmgr/dfmgr.c,v
retrieving revision 1.72
diff -u -r1.72 dfmgr.c
--- src/backend/utils/fmgr/dfmgr.c      17 May 2004 14:35:31 -0000      1.72
+++ src/backend/utils/fmgr/dfmgr.c      18 May 2004 18:59:40 -0000
@@ -350,7 +350,7 @@
                strncmp(name, "$libdir", strlen("$libdir")) != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_NAME),
-                                errmsg("invalid macro name in dynamic library 
path")));
+                                errmsg("invalid macro name in dynamic library path: 
%s", name)));
 
        ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
 
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/hba.c,v
retrieving revision 1.120
diff -u -r1.120 hba.c
--- src/backend/libpq/hba.c     2 Feb 2004 16:58:30 -0000       1.120
+++ src/backend/libpq/hba.c     18 May 2004 18:59:38 -0000
@@ -1296,8 +1296,11 @@
        hints.ai_addr = NULL;
        hints.ai_next = NULL;
        rc = getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
-       if (rc || !ident_serv)
+       if (rc || !ident_serv) {
+               if (ident_serv)
+                       freeaddrinfo_all(hints.ai_family, ident_serv);
                return false;                   /* we don't expect this to happen */
+       }
 
        hints.ai_flags = AI_NUMERICHOST;
        hints.ai_family = local_addr.addr.ss_family;
@@ -1308,8 +1311,11 @@
        hints.ai_addr = NULL;
        hints.ai_next = NULL;
        rc = getaddrinfo_all(local_addr_s, NULL, &hints, &la);
-       if (rc || !la)
+       if (rc || !la) {
+               if (la)
+                       freeaddrinfo_all(hints.ai_family, la);
                return false;                   /* we don't expect this to happen */
+       }
 
        sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
                                         ident_serv->ai_protocol);
Index: src/backend/libpq/ip.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v
retrieving revision 1.25
diff -u -r1.25 ip.c
--- src/backend/libpq/ip.c      24 Apr 2004 20:10:34 -0000      1.25
+++ src/backend/libpq/ip.c      18 May 2004 18:59:38 -0000
@@ -73,11 +73,11 @@
        *result = NULL;
 
 #ifdef HAVE_UNIX_SOCKETS
-       if (hintp != NULL && hintp->ai_family == AF_UNIX)
+       if (hintp->ai_family == AF_UNIX)
                return getaddrinfo_unix(servname, hintp, result);
 #endif
 
-       /* NULL has special meaning to getaddrinfo */
+       /* NULL has special meaning to getaddrinfo(). */
        return getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
                                           servname, hintp, result);
 }
Index: src/backend/libpq/pqcomm.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/pqcomm.c,v
retrieving revision 1.168
diff -u -r1.168 pqcomm.c
--- src/backend/libpq/pqcomm.c  12 Dec 2003 18:45:08 -0000      1.168
+++ src/backend/libpq/pqcomm.c  18 May 2004 18:59:38 -0000
@@ -251,7 +251,8 @@
                        ereport(LOG,
                         (errmsg("could not translate service \"%s\" to address: %s",
                                         service, gai_strerror(ret))));
-               freeaddrinfo_all(hint.ai_family, addrs);
+               if (addrs)
+                       freeaddrinfo_all(hint.ai_family, addrs);
                return STATUS_ERROR;
        }
 
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.269
diff -u -r1.269 fe-connect.c
--- src/interfaces/libpq/fe-connect.c   24 Mar 2004 03:44:59 -0000      1.269
+++ src/interfaces/libpq/fe-connect.c   18 May 2004 18:59:42 -0000
@@ -945,7 +945,8 @@
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("could not 
translate Unix-domain socket path \"%s\" to address: %s\n"),
                                                          portstr, gai_strerror(ret));
-               freeaddrinfo_all(hint.ai_family, addrs);
+               if (addrs)
+                       freeaddrinfo_all(hint.ai_family, addrs);
                goto connect_errReturn;
        }
 
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.388
diff -u -r1.388 postmaster.c
--- src/backend/postmaster/postmaster.c 17 May 2004 14:35:29 -0000      1.388
+++ src/backend/postmaster/postmaster.c 18 May 2004 19:24:37 -0000
@@ -2471,10 +2471,14 @@
                                                remote_port, sizeof(remote_port),
                                   (log_hostname ? 0 : NI_NUMERICHOST) | 
NI_NUMERICSERV))
        {
-               getnameinfo_all(&port->raddr.addr, port->raddr.salen,
+               int ret = getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                                remote_host, sizeof(remote_host),
                                                remote_port, sizeof(remote_port),
                                                NI_NUMERICHOST | NI_NUMERICSERV);
+               if (ret)
+                       ereport(WARNING,
+                               (errmsg("getnameinfo_all() failed: %s",
+                                       gai_strerror(ret))));
        }
        snprintf(remote_ps_data, sizeof(remote_ps_data),
                         remote_port[0] == '\0' ? "%s" : "%s(%s)",
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/func.sgml,v
retrieving revision 1.202
diff -u -r1.202 func.sgml
--- doc/src/sgml/func.sgml      14 May 2004 21:42:27 -0000      1.202
+++ doc/src/sgml/func.sgml      18 May 2004 18:59:37 -0000
@@ -6593,6 +6593,30 @@
       </row>
 
       <row>
+       <entry><function>inet_client_addr</function></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the remote connection</entry>
+      </row>
+
+      <row>
+       <entry><function>inet_client_port</function></entry>
+       <entry><type>int4</type></entry>
+       <entry>port of the remote connection</entry>
+      </row>
+
+      <row>
+       <entry><function>inet_server_addr</function></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the local connection</entry>
+      </row>
+
+      <row>
+       <entry><function>inet_server_port</function></entry>
+       <entry><type>int4</type></entry>
+       <entry>port of the local connection</entry>
+      </row>
+
+      <row>
        <entry><function>session_user</function></entry>
        <entry><type>name</type></entry>
        <entry>session user name</entry>
@@ -6646,6 +6670,17 @@
      they must be called without trailing parentheses.
     </para>
    </note>
+
+   <para>
+     <function>inet_client_addr</function> and
+     <function>inet_server_addr</function> return the IPv4 or IPv6 (if
+     configured) address of the remote or local host connecting to the
+     database, respectively.  <function>inet_client_port</function>
+     and <function>inet_server_port</function> return the port number
+     of the remote or local host connecting to the database,
+     respectively.  If the connection is not a network connection,
+     these functions will return <literal>NULL</literal>.
+   </para>
 
    <para>
     <function>current_schema</function> returns the name of the schema that is
Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/network.c,v
retrieving revision 1.49
diff -u -r1.49 network.c
--- src/backend/utils/adt/network.c     1 Dec 2003 18:50:19 -0000       1.49
+++ src/backend/utils/adt/network.c     18 May 2004 18:59:40 -0000
@@ -14,7 +14,10 @@
 #include <arpa/inet.h>
 
 #include "catalog/pg_type.h"
+#include "libpq/ip.h"
+#include "libpq/libpq-be.h"
 #include "libpq/pqformat.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/inet.h"
 
@@ -129,6 +132,110 @@
 
        PG_RETURN_INET_P(network_in(src, 1));
 }
+
+/* INET that the client is connecting from */
+Datum
+inet_client_addr(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->raddr.addr.ss_family) {
+       case AF_INET:
+#ifdef HAVE_IPV6
+       case AF_INET6:
+#endif
+               break;
+       default:
+               PG_RETURN_NULL();
+       }
+
+       PG_RETURN_INET_P(network_in(port->remote_host, 0));
+}
+
+
+/* port that the client is connecting from */
+Datum
+inet_client_port(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INT32(DirectFunctionCall1(int4in, 
CStringGetDatum(port->remote_port)));
+}
+
+
+/* server INET that the client connected to */
+Datum
+inet_server_addr(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+       char    local_host[NI_MAXHOST];
+       int     ret;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->laddr.addr.ss_family) {
+       case AF_INET:
+#ifdef HAVE_IPV6
+       case AF_INET6:
+#endif
+         break;
+       default:
+               PG_RETURN_NULL();
+       }
+
+       local_host[0] = '\0';
+
+       ret = getnameinfo_all(&port->laddr.addr, port->laddr.salen,
+                             local_host, sizeof(local_host),
+                             NULL, 0,
+                             NI_NUMERICHOST | NI_NUMERICSERV);
+       if (ret)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INET_P(network_in(local_host, 0));
+}
+
+
+/* port that the server accepted the connection on */
+Datum
+inet_server_port(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+       char    local_port[NI_MAXSERV];
+       int     ret;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->laddr.addr.ss_family) {
+       case AF_INET:
+#ifdef HAVE_IPV6
+       case AF_INET6:
+#endif
+         break;
+       default:
+               PG_RETURN_NULL();
+       }
+
+       local_port[0] = '\0';
+
+       ret = getnameinfo_all(&port->laddr.addr, port->laddr.salen,
+                             NULL, 0,
+                             local_port, sizeof(local_port),
+                             NI_NUMERICHOST | NI_NUMERICSERV);
+       if (ret)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INT32(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
+}
+
 
 /*
  *     INET address output function.
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.329
diff -u -r1.329 pg_proc.h
--- src/include/catalog/pg_proc.h       14 May 2004 21:42:28 -0000      1.329
+++ src/include/catalog/pg_proc.h       18 May 2004 18:59:41 -0000
@@ -2343,6 +2345,15 @@
 DESCR("I/O");
 DATA(insert OID = 911 (  inet_out                      PGNSP PGUID 12 f f t f i 1 
2275 "869" _null_  inet_out - _null_ ));
 DESCR("I/O");
+
+DATA(insert OID = 912 (  inet_client_addr              PGNSP PGUID 12 f f f f s 0 869 
"" _null_  inet_client_addr - _null_ ));
+DESCR("Returns the INET address of the client connected to the backend");
+DATA(insert OID = 913 (  inet_client_port              PGNSP PGUID 12 f f f f s 0 23 
"" _null_  inet_client_port - _null_ ));
+DESCR("Returns the client's port number for this connection");
+DATA(insert OID = 914 (  inet_server_addr              PGNSP PGUID 12 f f f f s 0 869 
"" _null_  inet_server_addr - _null_ ));
+DESCR("Returns the INET address that the backend is using to service the connection");
+DATA(insert OID = 915 (  inet_server_port              PGNSP PGUID 12 f f f f s 0 23 
"" _null_  inet_server_port - _null_ ));
+DESCR("Returns the servers's port number for this connection");
 
 /* for cidr type support */
 DATA(insert OID = 1267 (  cidr_in                      PGNSP PGUID 12 f f t f i 1 650 
"2275" _null_  cidr_in - _null_ ));
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.238
diff -u -r1.238 builtins.h
--- src/include/utils/builtins.h        14 May 2004 21:42:30 -0000      1.238
+++ src/include/utils/builtins.h        18 May 2004 18:59:41 -0000
@@ -645,6 +645,10 @@
                          void *dst, size_t size);
 
 /* network.c */
+extern Datum inet_client_addr(PG_FUNCTION_ARGS);
+extern Datum inet_client_port(PG_FUNCTION_ARGS);
+extern Datum inet_server_addr(PG_FUNCTION_ARGS);
+extern Datum inet_server_port(PG_FUNCTION_ARGS);
 extern Datum inet_in(PG_FUNCTION_ARGS);
 extern Datum inet_out(PG_FUNCTION_ARGS);
 extern Datum inet_recv(PG_FUNCTION_ARGS);
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/catalog/aclchk.c,v
retrieving revision 1.98
diff -u -r1.98 aclchk.c
--- src/backend/catalog/aclchk.c        11 May 2004 17:36:12 -0000      1.98
+++ src/backend/catalog/aclchk.c        18 May 2004 18:59:37 -0000
@@ -1342,16 +1342,26 @@
        bool            isNull;
        Acl                *acl;
 
-       /*
-        * If we have been assigned this namespace as a temp namespace, assume
-        * we have all grantable privileges on it.
-        */
-       if (isTempNamespace(nsp_oid))
-               return mask;
-
        /* Superusers bypass all permission checking. */
        if (superuser_arg(userid))
                return mask;
+
+       /*
+        * If we have been assigned this namespace as a temp
+        * namespace, check to make sure we have CREATE permissions on
+        * the database.
+        *
+        * Instead of returning ACLCHECK_NO_PRIV, should we return via
+        * ereport() with a message about trying to create an object
+        * in a TEMP namespace when GetUserId() doesn't have perms?
+        */
+       if (isTempNamespace(nsp_oid)) {
+         if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
+                                  ACL_CREATE_TEMP) == ACLCHECK_OK)
+           return ACLCHECK_OK;
+         else
+           return ACLCHECK_NO_PRIV;
+       }
 
        /*
         * Get the schema's ACL from pg_namespace
Index: src/backend/catalog/namespace.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/catalog/namespace.c,v
retrieving revision 1.63
diff -u -r1.63 namespace.c
--- src/backend/catalog/namespace.c     13 Feb 2004 01:08:20 -0000      1.63
+++ src/backend/catalog/namespace.c     18 May 2004 18:59:38 -0000
@@ -1640,11 +1640,11 @@
         * tables.      We use a nonstandard error message here since
         * "databasename: permission denied" might be a tad cryptic.
         *
-        * Note we apply the check to the session user, not the currently active
-        * userid, since we are not going to change our minds about temp table
-        * availability during the session.
+        * ACL_CREATE_TEMP perms are also checked in
+        * pg_namespace_aclcheck() that way only users who have TEMP
+        * perms can create objects.
         */
-       if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
+       if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
                                                         ACL_CREATE_TEMP) != 
ACLCHECK_OK)
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),


--
Sean Chittenden
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to