Skip to content
This repository was archived by the owner on Nov 25, 2020. It is now read-only.

Commit 1f90363

Browse files
committed
Reorganize MemorySafe. Add a context identifier to handle multiple credential sources. For storing when passed via ENV CLi.
1 parent 8ce3909 commit 1f90363

File tree

16 files changed

+264
-214
lines changed

16 files changed

+264
-214
lines changed

core/src/core/src/pydio/Core/Controller/CliRunner.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,7 @@ public static function applyActionInBackground(ContextInterface $ctx, $actionNam
105105
$cmd .= " --$key=" . escapeshellarg($value);
106106
}
107107
}
108-
$envSet = false;
109-
if ($ctx->getRepository()->getContextOption($ctx, "USE_SESSION_CREDENTIALS")) {
110-
$envSet = MemorySafe::setEnv();
111-
}
112-
108+
$envSet = MemorySafe::setEnvForContext($ctx);
113109
// NOW RUN COMMAND
114110
$res = self::runCommandInBackground($cmd, $logFile);
115111

core/src/core/src/pydio/Core/Exception/PydioPromptException.php

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
namespace Pydio\Core\Exception;
2222

23+
use Pydio\Core\Http\Middleware\WorkspaceAuthMiddleware;
2324
use Pydio\Core\Http\Response\JSONSerializableResponseChunk;
2425
use Pydio\Core\Http\Response\XMLSerializableResponseChunk;
2526

