| | @@ -31,25 +31,57 @@ |
| 31 | 31 | */ |
| 32 | 32 | #include "config.h" |
| 33 | 33 | #if defined(_WIN32) |
| 34 | 34 | # if USE_SEE |
| 35 | 35 | # include <windows.h> |
| 36 | +# define GETPID (int)GetCurrentProcessId |
| 36 | 37 | # endif |
| 37 | 38 | #else |
| 38 | 39 | # include <pwd.h> |
| 40 | +# if USE_SEE |
| 41 | +# define GETPID getpid |
| 42 | +# endif |
| 39 | 43 | #endif |
| 40 | 44 | #if USE_SEE && !defined(SQLITE_HAS_CODEC) |
| 41 | 45 | # define SQLITE_HAS_CODEC |
| 46 | +#endif |
| 47 | +#if USE_SEE && defined(__linux__) |
| 48 | +# include <sys/uio.h> |
| 42 | 49 | #endif |
| 43 | 50 | #include <sqlite3.h> |
| 44 | 51 | #include <sys/types.h> |
| 45 | 52 | #include <sys/stat.h> |
| 46 | 53 | #include <unistd.h> |
| 47 | 54 | #include <time.h> |
| 55 | + |
| 56 | +/* BUGBUG: This (PID_T) does not work inside of INTERFACE block. */ |
| 57 | +#if USE_SEE |
| 58 | +#if defined(_WIN32) |
| 59 | +typedef DWORD PID_T; |
| 60 | +#else |
| 61 | +typedef pid_t PID_T; |
| 62 | +#endif |
| 63 | +#endif |
| 64 | + |
| 48 | 65 | #include "db.h" |
| 49 | 66 | |
| 50 | 67 | #if INTERFACE |
| 68 | +/* |
| 69 | +** Type definitions used for handling the saved encryption key for SEE. |
| 70 | +*/ |
| 71 | +#if !defined(_WIN32) |
| 72 | +typedef void *LPVOID; |
| 73 | +typedef size_t SIZE_T; |
| 74 | +#endif |
| 75 | + |
| 76 | +/* |
| 77 | +** Operations for db_maybe_handle_saved_encryption_key_for_process, et al. |
| 78 | +*/ |
| 79 | +#define SEE_KEY_READ ((int)0) |
| 80 | +#define SEE_KEY_WRITE ((int)1) |
| 81 | +#define SEE_KEY_ZERO ((int)2) |
| 82 | + |
| 51 | 83 | /* |
| 52 | 84 | ** An single SQL statement is represented as an instance of the following |
| 53 | 85 | ** structure. |
| 54 | 86 | */ |
| 55 | 87 | struct Stmt { |
| | @@ -1539,11 +1571,30 @@ |
| 1539 | 1571 | static char *zSavedKey = 0; |
| 1540 | 1572 | |
| 1541 | 1573 | /* |
| 1542 | 1574 | ** This is the size of the saved database encryption key, in bytes. |
| 1543 | 1575 | */ |
| 1544 | | -size_t savedKeySize = 0; |
| 1576 | +static size_t savedKeySize = 0; |
| 1577 | + |
| 1578 | +/* |
| 1579 | +** This function returns non-zero if there is a saved database encryption |
| 1580 | +** key available. |
| 1581 | +*/ |
| 1582 | +int db_have_saved_encryption_key(){ |
| 1583 | + return db_is_valid_saved_encryption_key(zSavedKey, savedKeySize); |
| 1584 | +} |
| 1585 | + |
| 1586 | +/* |
| 1587 | +** This function returns non-zero if the specified saved database encryption |
| 1588 | +** key is valid. |
| 1589 | +*/ |
| 1590 | +int db_is_valid_saved_encryption_key(const char *p, size_t n){ |
| 1591 | + if( p==0 ) return 0; |
| 1592 | + if( n==0 ) return 0; |
| 1593 | + if( p[0]==0 ) return 0; |
| 1594 | + return 1; |
| 1595 | +} |
| 1545 | 1596 | |
| 1546 | 1597 | /* |
| 1547 | 1598 | ** This function returns the saved database encryption key -OR- zero if |
| 1548 | 1599 | ** no database encryption key is saved. |
| 1549 | 1600 | */ |
| | @@ -1556,10 +1607,36 @@ |
| 1556 | 1607 | ** -OR- zero if no database encryption key is saved. |
| 1557 | 1608 | */ |
| 1558 | 1609 | size_t db_get_saved_encryption_key_size(){ |
| 1559 | 1610 | return savedKeySize; |
| 1560 | 1611 | } |
| 1612 | + |
| 1613 | +/* |
| 1614 | +** This function arranges for the saved database encryption key buffer |
| 1615 | +** to be allocated and then sets up the environment variable to allow |
| 1616 | +** a child process to initialize it with the actual database encryption |
| 1617 | +** key. |
| 1618 | +*/ |
| 1619 | +void db_setup_for_saved_encryption_key(){ |
| 1620 | + void *p = NULL; |
| 1621 | + size_t n = 0; |
| 1622 | + size_t pageSize = 0; |
| 1623 | + Blob pidKey; |
| 1624 | + |
| 1625 | + assert( !db_have_saved_encryption_key() ); |
| 1626 | + db_unsave_encryption_key(); |
| 1627 | + fossil_get_page_size(&pageSize); |
| 1628 | + assert( pageSize>0 ); |
| 1629 | + p = fossil_secure_alloc_page(&n); |
| 1630 | + assert( p!=NULL ); |
| 1631 | + assert( n==pageSize ); |
| 1632 | + blob_zero(&pidKey); |
| 1633 | + blob_appendf(&pidKey, "%lu:%p:%u", (unsigned long)GETPID(), p, n); |
| 1634 | + fossil_setenv("FOSSIL_SEE_PID_KEY", blob_str(&pidKey)); |
| 1635 | + zSavedKey = p; |
| 1636 | + savedKeySize = n; |
| 1637 | +} |
| 1561 | 1638 | |
| 1562 | 1639 | /* |
| 1563 | 1640 | ** This function arranges for the database encryption key to be securely |
| 1564 | 1641 | ** saved in non-pagable memory (on platforms where this is possible). |
| 1565 | 1642 | */ |
| | @@ -1569,10 +1646,11 @@ |
| 1569 | 1646 | void *p = NULL; |
| 1570 | 1647 | size_t n = 0; |
| 1571 | 1648 | size_t pageSize = 0; |
| 1572 | 1649 | size_t blobSize = 0; |
| 1573 | 1650 | |
| 1651 | + assert( !db_have_saved_encryption_key() ); |
| 1574 | 1652 | blobSize = blob_size(pKey); |
| 1575 | 1653 | if( blobSize==0 ) return; |
| 1576 | 1654 | fossil_get_page_size(&pageSize); |
| 1577 | 1655 | assert( pageSize>0 ); |
| 1578 | 1656 | if( blobSize>pageSize ){ |
| | @@ -1599,11 +1677,11 @@ |
| 1599 | 1677 | |
| 1600 | 1678 | /* |
| 1601 | 1679 | ** This function sets the saved database encryption key to the specified |
| 1602 | 1680 | ** string value, allocating or freeing the underlying memory if needed. |
| 1603 | 1681 | */ |
| 1604 | | -void db_set_saved_encryption_key( |
| 1682 | +static void db_set_saved_encryption_key( |
| 1605 | 1683 | Blob *pKey |
| 1606 | 1684 | ){ |
| 1607 | 1685 | if( zSavedKey!=NULL ){ |
| 1608 | 1686 | size_t blobSize = blob_size(pKey); |
| 1609 | 1687 | if( blobSize==0 ){ |
| | @@ -1619,25 +1697,213 @@ |
| 1619 | 1697 | }else{ |
| 1620 | 1698 | db_save_encryption_key(pKey); |
| 1621 | 1699 | } |
| 1622 | 1700 | } |
| 1623 | 1701 | |
| 1702 | +/* |
| 1703 | +** WEBPAGE: setseekey |
| 1704 | +** |
| 1705 | +** Sets the sets the saved database encryption key to one that gets passed |
| 1706 | +** via the "key" query string parameter. If the saved database encryption |
| 1707 | +** key has already been set, does nothing. This web page does not produce |
| 1708 | +** any output on success or failure. |
| 1709 | +** |
| 1710 | +** Query parameters: |
| 1711 | +** |
| 1712 | +** key The string to set as the saved database encryption |
| 1713 | +** key. |
| 1714 | +*/ |
| 1715 | +void db_set_see_key_page(void){ |
| 1716 | + Blob key; |
| 1717 | + const char *zKey; |
| 1718 | + if( db_have_saved_encryption_key() ){ |
| 1719 | + fossil_errorlog("SEE: encryption key was already set\n"); |
| 1720 | + return; |
| 1721 | + } |
| 1722 | + zKey = P("key"); |
| 1723 | + blob_init(&key, 0, 0); |
| 1724 | + if( zKey!=0 ){ |
| 1725 | + PID_T processId; |
| 1726 | + blob_set(&key, zKey); |
| 1727 | + db_set_saved_encryption_key(&key); |
| 1728 | + processId = db_maybe_handle_saved_encryption_key_for_process( |
| 1729 | + SEE_KEY_WRITE |
| 1730 | + ); |
| 1731 | + fossil_errorlog("SEE: set encryption key for process %lu, length %u\n", |
| 1732 | + (unsigned long)processId, blob_size(&key)); |
| 1733 | + }else{ |
| 1734 | + fossil_errorlog("SEE: no encryption key specified\n"); |
| 1735 | + } |
| 1736 | + blob_reset(&key); |
| 1737 | +} |
| 1738 | + |
| 1739 | +/* |
| 1740 | +** WEBPAGE: unsetseekey |
| 1741 | +** |
| 1742 | +** Unsets the saved database encryption key to zeros. If the saved database |
| 1743 | +** encryption key has already been set, does nothing. This web page does not |
| 1744 | +** produce any output on success or failure. |
| 1745 | +*/ |
| 1746 | +void db_unset_see_key_page(void){ |
| 1747 | + PID_T processId; |
| 1748 | + login_check_credentials(); |
| 1749 | + if( !g.perm.Setup ){ login_needed(0); return; } |
| 1750 | + processId = db_maybe_handle_saved_encryption_key_for_process( |
| 1751 | + SEE_KEY_ZERO |
| 1752 | + ); |
| 1753 | + fossil_errorlog("SEE: unset encryption key for process %lu\n", |
| 1754 | + (unsigned long)processId); |
| 1755 | +} |
| 1756 | + |
| 1757 | +/* |
| 1758 | +** This function reads the saved database encryption key from the |
| 1759 | +** specified Fossil parent process. This is only necessary (or |
| 1760 | +** functional) on Windows or Linux. |
| 1761 | +*/ |
| 1762 | +static void db_read_saved_encryption_key_from_process( |
| 1763 | + PID_T processId, /* Identifier for Fossil parent process. */ |
| 1764 | + LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ |
| 1765 | + SIZE_T nSize /* Size of saved key buffer in the parent process. */ |
| 1766 | +){ |
| 1767 | + void *p = NULL; |
| 1768 | + size_t n = 0; |
| 1769 | + size_t pageSize = 0; |
| 1770 | + |
| 1771 | + fossil_get_page_size(&pageSize); |
| 1772 | + assert( pageSize>0 ); |
| 1773 | + if( nSize>pageSize ){ |
| 1774 | + fossil_panic("key too large: %u versus %u", nSize, pageSize); |
| 1775 | + } |
| 1776 | + p = fossil_secure_alloc_page(&n); |
| 1777 | + assert( p!=NULL ); |
| 1778 | + assert( n==pageSize ); |
| 1779 | + assert( n>=nSize ); |
| 1780 | + { |
| 1781 | +#if defined(_WIN32) |
| 1782 | + HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); |
| 1783 | + if( hProcess!=NULL ){ |
| 1784 | + SIZE_T nRead = 0; |
| 1785 | + if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ |
| 1786 | + CloseHandle(hProcess); |
| 1787 | + if( nRead==nSize ){ |
| 1788 | + db_unsave_encryption_key(); |
| 1789 | + zSavedKey = p; |
| 1790 | + savedKeySize = n; |
| 1791 | + }else{ |
| 1792 | + fossil_secure_free_page(p, n); |
| 1793 | + fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu", |
| 1794 | + nRead, nSize, pAddress, processId); |
| 1795 | + } |
| 1796 | + }else{ |
| 1797 | + CloseHandle(hProcess); |
| 1798 | + fossil_secure_free_page(p, n); |
| 1799 | + fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize, |
| 1800 | + pAddress, processId, GetLastError()); |
| 1801 | + } |
| 1802 | + }else{ |
| 1803 | + fossil_secure_free_page(p, n); |
| 1804 | + fossil_panic("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1805 | + } |
| 1806 | +#elif defined(__linux__) |
| 1807 | + ssize_t nRead; |
| 1808 | + struct iovec liov = {0}; |
| 1809 | + struct iovec riov = {0}; |
| 1810 | + liov.iov_base = p; |
| 1811 | + liov.iov_len = n; |
| 1812 | + riov.iov_base = pAddress; |
| 1813 | + riov.iov_len = nSize; |
| 1814 | + nRead = process_vm_readv(processId, &liov, 1, &riov, 1, 0); |
| 1815 | + if( nRead==nSize ){ |
| 1816 | + db_unsave_encryption_key(); |
| 1817 | + zSavedKey = p; |
| 1818 | + savedKeySize = n; |
| 1819 | + }else{ |
| 1820 | + fossil_secure_free_page(p, n); |
| 1821 | + fossil_panic("bad size read, %zd out of %zu bytes at %p from pid %lu", |
| 1822 | + nRead, nSize, pAddress, (unsigned long)processId); |
| 1823 | + } |
| 1824 | +#else |
| 1825 | + fossil_secure_free_page(p, n); |
| 1826 | + fossil_panic("db_read_saved_encryption_key_from_process unsupported"); |
| 1827 | +#endif |
| 1828 | + } |
| 1829 | +} |
| 1830 | + |
| 1831 | +/* |
| 1832 | +** This function writes the saved database encryption key into the |
| 1833 | +** specified Fossil parent process. This is only necessary (or |
| 1834 | +** functional) on Windows or Linux. |
| 1835 | +*/ |
| 1836 | +static void db_write_saved_encryption_key_to_process( |
| 1837 | + PID_T processId, /* Identifier for Fossil parent process. */ |
| 1838 | + LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ |
| 1839 | + SIZE_T nSize /* Size of saved key buffer in the parent process. */ |
| 1840 | +){ |
| 1841 | + void *p = db_get_saved_encryption_key(); |
| 1842 | + size_t n = db_get_saved_encryption_key_size(); |
| 1843 | + size_t pageSize = 0; |
| 1844 | + |
| 1845 | + fossil_get_page_size(&pageSize); |
| 1846 | + assert( pageSize>0 ); |
| 1847 | + if( nSize>pageSize ){ |
| 1848 | + fossil_panic("key too large: %u versus %u", nSize, pageSize); |
| 1849 | + } |
| 1850 | + assert( p!=NULL ); |
| 1851 | + assert( n==pageSize ); |
| 1852 | + assert( n>=nSize ); |
| 1853 | + { |
| 1624 | 1854 | #if defined(_WIN32) |
| 1855 | + HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE, |
| 1856 | + FALSE, processId); |
| 1857 | + if( hProcess!=NULL ){ |
| 1858 | + SIZE_T nWrite = 0; |
| 1859 | + if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){ |
| 1860 | + CloseHandle(hProcess); |
| 1861 | + if( nWrite!=nSize ){ |
| 1862 | + fossil_panic("bad size write, %u out of %u bytes at %p from pid %lu", |
| 1863 | + nRead, nSize, pAddress, processId); |
| 1864 | + } |
| 1865 | + }else{ |
| 1866 | + CloseHandle(hProcess); |
| 1867 | + fossil_panic("failed write, %u bytes at %p from pid %lu: %lu", nSize, |
| 1868 | + pAddress, processId, GetLastError()); |
| 1869 | + } |
| 1870 | + }else{ |
| 1871 | + fossil_panic("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1872 | + } |
| 1873 | +#elif defined(__linux__) |
| 1874 | + ssize_t nWrite; |
| 1875 | + struct iovec liov = {0}; |
| 1876 | + struct iovec riov = {0}; |
| 1877 | + liov.iov_base = p; |
| 1878 | + liov.iov_len = n; |
| 1879 | + riov.iov_base = pAddress; |
| 1880 | + riov.iov_len = nSize; |
| 1881 | + nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0); |
| 1882 | + if( nWrite!=nSize ){ |
| 1883 | + fossil_panic("bad size write, %zd out of %zu bytes at %p from pid %lu", |
| 1884 | + nWrite, nSize, pAddress, (unsigned long)processId); |
| 1885 | + } |
| 1886 | +#else |
| 1887 | + fossil_panic("db_write_saved_encryption_key_to_process unsupported"); |
| 1888 | +#endif |
| 1889 | + } |
| 1890 | +} |
| 1891 | + |
| 1625 | 1892 | /* |
| 1626 | | -** This function sets the saved database encryption key to one that gets |
| 1627 | | -** read from the specified Fossil parent process. This is only necessary |
| 1628 | | -** (or functional) on Windows. |
| 1893 | +** This function zero the saved database encryption key in the specified |
| 1894 | +** Fossil parent process. This is only necessary (or functional) on |
| 1895 | +** Windows or Linux. |
| 1629 | 1896 | */ |
| 1630 | | -void db_read_saved_encryption_key_from_process( |
| 1631 | | - DWORD processId, /* Identifier for Fossil parent process. */ |
| 1897 | +static void db_zero_saved_encryption_key_in_process( |
| 1898 | + PID_T processId, /* Identifier for Fossil parent process. */ |
| 1632 | 1899 | LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ |
| 1633 | 1900 | SIZE_T nSize /* Size of saved key buffer in the parent process. */ |
| 1634 | 1901 | ){ |
| 1635 | 1902 | void *p = NULL; |
| 1636 | 1903 | size_t n = 0; |
| 1637 | 1904 | size_t pageSize = 0; |
| 1638 | | - HANDLE hProcess = NULL; |
| 1639 | 1905 | |
| 1640 | 1906 | fossil_get_page_size(&pageSize); |
| 1641 | 1907 | assert( pageSize>0 ); |
| 1642 | 1908 | if( nSize>pageSize ){ |
| 1643 | 1909 | fossil_panic("key too large: %u versus %u", nSize, pageSize); |
| | @@ -1644,42 +1910,66 @@ |
| 1644 | 1910 | } |
| 1645 | 1911 | p = fossil_secure_alloc_page(&n); |
| 1646 | 1912 | assert( p!=NULL ); |
| 1647 | 1913 | assert( n==pageSize ); |
| 1648 | 1914 | assert( n>=nSize ); |
| 1649 | | - hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); |
| 1650 | | - if( hProcess!=NULL ){ |
| 1651 | | - SIZE_T nRead = 0; |
| 1652 | | - if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ |
| 1653 | | - CloseHandle(hProcess); |
| 1654 | | - if( nRead==nSize ){ |
| 1655 | | - db_unsave_encryption_key(); |
| 1656 | | - zSavedKey = p; |
| 1657 | | - savedKeySize = n; |
| 1658 | | - }else{ |
| 1659 | | - fossil_panic("bad size read, %u out of %u bytes at %p from pid %lu", |
| 1660 | | - nRead, nSize, pAddress, processId); |
| 1661 | | - } |
| 1662 | | - }else{ |
| 1663 | | - CloseHandle(hProcess); |
| 1664 | | - fossil_panic("failed read, %u bytes at %p from pid %lu: %lu", nSize, |
| 1665 | | - pAddress, processId, GetLastError()); |
| 1666 | | - } |
| 1667 | | - }else{ |
| 1668 | | - fossil_panic("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1915 | + { |
| 1916 | +#if defined(_WIN32) |
| 1917 | + HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE, |
| 1918 | + FALSE, processId); |
| 1919 | + if( hProcess!=NULL ){ |
| 1920 | + SIZE_T nWrite = 0; |
| 1921 | + if( WriteProcessMemory(hProcess, pAddress, p, nSize, &nWrite) ){ |
| 1922 | + CloseHandle(hProcess); |
| 1923 | + fossil_secure_free_page(p, n); |
| 1924 | + if( nWrite!=nSize ){ |
| 1925 | + fossil_panic("bad size zero, %u out of %u bytes at %p from pid %lu", |
| 1926 | + nRead, nSize, pAddress, processId); |
| 1927 | + } |
| 1928 | + }else{ |
| 1929 | + CloseHandle(hProcess); |
| 1930 | + fossil_secure_free_page(p, n); |
| 1931 | + fossil_panic("failed zero, %u bytes at %p from pid %lu: %lu", nSize, |
| 1932 | + pAddress, processId, GetLastError()); |
| 1933 | + } |
| 1934 | + }else{ |
| 1935 | + fossil_secure_free_page(p, n); |
| 1936 | + fossil_panic("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1937 | + } |
| 1938 | +#elif defined(__linux__) |
| 1939 | + ssize_t nWrite; |
| 1940 | + struct iovec liov = {0}; |
| 1941 | + struct iovec riov = {0}; |
| 1942 | + liov.iov_base = p; |
| 1943 | + liov.iov_len = n; |
| 1944 | + riov.iov_base = pAddress; |
| 1945 | + riov.iov_len = nSize; |
| 1946 | + nWrite = process_vm_writev(processId, &liov, 1, &riov, 1, 0); |
| 1947 | + if( nWrite!=nSize ){ |
| 1948 | + fossil_secure_free_page(p, n); |
| 1949 | + fossil_panic("bad size zero, %zd out of %zu bytes at %p from pid %lu", |
| 1950 | + nWrite, nSize, pAddress, (unsigned long)processId); |
| 1951 | + } |
| 1952 | +#else |
| 1953 | + fossil_secure_free_page(p, n); |
| 1954 | + fossil_panic("db_zero_saved_encryption_key_in_process unsupported"); |
| 1955 | +#endif |
| 1669 | 1956 | } |
| 1670 | 1957 | } |
| 1671 | 1958 | |
| 1672 | 1959 | /* |
| 1673 | 1960 | ** This function evaluates the specified TH1 script and attempts to parse |
| 1674 | 1961 | ** its result as a colon-delimited triplet containing a process identifier, |
| 1675 | 1962 | ** address, and size (in bytes) of the database encryption key. This is |
| 1676 | | -** only necessary (or functional) on Windows. |
| 1963 | +** only necessary (or functional) on Windows or Linux. |
| 1677 | 1964 | */ |
| 1678 | | -void db_read_saved_encryption_key_from_process_via_th1( |
| 1679 | | - const char *zConfig /* The TH1 script to evaluate. */ |
| 1965 | +static PID_T db_handle_saved_encryption_key_for_process_via_th1( |
| 1966 | + const char *zConfig, /* The TH1 script to evaluate. */ |
| 1967 | + int eType /* Non-zero to write key to parent process -OR- |
| 1968 | + * zero to read it from the parent process. */ |
| 1680 | 1969 | ){ |
| 1970 | + PID_T processId = 0; |
| 1681 | 1971 | int rc; |
| 1682 | 1972 | char *zResult; |
| 1683 | 1973 | char *zPwd = file_getcwd(0, 0); |
| 1684 | 1974 | Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_NEED_CONFIG | TH_INIT_NO_REPO); |
| 1685 | 1975 | rc = Th_Eval(g.interp, 0, zConfig, -1); |
| | @@ -1686,20 +1976,65 @@ |
| 1686 | 1976 | zResult = (char*)Th_GetResult(g.interp, 0); |
| 1687 | 1977 | if( rc!=TH_OK ){ |
| 1688 | 1978 | fossil_fatal("script for pid key failed: %s", zResult); |
| 1689 | 1979 | } |
| 1690 | 1980 | if( zResult ){ |
| 1691 | | - DWORD processId = 0; |
| 1692 | 1981 | LPVOID pAddress = NULL; |
| 1693 | 1982 | SIZE_T nSize = 0; |
| 1694 | 1983 | parse_pid_key_value(zResult, &processId, &pAddress, &nSize); |
| 1695 | | - db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 1984 | + if( eType==SEE_KEY_READ ){ |
| 1985 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 1986 | + }else if( eType==SEE_KEY_WRITE ){ |
| 1987 | + db_write_saved_encryption_key_to_process(processId, pAddress, nSize); |
| 1988 | + }else if( eType==SEE_KEY_ZERO ){ |
| 1989 | + db_zero_saved_encryption_key_in_process(processId, pAddress, nSize); |
| 1990 | + }else{ |
| 1991 | + fossil_panic("unsupported SEE key operation %d", eType); |
| 1992 | + } |
| 1696 | 1993 | } |
| 1697 | 1994 | file_chdir(zPwd, 0); |
| 1698 | 1995 | fossil_free(zPwd); |
| 1996 | + return processId; |
| 1699 | 1997 | } |
| 1700 | | -#endif /* defined(_WIN32) */ |
| 1998 | + |
| 1999 | +/* |
| 2000 | +** This function sets the saved database encryption key to one that gets |
| 2001 | +** read from the specified Fossil parent process, if applicable. This is |
| 2002 | +** only necessary (or functional) on Windows or Linux. |
| 2003 | +*/ |
| 2004 | +PID_T db_maybe_handle_saved_encryption_key_for_process(int eType){ |
| 2005 | + PID_T processId = 0; |
| 2006 | + g.zPidKey = find_option("usepidkey",0,1); |
| 2007 | + if( !g.zPidKey ){ |
| 2008 | + g.zPidKey = fossil_getenv("FOSSIL_SEE_PID_KEY"); |
| 2009 | + } |
| 2010 | + if( g.zPidKey ){ |
| 2011 | + LPVOID pAddress = NULL; |
| 2012 | + SIZE_T nSize = 0; |
| 2013 | + parse_pid_key_value(g.zPidKey, &processId, &pAddress, &nSize); |
| 2014 | + if( eType==SEE_KEY_READ ){ |
| 2015 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 2016 | + }else if( eType==SEE_KEY_WRITE ){ |
| 2017 | + db_write_saved_encryption_key_to_process(processId, pAddress, nSize); |
| 2018 | + }else if( eType==SEE_KEY_ZERO ){ |
| 2019 | + db_zero_saved_encryption_key_in_process(processId, pAddress, nSize); |
| 2020 | + }else{ |
| 2021 | + fossil_panic("unsupported SEE key operation %d", eType); |
| 2022 | + } |
| 2023 | + }else{ |
| 2024 | + const char *zSeeDbConfig = find_option("seedbcfg",0,1); |
| 2025 | + if( !zSeeDbConfig ){ |
| 2026 | + zSeeDbConfig = fossil_getenv("FOSSIL_SEE_DB_CONFIG"); |
| 2027 | + } |
| 2028 | + if( zSeeDbConfig ){ |
| 2029 | + processId = db_handle_saved_encryption_key_for_process_via_th1( |
| 2030 | + zSeeDbConfig, eType |
| 2031 | + ); |
| 2032 | + } |
| 2033 | + } |
| 2034 | + return processId; |
| 2035 | +} |
| 1701 | 2036 | #endif /* USE_SEE */ |
| 1702 | 2037 | |
| 1703 | 2038 | /* |
| 1704 | 2039 | ** If the database file zDbFile has a name that suggests that it is |
| 1705 | 2040 | ** encrypted, then prompt for the database encryption key and return it |
| 1706 | 2041 | |