? src/include/stamp-h
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/runtime.sgml,v
retrieving revision 1.94
diff -w -b -i -B -u -r1.94 runtime.sgml
--- doc/src/sgml/runtime.sgml 2001/11/12 19:19:39 1.94
+++ doc/src/sgml/runtime.sgml 2001/11/16 11:03:05
@@ -1148,6 +1148,48 @@
+ LO_IMP_EXP_DIR (string)
+ LO_IMP_EXP_DIR>>
+ large objects>>
+
+
+ Importing and exporting large objects on the server-side is
+ always a security-problem, because it may allow to read and
+ write files on the server. But in some cases it is neccesary
+ to handle large objects on the server, e.g. when this is done
+ in stored procedures.
+
+
+
+ To minimize the risk, the administrator may pass a directory
+ as parameter, which is the root of all of the files, that
+ can be im- or exported. The passed argument MUST be a directory.
+ To enhance the security, the files to import from or to export
+ to must be regular files. Any other types (directories,
+ block-devices, symbolic-links, etc.) are rejected by the server.
+
+
+
+lo_imp_exp_dir = '/tmp'
+
+
+
+
+
+ The default value for this parameter is
+ '' (empty string). If the value is set to the empty
+ string, importing or exporting is forbidden on server-side.
+
+
+
+ This parameter can be changed in the
+ postgresql.conf
+ configuration file.
+
+
+
+
+
fsync
Index: src/backend/libpq/be-fsstubs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v
retrieving revision 1.59
diff -w -b -i -B -u -r1.59 be-fsstubs.c
--- src/backend/libpq/be-fsstubs.c 2001/06/13 21:44:41 1.59
+++ src/backend/libpq/be-fsstubs.c 2001/11/16 11:03:06
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include "libpq/be-fsstubs.h"
#include "libpq/libpq-fs.h"
@@ -47,6 +48,7 @@
/* [PA] is Pascal André */
+/* [KR] is Klaus Reger */
/*#define FSDB 1*/
#define BUFSIZE 8192
@@ -64,10 +66,16 @@
static MemoryContext fscxt = NULL;
+#define IE_IMPORT 1
+#define IE_EXPORT 2
static int newLOfd(LargeObjectDesc *lobjCookie);
static void deleteLOfd(int fd);
+static int isImpExpOK(char *filename, int ie_type);
+/* externally defined via config-file */
+char *lo_imp_exp_dir;
+
/*****************************************************************************
* File Interfaces for Large Objects
*****************************************************************************/
@@ -359,13 +367,6 @@
LargeObjectDesc *lobj;
Oid lobjOid;
-#ifndef ALLOW_DANGEROUS_LO_FUNCTIONS
- if (!superuser())
- elog(ERROR, "You must have Postgres superuser privilege to use "
- "server-side lo_import().\n\tAnyone can use the "
- "client-side lo_import() provided by libpq.");
-#endif
-
/*
* open the file to be read in
*/
@@ -374,6 +375,16 @@
nbytes = MAXPGPATH - 1;
memcpy(fnamebuf, VARDATA(filename), nbytes);
fnamebuf[nbytes] = '\0';
+
+#ifndef ALLOW_DANGEROUS_LO_FUNCTIONS
+
+ if (!superuser() && !isImpExpOK(fnamebuf, IE_IMPORT))
+ elog(ERROR, "You must have Postgres superuser privilege to use "
+ "server-side lo_import().\n\tAnyone can use the "
+ "client-side lo_import() provided by libpq.");
+#endif
+
+
fd = PathNameOpenFile(fnamebuf, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
elog(ERROR, "lo_import: can't open unix file \"%s\": %m",
@@ -422,8 +433,16 @@
LargeObjectDesc *lobj;
mode_t oumask;
+
+ nbytes = VARSIZE(filename) - VARHDRSZ;
+ if (nbytes >= MAXPGPATH)
+ nbytes = MAXPGPATH - 1;
+ memcpy(fnamebuf, VARDATA(filename), nbytes);
+ fnamebuf[nbytes] = '\0';
+
#ifndef ALLOW_DANGEROUS_LO_FUNCTIONS
- if (!superuser())
+
+ if (!superuser() && !isImpExpOK(fnamebuf, IE_EXPORT))
elog(ERROR, "You must have Postgres superuser privilege to use "
"server-side lo_export().\n\tAnyone can use the "
"client-side lo_export() provided by libpq.");
@@ -443,11 +462,6 @@
* 022. This code used to drop it all the way to 0, but creating
* world-writable export files doesn't seem wise.
*/
- nbytes = VARSIZE(filename) - VARHDRSZ;
- if (nbytes >= MAXPGPATH)
- nbytes = MAXPGPATH - 1;
- memcpy(fnamebuf, VARDATA(filename), nbytes);
- fnamebuf[nbytes] = '\0';
oumask = umask((mode_t) 0022);
fd = PathNameOpenFile(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
umask(oumask);
@@ -566,3 +580,63 @@
{
cookies[fd] = NULL;
}
+
+
+
+/*
+ * isImpExpOK -
+ * checks if file matches the criteria for import/export [KR, 2001-11-15]
+ */
+static int
+isImpExpOK(char *filename,
+ int ie_type)
+{
+ struct stat file_stat;
+ int result = 0;
+ int stat_result;
+
+ /*
+ * When lo_imp_exp_dir is set explicitly in the config-file, then
+ * we are allowed to do this dangerous function
+ */
+ if((strncmp(lo_imp_exp_dir,
+ filename,
+ strlen(lo_imp_exp_dir)) == 0) &&
+ (strlen(lo_imp_exp_dir) > 0))
+ result = 1;
+
+ /*
+ * lo_imp_exp_dir has to be a directory
+ */
+ stat_result = lstat(lo_imp_exp_dir, &file_stat);
+ if(!S_ISDIR(file_stat.st_mode))
+ {
+ result = 0;
+#if FSDB
+ elog(NOTICE, "lo_imp_exp_dir is not a dir");
+#endif
+ }
+
+ /*
+ * filename has to be a regular file
+ */
+ stat_result = lstat(filename, &file_stat);
+ if(!S_ISREG(file_stat.st_mode) || S_ISLNK(file_stat.st_mode))
+ {
+
+ /*
+ * if we want to create a new file, but it does not exist,
+ * everything is OK (for export only)
+ */
+ if(!(ie_type == IE_EXPORT && stat_result != 0 && errno == ENOENT))
+ {
+ result = 0;
+#if FSDB
+ elog(NOTICE, "%s is not a regular file", filename);
+#endif
+ }
+ }
+
+ return result;
+}
+
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.58
diff -w -b -i -B -u -r1.58 guc.c
--- src/backend/utils/misc/guc.c 2001/10/30 05:38:56 1.58
+++ src/backend/utils/misc/guc.c 2001/11/16 11:03:09
@@ -25,6 +25,7 @@
#include "fmgr.h"
#include "libpq/auth.h"
#include "libpq/pqcomm.h"
+#include "libpq/be-fsstubs.h"
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
@@ -556,6 +557,11 @@
{
"dynamic_library_path", PGC_SUSET, &Dynamic_library_path,
"$libdir", NULL, NULL
+ },
+
+ {
+ "lo_imp_exp_dir", PGC_POSTMASTER, &lo_imp_exp_dir,
+ "", NULL, NULL
},
{
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.26
diff -w -b -i -B -u -r1.26 postgresql.conf.sample
--- src/backend/utils/misc/postgresql.conf.sample 2001/09/30 18:57:45 1.26
+++ src/backend/utils/misc/postgresql.conf.sample 2001/11/16 11:03:09
@@ -174,6 +174,7 @@
#
# Misc
#
+#lo_imp_exp_dir = '' # absolute dirname or ''
#dynamic_library_path = '$libdir'
#australian_timezones = false
#authentication_timeout = 60 # min 1, max 600
Index: src/include/libpq/be-fsstubs.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/libpq/be-fsstubs.h,v
retrieving revision 1.15
diff -w -b -i -B -u -r1.15 be-fsstubs.h
--- src/include/libpq/be-fsstubs.h 2001/11/05 17:46:33 1.15
+++ src/include/libpq/be-fsstubs.h 2001/11/16 11:03:12
@@ -47,4 +47,6 @@
*/
extern void lo_commit(bool isCommit);
+extern char *lo_imp_exp_dir;
+
#endif /* BE_FSSTUBS_H */