Skip to content

Allow to specify SQLite URI filenames to PDO DSN #6610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

tzmfreedom
Copy link
Contributor

@tzmfreedom tzmfreedom commented Jan 17, 2021

SQLite allows to URI filenames to setup database configuration.
https://www.sqlite.org/uri.html
https://www.sqlite.org/c3ref/open.html#urifilenameexamples

With URI filename, we can specify query parameters to setup SQLite configuration, for example mode=ro disables write access, nolock=1 disables file locking.

In current PHP implementation, we cannot specify URI filenames because of expanding filename process, so this PR resolve it.

Example usage:

$pdo = new PDO('sqlite3:file:/tmp/db.sqlite?mode=ro');

@tzmfreedom tzmfreedom force-pushed the feature/pdo_sqlite3_dsn branch from d259207 to b2c6ff5 Compare January 17, 2021 07:15
@nikic
Copy link
Member

nikic commented Jan 18, 2021

As implemented, this allows an open_basedir bypass by prefixing with file:. It would be necessary to parse out the filename portion from the URI and validate it. Or alternatively don't permit the URI form if open_basedir is enabled.

Though this is actually a pre-existing problem, as one could manually specify SQLITE_OPEN_URI via PDO::SQLITE_ATTR_OPEN_FLAGS. We should probably explicitly filter out SQLITE_OPEN_URI under open_basedir. cc @cmb69

@nikic
Copy link
Member

nikic commented Jan 18, 2021

Though this is actually a pre-existing problem, as one could manually specify SQLITE_OPEN_URI via PDO::SQLITE_ATTR_OPEN_FLAGS. We should probably explicitly filter out SQLITE_OPEN_URI under open_basedir. cc @cmb69

Ah no, that's not right. There's no problem right now, as we'd treat the file: as part of the filename.

@nikic nikic closed this Jan 18, 2021
@nikic nikic reopened this Jan 18, 2021
@tzmfreedom tzmfreedom force-pushed the feature/pdo_sqlite3_dsn branch 2 times, most recently from 6ad929f to 2f06c40 Compare January 18, 2021 10:53
@tzmfreedom tzmfreedom force-pushed the feature/pdo_sqlite3_dsn branch from 2f06c40 to 260a304 Compare January 18, 2021 11:04
@tzmfreedom
Copy link
Contributor Author

Thank you for review.

As implemented, this allows an open_basedir bypass by prefixing with file:. It would be necessary to parse out the filename portion from the URI and validate it. Or alternatively don't permit the URI form if open_basedir is enabled.

I fixed, so it parse filename portion and validate it with php_check_open_basedir.

@nikic
Copy link
Member

nikic commented Jan 18, 2021

I pushed an additional test for check the open_basedir part. @cmb69 Do you see any issues with this?

@cmb69
Copy link
Member

cmb69 commented Jan 18, 2021

Hm, would that really work with arbitrary file:// URIs? E.g. when there is %2f in the path component.

@tzmfreedom
Copy link
Contributor Author

tzmfreedom commented Jan 18, 2021

If the filename or query parameter contains %2fin path component, decoded string / is recognized by sqlite.

$db = new \PDO('sqlite:file:/Users/foo%20bar%2fexample.db');
// => Access to "/Users/foo bar/example.db"
$db = new \PDO('sqlite:file:/Users/foo/example.db?mode=%2f');
// => Fatal error: Uncaught PDOException: SQLSTATE[HY000] [1] no such access mode: / in ...

But, I find my mistake that the current change on this PullRequest is not considered about file://{authority}/ or file:/// formatted URI. So I fixed it. 85f5361

@cmb69
Copy link
Member

cmb69 commented Jan 18, 2021

If the filename or query parameter contains %2fin path component, decoded string / is recognized by sqlite.

Yes, but it is also correctly handled by expand_filepath()?

@nikic
Copy link
Member

nikic commented Jan 19, 2021

I don't think we'll want to parse/decode the URL, as we could easily end up interpreting it differently than sqlite3 will. I think the path of least resistance here it to simply disable the SQLITE_OPEN_URI feature under open_basedir entirely.

@tzmfreedom
Copy link
Contributor Author

Thank you for your advice.
I've changed that it disable SQLITE_OPEN_URI feature when open_basedir is set: 25d4392

@nikic
Copy link
Member

nikic commented Jan 25, 2021

This looks good to me. @cmb69 Any further concerns?

@cmb69
Copy link
Member

cmb69 commented Jan 25, 2021

Nope; should be okay. :)

@php-pulls php-pulls closed this in a8dd009 Jan 25, 2021
nikic pushed a commit that referenced this pull request Aug 11, 2021
SQLITE_OPEN_URI introduced in #6610 is available from sqlite version 3.7.7.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants