~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/bin/pg_dump/pg_backup_tar.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-02-05 18:13:52 UTC
  • mfrom: (1.1.10) (10.1.5 oneiric-proposed)
  • Revision ID: package-import@ubuntu.com-20130205181352-3kw4f94ilqklzm7c
Tags: 9.1.8-0ubuntu11.10
* New upstream security/bug fix release: (LP: #1116336)
  - Prevent execution of enum_recv from SQL
    The function was misdeclared, allowing a simple SQL command to crash the
    server.  In principle an attacker might be able to use it to examine the
    contents of server memory.  Our thanks to Sumit Soni (via Secunia SVCRP)
    for reporting this issue. (CVE-2013-0255)
  - See HISTORY/changelog.gz for the other bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
648
648
{
649
649
        lclContext *ctx = (lclContext *) AH->formatData;
650
650
        lclTocEntry *tctx = (lclTocEntry *) te->formatData;
651
 
        char       *tmpCopy;
652
 
        size_t          i,
653
 
                                pos1,
654
 
                                pos2;
 
651
        int                     pos1;
655
652
 
656
653
        if (!tctx->filename)
657
654
                return;
658
655
 
 
656
        /*
 
657
         * If we're writing the special restore.sql script, emit a suitable
 
658
         * command to include each table's data from the corresponding file.
 
659
         *
 
660
         * In the COPY case this is a bit klugy because the regular COPY command
 
661
         * was already printed before we get control.
 
662
         */
659
663
        if (ctx->isSpecialScript)
660
664
        {
661
 
                if (!te->copyStmt)
662
 
                        return;
663
 
 
664
 
                /* Abort the default COPY */
665
 
                ahprintf(AH, "\\.\n");
666
 
 
667
 
                /* Get a copy of the COPY statement and clean it up */
668
 
                tmpCopy = strdup(te->copyStmt);
669
 
                for (i = 0; i < strlen(tmpCopy); i++)
670
 
                        tmpCopy[i] = pg_tolower((unsigned char) tmpCopy[i]);
671
 
 
672
 
                /*
673
 
                 * This is very nasty; we don't know if the archive used WITH OIDS, so
674
 
                 * we search the string for it in a paranoid sort of way.
675
 
                 */
676
 
                if (strncmp(tmpCopy, "copy ", 5) != 0)
677
 
                        die_horribly(AH, modulename,
678
 
                                                 "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
679
 
 
680
 
                pos1 = 5;
681
 
                for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
682
 
                        if (tmpCopy[pos1] != ' ')
683
 
                                break;
684
 
 
685
 
                if (tmpCopy[pos1] == '"')
686
 
                        pos1 += 2;
687
 
 
688
 
                pos1 += strlen(te->tag);
689
 
 
690
 
                for (pos2 = pos1; pos2 < strlen(tmpCopy); pos2++)
691
 
                        if (strncmp(&tmpCopy[pos2], "from stdin", 10) == 0)
692
 
                                break;
693
 
 
694
 
                if (pos2 >= strlen(tmpCopy))
695
 
                        die_horribly(AH, modulename,
696
 
                                                 "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
697
 
                                                 tmpCopy, (unsigned long) pos1);
698
 
 
699
 
                ahwrite(tmpCopy, 1, pos2, AH);  /* 'copy "table" [with oids]' */
700
 
                ahprintf(AH, " from '$$PATH$$/%s' %s", tctx->filename, &tmpCopy[pos2 + 10]);
 
665
                if (te->copyStmt)
 
666
                {
 
667
                        /* Abort the COPY FROM stdin */
 
668
                        ahprintf(AH, "\\.\n");
 
669
 
 
670
                        /*
 
671
                         * The COPY statement should look like "COPY ... FROM stdin;\n",
 
672
                         * see dumpTableData().
 
673
                         */
 
674
                        pos1 = (int) strlen(te->copyStmt) - 13;
 
675
                        if (pos1 < 6 || strncmp(te->copyStmt, "COPY ", 5) != 0 ||
 
676
                                strcmp(te->copyStmt + pos1, " FROM stdin;\n") != 0)
 
677
                                die_horribly(AH, modulename,
 
678
                                                         "unexpected COPY statement syntax: \"%s\"\n",
 
679
                                                         te->copyStmt);
 
680
 
 
681
                        /* Emit all but the FROM part ... */
 
682
                        ahwrite(te->copyStmt, 1, pos1, AH);
 
683
                        /* ... and insert modified FROM */
 
684
                        ahprintf(AH, " FROM '$$PATH$$/%s';\n\n", tctx->filename);
 
685
                }
 
686
                else
 
687
                {
 
688
                        /* --inserts mode, no worries, just include the data file */
 
689
                        ahprintf(AH, "\\i $$PATH$$/%s\n\n", tctx->filename);
 
690
                }
701
691
 
702
692
                return;
703
693
        }
843
833
                 * if the files have been extracted.
844
834
                 */
845
835
                th = tarOpen(AH, "restore.sql", 'w');
846
 
                tarPrintf(AH, th, "create temporary table pgdump_restore_path(p text);\n");
 
836
 
847
837
                tarPrintf(AH, th, "--\n"
848
838
                                  "-- NOTE:\n"
849
839
                                  "--\n"
850
840
                                  "-- File paths need to be edited. Search for $$PATH$$ and\n"
851
841
                                  "-- replace it with the path to the directory containing\n"
852
842
                                  "-- the extracted data files.\n"
853
 
                                  "--\n"
854
 
                                  "-- Edit the following to match the path where the\n"
855
 
                                  "-- tar archive has been extracted.\n"
856
843
                                  "--\n");
857
 
                tarPrintf(AH, th, "insert into pgdump_restore_path values('/tmp');\n\n");
858
844
 
859
845
                AH->CustomOutPtr = _scriptOut;
860
846
 
876
862
 
877
863
                tarClose(AH, th);
878
864
 
879
 
                /* Add a block of NULLs since it's de-rigeur. */
880
 
                for (i = 0; i < 512; i++)
 
865
                ctx->isSpecialScript = 0;
 
866
 
 
867
                /*
 
868
                 * EOF marker for tar files is two blocks of NULLs.
 
869
                 */
 
870
                for (i = 0; i < 512 * 2; i++)
881
871
                {
882
872
                        if (fputc(0, ctx->tarFH) == EOF)
883
873
                                die_horribly(AH, modulename,
1028
1018
        int                     i,
1029
1019
                                sum;
1030
1020
 
1031
 
        sum = 0;
 
1021
        /*
 
1022
         * Per POSIX, the checksum is the simple sum of all bytes in the header,
 
1023
         * treating the bytes as unsigned, and treating the checksum field (at
 
1024
         * offset 148) as though it contained 8 spaces.
 
1025
         */
 
1026
        sum = 8 * ' ';                          /* presumed value for checksum field */
1032
1027
        for (i = 0; i < 512; i++)
1033
1028
                if (i < 148 || i >= 156)
1034
1029
                        sum += 0xFF & header[i];
1035
 
        return sum + 256;                       /* Assume 8 blanks in checksum field */
 
1030
        return sum;
1036
1031
}
1037
1032
 
1038
1033
bool
1046
1041
        if (sum != chk)
1047
1042
                return false;
1048
1043
 
1049
 
        /* POSIX format */
1050
 
        if (strncmp(&header[257], "ustar00", 7) == 0)
1051
 
                return true;
1052
 
        /* older format */
1053
 
        if (strncmp(&header[257], "ustar  ", 7) == 0)
 
1044
        /* POSIX tar format */
 
1045
        if (memcmp(&header[257], "ustar\0", 6) == 0 &&
 
1046
                memcmp(&header[263], "00", 2) == 0)
 
1047
                return true;
 
1048
        /* GNU tar format */
 
1049
        if (memcmp(&header[257], "ustar  \0", 8) == 0)
 
1050
                return true;
 
1051
        /* not-quite-POSIX format written by pre-9.3 pg_dump */
 
1052
        if (memcmp(&header[257], "ustar00\0", 8) == 0)
1054
1053
                return true;
1055
1054
 
1056
1055
        return false;