@@ -78,31 +79,33 @@ public function __construct($promptType, $data, $messageString, $messageId = fal
7879
/**
7980
* Prompt user for credentials
8081
* @param array $parameters
81-
* @param string $passFieldName
8282
* @param string $postSubmitCallback
83-
* @throws PydioPromptException
83+
* @return PydioPromptException
8484
*/
85-
public static function promptForWorkspaceCredentials($parameters, $passFieldName, $postSubmitCallback = ""){
86-
$hiddens = [];
87-
$getFields = [$passFieldName];
85+
public static function promptForWorkspaceCredentials($parameters, $postSubmitCallback = ""){
86+
$inputs = [];
8887
foreach($parameters as $key => $value){
89-
$hiddens[] = "<input type='hidden' name='$key' value='$value'>";
90-
$getFields[] = $key;
88+
if($key === WorkspaceAuthMiddleware::FORM_RESUBMIT_LOGIN) {
89+
$inputs[] = "<input type='text' name='$key' value='$value' placeholder='Login'>";
90+
}else if($key === WorkspaceAuthMiddleware::FORM_RESUBMIT_PASS){
91+
$inputs[] = "<input type='password' name='$key' value='' placeholder='Password' autocomplete='off'>";
92+
}else{
93+
$inputs[] = "<input type='hidden' name='$key' value='$value'>";
94+
}
9195
}
92-
throw new PydioPromptException(
96+
return new PydioPromptException(
9397
"confirm",
9498
array(
9599
"DIALOG" => "<div>
96100
<h3>Credentials Required</h3>
97-
<div class='dialogLegend'>Please provide a password to enter this workspace. You may have to manually redo the action you were currently trying to achieve.</div>
101+
<div class='dialogLegend'>Please provide a password to enter this workspace.</div>
98102
<form autocomplete='off'>
99-
".implode("\n", $hiddens)."
100-
<input style='width: 200px;' type='password' autocomplete='off' name='$passFieldName' value='' placeholder='Password'>
103+
".implode("\n", $inputs)."
101104
</form>
102105
</div>
103106
",
104107
"OK" => array(
105-
"GET_FIELDS" => $getFields,
108+
"GET_FIELDS" => array_keys($parameters),
106109
"EVAL" => $postSubmitCallback
107110
),
108111
"CANCEL" => array(

core/src/core/src/pydio/Core/Exception/RepositoryLoadException.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ class RepositoryLoadException extends PydioException
3636
private $repository;
3737
/**
3838
* RepositoryLoadException constructor.
39-
* @param RepositoryInterface|String $repository
39+
* @param RepositoryInterface|String $workspace
4040
* @param array $errors
4141
*/
42-
public function __construct($repository, $errors)
42+
public function __construct($workspace, $errors)
4343
{
44-
if($repository instanceof RepositoryInterface){
45-
$message = "Error while loading workspace ".$repository->getDisplay()." : ".implode("\n-", $errors);
46-
$this->repository = $repository;
44+
if($workspace instanceof RepositoryInterface){
45+
$message = "Error while loading workspace ".$workspace->getDisplay()." : ".implode("\n-", $errors);
46+
$this->repository = $workspace;
4747
}else{
48-
$message = "Error while loading workspace ".$repository." : ".implode("\n-", $errors);
48+
$message = "Error while loading workspace ".$workspace." : ".implode("\n-", $errors);
4949
}
5050
parent::__construct($message, false, 5000);
5151
}

core/src/core/src/pydio/Core/Exception/WorkspaceAuthRequired.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@
3434
*/
3535
class WorkspaceAuthRequired extends PydioException {
3636

37-
private $repositoryId;
37+
private $workspaceId;
38+
private $requireLogin;
3839

3940
/**
4041
* WorkspaceAuthRequired constructor.
41-
* @param string $repositoryId
42+
* @param string $workspaceId
43+
* @param boolean $requireLogin
4244
* @param string $message
4345
*/
44-
public function __construct($repositoryId, $message = "Authentication required for this workspace")
46+
public function __construct($workspaceId, $requireLogin = false, $message = "Authentication required for this workspace")
4547
{
46-
$this->repositoryId = $repositoryId;
48+
$this->workspaceId = $workspaceId;
49+
$this->requireLogin = $requireLogin;
4750
parent::__construct($message, false, null);
4851
}
4952

@@ -53,13 +56,31 @@ public function __construct($repositoryId, $message = "Authentication required f
5356
* @throws WorkspaceAuthRequired
5457
*/
5558
public static function testWorkspace($workspaceObject, $userObject){
56-
if($workspaceObject->getContextOption(Context::contextWithObjects($userObject, $workspaceObject), "USE_SESSION_CREDENTIALS") !== true){
59+
$ctx = Context::contextWithObjects($userObject, $workspaceObject);
60+
$instanceId = MemorySafe::contextUsesInstance($ctx);
61+
if($instanceId === false){
5762
return;
5863
}
59-
if(MemorySafe::loadCredentials() !== false){
64+
if(MemorySafe::loadCredentials($instanceId) !== false){
6065
return;
6166
}
62-
throw new WorkspaceAuthRequired($workspaceObject->getId());
67+
$allowFreeLogin = ($workspaceObject->getContextOption($ctx, "SESSION_CREDENTIALS_FREE_LOGIN") === true);
68+
throw new WorkspaceAuthRequired($workspaceObject->getId(), $allowFreeLogin);
6369
}
6470

71+
/**
72+
* @return string
73+
*/
74+
public function getWorkspaceId(){
75+
return $this->workspaceId;
76+
}
77+
78+
/**
79+
* @return bool
80+
*/
81+
public function requiresLogin(){
82+
return $this->requireLogin;
83+
}
84+
85+
6586
}

core/src/core/src/pydio/Core/Http/Cli/AuthCliMiddleware.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ protected static function authenticateFromCliParameters($options){
7676
if($envPass !== false){
7777
unset($optToken);
7878
$optPass = $envPass;
79+
MemorySafe::storeCredentials($optUser, $optPass);
7980
}
8081
}
8182

core/src/core/src/pydio/Core/Http/Middleware/WorkspaceAuthMiddleware.php

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
use Psr\Http\Message\ResponseInterface;
2424
use Psr\Http\Message\ServerRequestInterface;
25+
use Pydio\Access\Core\Model\AJXP_Node;
2526
use Pydio\Auth\Core\MemorySafe;
2627
use Pydio\Core\Exception\PydioException;
2728

@@ -30,6 +31,7 @@
3031
use Pydio\Core\Http\Server;
3132
use Pydio\Core\Model\ContextInterface;
3233
use Pydio\Core\Services\SessionService;
34+
use Pydio\Core\Utils\Vars\InputFilter;
3335
use Pydio\Core\Utils\Vars\StringHelper;
3436

3537
defined('AJXP_EXEC') or die('Access not allowed');
@@ -47,7 +49,9 @@ class WorkspaceAuthMiddleware
4749
const RESUBMIT_AUTH_COUNT = "PYDIO_WORKSPACE_AUTH_RESUBMIT_COUNT";
4850

4951
const FORM_RESUBMIT_KEY = "workspace-auth-submission-id";
52+
const FORM_RESUBMIT_LOGIN = "workspace-auth-login";
5053
const FORM_RESUBMIT_PASS = "workspace-auth-password";
54+
const FORM_SESSION_CREDS = "workspace-auth-test-session-credentials";
5155

5256
/**
5357
* @param ServerRequestInterface $requestInterface
@@ -59,15 +63,33 @@ class WorkspaceAuthMiddleware
5963
public static function handleRequest(ServerRequestInterface $requestInterface, ResponseInterface $responseInterface, callable $next = null){
6064

6165
$vars = $requestInterface->getParsedBody();
66+
/** @var ContextInterface $ctx */
67+
$ctx = $requestInterface->getAttribute("ctx");
68+
6269
if(isSet($vars[self::FORM_RESUBMIT_KEY]) && SessionService::has(self::RESUBMIT_AUTH_VARS."-".$vars[self::FORM_RESUBMIT_KEY]) && !empty($vars[self::FORM_RESUBMIT_PASS])){
6370
$submittedId = $vars[self::FORM_RESUBMIT_KEY];
64-
// Count a max number of submission?
6571

66-
/** @var ContextInterface $ctx */
67-
$ctx = $requestInterface->getAttribute("ctx");
6872
if($ctx->hasUser()){
73+
$userId = $ctx->getUser()->getId();
74+
}
75+
if(isSet($vars[self::FORM_RESUBMIT_LOGIN]) && !empty($vars[self::FORM_RESUBMIT_LOGIN])){
76+
$userId = InputFilter::sanitize($vars[self::FORM_RESUBMIT_LOGIN], InputFilter::SANITIZE_EMAILCHARS);
77+
}
78+
79+
if(!empty($userId)){
6980
$password = $vars[self::FORM_RESUBMIT_PASS];
70-
MemorySafe::storeCredentials($ctx->getUser()->getId(), $password);
81+
if(isSet($vars[self::FORM_SESSION_CREDS])){
82+
$node = new AJXP_Node("pydio://".$userId."@".$vars[self::FORM_SESSION_CREDS]."/");
83+
try{
84+
MemorySafe::storeCredentials($userId, $password);
85+
if(!is_writeable($node->getUrl())){
86+
MemorySafe::clearCredentials();
87+
}
88+
}catch (\Exception $e){
89+
MemorySafe::clearCredentials();
90+
throw new PydioException($e->getMessage());
91+
}
92+
}
7193
}
7294

7395
$newVars = SessionService::fetch(self::RESUBMIT_AUTH_VARS."-".$submittedId);
@@ -89,13 +111,21 @@ public static function handleRequest(ServerRequestInterface $requestInterface, R
89111
// Generate a random ID.
90112
$submissionId = StringHelper::generateRandomString(24);
91113
SessionService::save(self::RESUBMIT_AUTH_VARS."-".$submissionId, $vars);
92-
$parameters = [self::FORM_RESUBMIT_KEY => $submissionId];
114+
$parameters = [];
115+
if($ex->requiresLogin()){
116+
$parameters[self::FORM_RESUBMIT_LOGIN] = $ctx->hasUser() ? $ctx->getUser()->getId() : "";
117+
}
118+
$parameters = array_merge($parameters, [
119+
self::FORM_RESUBMIT_KEY => $submissionId,
120+
self::FORM_RESUBMIT_PASS => "",
121+
self::FORM_SESSION_CREDS => $ex->getWorkspaceId()
122+
]);
93123
$postSubmitCallback = "";
94124
if($requestInterface->getAttribute("action") === "switch_repository"){
95125
$postSubmitCallback = "ajaxplorer.loadXmlRegistry();";
96126
}
97127
// Will throw a prompt exception with all current values
98-
return PydioPromptException::promptForWorkspaceCredentials($parameters, self::FORM_RESUBMIT_PASS, $postSubmitCallback);
128+
throw PydioPromptException::promptForWorkspaceCredentials($parameters, $postSubmitCallback);
99129

100130
}
101131

core/src/plugins/access.ajxp_conf/src/ConfAccessDriver.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ public function editAction(ServerRequestInterface $requestInterface, ResponseInt
309309
case "user_reorder_roles":
310310
case "users_bulk_update_roles":
311311
case "save_custom_user_params":
312-
case "save_repository_user_params":
313312
case "update_user_pwd":
314313
$this->usersAction($requestInterface, $responseInterface);
315314
break;

core/src/plugins/access.ajxp_conf/src/UsersManager.php

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -552,40 +552,7 @@ public function usersActions(ServerRequestInterface $requestInterface, ResponseI
552552
$responseInterface = $responseInterface->withBody(new SerializableResponseStream(new UserMessage($mess["ajxp_conf.47"].$userId)));
553553

554554
break;
555-
556-
case "save_repository_user_params" :
557-
558-
$userId = InputFilter::sanitize($httpVars["user_id"], InputFilter::SANITIZE_EMAILCHARS);
559-
$currentIsLogged = false;
560-
if ($userId === $ctx->getUser()->getId()) {
561-
$currentIsLogged = true;
562-
$user = $ctx->getUser();
563-
} else {
564-
$user = $this->getUserIfAuthorized($ctx, $userId);
565-
}
566-
567-
$wallet = $user->getPref("AJXP_WALLET");
568-
if(!is_array($wallet)) $wallet = array();
569-
$repoID = InputFilter::sanitize($httpVars["repository_id"], InputFilter::SANITIZE_ALPHANUM);
570-
if (!array_key_exists($repoID, $wallet)) {
571-
$wallet[$repoID] = array();
572-
}
573-
$options = $wallet[$repoID];
574-
$existing = $options;
575-
$newCtx = new Context($userId, $ctx->getRepositoryId());
576-
$this->parseParameters($newCtx, $httpVars, $options, false, $existing);
577-
$wallet[$repoID] = $options;
578-
$user->setPref("AJXP_WALLET", $wallet);
579-
$user->save();
580-
581-
if ($currentIsLogged) {
582-
AuthService::updateSessionUser($user);
583-
}
584-
585-
$responseInterface = $responseInterface->withBody(new SerializableResponseStream(new UserMessage($mess["ajxp_conf.47"].$userId)));
586-
587-
break;
588-
555+
589556
case "update_user_pwd" :
590557

591558
$userId = isSet($httpVars["user_id"]) ? InputFilter::sanitize($httpVars["user_id"], InputFilter::SANITIZE_EMAILCHARS) : null;

core/src/plugins/access.fs/FsAccessDriver.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,8 +2527,9 @@ public function makeSharedRepositoryOptions(ContextInterface $ctx, $httpVars)
25272527
"DEFAULT_RIGHTS" => "",
25282528
"DATA_TEMPLATE" => ""
25292529
];
2530-
if ($repository->getContextOption($ctx, "USE_SESSION_CREDENTIALS") === true) {
2531-
$newOptions["ENCODED_CREDENTIALS"] = MemorySafe::getEncodedCredentialString();
2530+
$sessionCredsInstance = MemorySafe::contextUsesInstance($ctx);
2531+
if($sessionCredsInstance !== false){
2532+
$newOptions["ENCODED_CREDENTIALS"] = MemorySafe::getInstance($sessionCredsInstance)->getEncodedCredentials();
25322533
}
25332534
$customData = [];
25342535
foreach ($httpVars as $key => $value) {
@@ -2543,7 +2544,7 @@ public function makeSharedRepositoryOptions(ContextInterface $ctx, $httpVars)
25432544
$newOptions["META_SOURCES"] = $repository->getContextOption($ctx, "META_SOURCES");
25442545
foreach ($newOptions["META_SOURCES"] as $index => &$data) {
25452546
if (isSet($data["USE_SESSION_CREDENTIALS"]) && $data["USE_SESSION_CREDENTIALS"] === true) {
2546-
$newOptions["META_SOURCES"][$index]["ENCODED_CREDENTIALS"] = MemorySafe::getEncodedCredentialString();
2547+
$newOptions["META_SOURCES"][$index]["ENCODED_CREDENTIALS"] = MemorySafe::getInstance()->getEncodedCredentials();
25472548
}
25482549
}
25492550
Controller::applyHook("workspace.share_metasources", [$ctx, &$newOptions["META_SOURCES"]]);

core/src/plugins/access.smb/manifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<param name="PATH" type="string" label="CONF_MESSAGE[Uri]" description="CONF_MESSAGE[Path to the share and complementary URI if necessary]" mandatory="false"/>
1111
<param name="DOMAIN" type="string" label="CONF_MESSAGE[Domain]" description="CONF_MESSAGE[Default domain to use with session credentials. The domain name ends with '/' or '\' depend on your system. Example: MyDomain\ or YourDomain/. Default is /]" mandatory="false"/>
1212
<param name="CHMOD_VALUE" type="string" label="CONF_MESSAGE[File Creation Mask]" description="CONF_MESSAGE[Optionnaly apply a chmod operation. Value must be numeric, like 0777, 0644, etc.]" default="0666"/>
13+
<param name="SESSION_CREDENTIALS_AUTHFRONT" type="string" label="CONF_MESSAGE[Session Credentials Authfront]" description="CONF_MESSAGE[Set this workspace to use only credentials from a specific authfront. Leave empty by default, can be useful to restrict credentials to e.g. CAS authfront (use authfront.cas value in that case).]" default=""/>
1314
<global_param name="SMBCLIENT" type="string" label="CONF_MESSAGE[Smbclient]" description="CONF_MESSAGE[Path to smbclient executable, considered to be in the path by default.]" mandatory="true" default="smbclient"/>
1415
<global_param name="SMB_PATH_TMP" type="string" label="CONF_MESSAGE[Path Tmp]" description="CONF_MESSAGE[OS Path Temporary if not the default one]" mandatory="true" default="/tmp"/>
1516
<global_param name="SMB_ENABLE_ZIP" type="boolean" label="CONF_MESSAGE[Enable Zip]" description="CONF_MESSAGE[Enable zip creation for repositories using Samba access. Make sure that you are using a very fast network, otherwise it will be very long!]" mandatory="false" default="false"/>

0 commit comments

Comments
 (0)