Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13957685
D7468.id16834.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D7468.id16834.diff
View Options
Index: src/applications/diffusion/controller/DiffusionController.php
===================================================================
--- src/applications/diffusion/controller/DiffusionController.php
+++ src/applications/diffusion/controller/DiffusionController.php
@@ -35,6 +35,9 @@
} else if ($content_type == 'application/x-git-upload-pack-request') {
// We get this for `git-upload-pack`.
$vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
+ } else if ($content_type == 'application/x-git-receive-pack-request') {
+ // We get this for `git-receive-pack`.
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
} else if ($request->getExists('cmd')) {
// Mercurial also sends an Accept header like
// "application/mercurial-0.1", and a User-Agent like
@@ -61,16 +64,37 @@
private function processVCSRequest($callsign) {
- // TODO: Authenticate user.
+ // If authentication credentials have been provided, try to find a user
+ // that actually matches those credentials.
+ if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
+ $username = $_SERVER['PHP_AUTH_USER'];
+ $password = new PhutilOpaqueEnvelope($_SERVER['PHP_AUTH_PW']);
- $viewer = new PhabricatorUser();
+ $viewer = $this->authenticateHTTPRepositoryUser($username, $password);
+ if (!$viewer) {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('Invalid credentials.'));
+ }
+ } else {
+ // User hasn't provided credentials, which means we count them as
+ // being "not logged in".
+ $viewer = new PhabricatorUser();
+ }
$allow_public = PhabricatorEnv::getEnvConfig('policy.allow-public');
+ $allow_auth = PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth');
if (!$allow_public) {
if (!$viewer->isLoggedIn()) {
- return new PhabricatorVCSResponse(
- 403,
- pht('You must log in to access repositories.'));
+ if ($allow_auth) {
+ return new PhabricatorVCSResponse(
+ 401,
+ pht('You must log in to access repositories.'));
+ } else {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('Public and authenticated HTTP access are both forbidden.'));
+ }
}
}
@@ -90,9 +114,17 @@
403,
pht('You do not have permission to access this repository.'));
} else {
- return new PhabricatorVCSResponse(
- 401,
- pht('You must log in to access this repository.'));
+ if ($allow_auth) {
+ return new PhabricatorVCSResponse(
+ 401,
+ pht('You must log in to access this repository.'));
+ } else {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht(
+ 'This repository requires authentication, which is forbidden '.
+ 'over HTTP.'));
+ }
}
}
@@ -124,9 +156,17 @@
403,
pht('You do not have permission to push to this repository.'));
} else {
- return new PhabricatorVCSResponse(
- 401,
- pht('You must log in to push to this repository.'));
+ if ($allow_auth) {
+ return new PhabricatorVCSResponse(
+ 401,
+ pht('You must log in to push to this repository.'));
+ } else {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht(
+ 'Pushing to this repository requires authentication, '.
+ 'which is forbidden over HTTP.'));
+ }
}
}
}
@@ -413,7 +453,16 @@
// Rebuild the query string to strip `__magic__` parameters and prevent
// issues where we might interpret inputs like "service=read&service=write"
// differently than the server does and pass it an unsafe command.
- $query_data = $request->getPassthroughRequestParameters();
+
+ // NOTE: This does not use getPassthroughRequestParameters() because
+ // that code is HTTP-method agnostic and will encode POST data.
+
+ $query_data = $_GET;
+ foreach ($query_data as $key => $value) {
+ if (!strncmp($key, '__', 2)) {
+ unset($query_data[$key]);
+ }
+ }
$query_string = http_build_query($query_data, '', '&');
// We're about to wipe out PATH with the rest of the environment, so
@@ -426,18 +475,31 @@
$env = array(
'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'],
'QUERY_STRING' => $query_string,
- 'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'],
- 'REMOTE_USER' => '',
+ 'CONTENT_TYPE' => $request->getHTTPHeader('Content-Type'),
+ 'HTTP_CONTENT_ENCODING' => $request->getHTTPHeader('Content-Encoding'),
'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
'GIT_PROJECT_ROOT' => $repository_root,
'GIT_HTTP_EXPORT_ALL' => '1',
'PATH_INFO' => $request_path,
+
+ // TODO: Set these correctly.
+ 'REMOTE_USER' => '',
+ // GIT_COMMITTER_NAME
+ // GIT_COMMITTER_EMAIL
);
- list($stdout) = id(new ExecFuture('%s', $bin))
+ $input = PhabricatorStartup::getRawInput();
+
+ list($err, $stdout, $stderr) = id(new ExecFuture('%s', $bin))
->setEnv($env, true)
- ->write(PhabricatorStartup::getRawInput())
- ->resolvex();
+ ->write($input)
+ ->resolve();
+
+ if ($err) {
+ return new PhabricatorVCSResponse(
+ 500,
+ pht('Error %d: %s', $err, $stderr));
+ }
return id(new DiffusionGitResponse())->setGitData($stdout);
}
@@ -454,5 +516,43 @@
->setTitle($title)
->appendChild($body);
}
+
+ private function authenticateHTTPRepositoryUser(
+ $username,
+ PhutilOpaqueEnvelope $password) {
+
+ if (!PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')) {
+ // No HTTP auth permitted.
+ return null;
+ }
+
+ $user = id(new PhabricatorPeopleQuery())
+ ->setViewer(new PhabricatorUser())
+ ->withUsernames(array($username))
+ ->executeOne();
+ if (!$user) {
+ // Username doesn't match anything.
+ return null;
+ }
+
+ $password_entry = id(new PhabricatorRepositoryVCSPassword())
+ ->loadOneWhere('userPHID = %s', $user->getPHID());
+ if (!$password_entry) {
+ // User doesn't have a password set.
+ return null;
+ }
+
+ if (!$password_entry->comparePassword($password, $user)) {
+ // Password doesn't match.
+ return null;
+ }
+
+ if ($user->getIsDisabled()) {
+ // User is disabled.
+ return null;
+ }
+
+ return $user;
+ }
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Oct 15 2024, 10:41 AM (5 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6712556
Default Alt Text
D7468.id16834.diff (6 KB)
Attached To
Mode
D7468: Implement writes over HTTP for Git.
Attached
Detach File
Event Timeline
Log In to Comment