Skip to content

Commit d9161c3

Browse files
marcosbentoiainrussell
authored andcommitted
Pull request #14: Handle --password option in ecFlow client (ECFLOW-1865)
Merge in ECFLOW/ecflow from bug/ECFLOW-1865_password_option to develop * commit 'd92e902bf1fefee7fdc4eebfdfb90cc1e544770f': Add test to ensure the ---password option is handled ECFLOW-1865 Add missing handling of --password option Encapsulate POSIX crypt uses into specific class ECFLOW-1865
2 parents e7d5c25 + d92e902 commit d9161c3

9 files changed

+150
-19
lines changed

ACore/src/Passwd.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818

1919
#include "Passwd.hpp"
2020

21-
//extern char *crypt(const char *key, const char *salt);
22-
23-
2421
double ecf_drand48();
2522

2623

ACore/src/PasswdFile.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// Description : Parser for white list file
1414
//============================================================================
1515

16-
#include <unistd.h> // for crypt
1716
#include <iostream>
1817

1918
#include <boost/lexical_cast.hpp>
@@ -23,6 +22,7 @@
2322
#include "File.hpp"
2423
#include "Str.hpp"
2524
#include "User.hpp"
25+
#include "PasswordEncryption.hpp"
2626

2727
using namespace ecf;
2828
using namespace std;
@@ -269,7 +269,7 @@ bool PasswdFile::add_user(std::vector<std::string>& tokens, std::string& error_m
269269
return false;
270270
}
271271

272-
vec_.emplace_back(tokens[0],tokens[1],tokens[2],crypt(tokens[3].c_str(),tokens[0].c_str()));
272+
vec_.emplace_back(tokens[0],tokens[1],tokens[2],PasswordEncryption::encrypt(tokens[3],tokens[0]));
273273

274274
return true;
275275
}

ACore/src/PasswordEncryption.hpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#ifndef PASSWORD_ENCRYPTION_HPP_
2+
#define PASSWORD_ENCRYPTION_HPP_
3+
//============================================================================
4+
// Name :
5+
// Author :
6+
// Revision :
7+
//
8+
// Copyright 2009- ECMWF.
9+
// This software is licensed under the terms of the Apache Licence version 2.0
10+
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
11+
// In applying this licence, ECMWF does not waive the privileges and immunities
12+
// granted to it by virtue of its status as an intergovernmental organisation
13+
// nor does it submit to any jurisdiction.
14+
//
15+
// Description : Provides a generic password encryption mechanism
16+
// + specific POSIX implementation
17+
//============================================================================
18+
19+
#include <unistd.h>
20+
21+
#include <string>
22+
23+
struct PosixEncryption {
24+
using salt_t = std::string;
25+
using key_t = std::string;
26+
using encrypted_t = std::string;
27+
28+
static encrypted_t encrypt(const key_t& key, const salt_t& salt) {
29+
auto result = crypt(key.c_str(), salt.c_str());
30+
if (!result) {
31+
throw std::runtime_error("Error: unable to encrypt the given key");
32+
}
33+
return std::string{result};
34+
}
35+
};
36+
37+
template <typename ENGINE>
38+
struct BasePasswordEncryption {
39+
using username_t = std::string;
40+
using plain_password_t = std::string;
41+
using encrypted_password_t = std::string;
42+
43+
static encrypted_password_t encrypt(const plain_password_t& password, const username_t& username) {
44+
return ENGINE::encrypt(password, username);
45+
}
46+
};
47+
48+
using PasswordEncryption = BasePasswordEncryption<PosixEncryption>;
49+
50+
#endif // PASSWORD_ENCRYPTION_HPP_

ACore/test/TestPasswdFile.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
//
1313
// Description :
1414
//============================================================================
15-
#include <iostream>
16-
#include <unistd.h>
17-
15+
#include <boost/filesystem/operations.hpp>
16+
#include <boost/filesystem/path.hpp>
1817
#include <boost/test/unit_test.hpp>
19-
#include "boost/filesystem/operations.hpp"
20-
#include "boost/filesystem/path.hpp"
18+
#include <iostream>
2119

22-
#include "PasswdFile.hpp"
2320
#include "File.hpp"
21+
#include "PasswdFile.hpp"
22+
#include "PasswordEncryption.hpp"
2423

2524
namespace fs = boost::filesystem;
2625
using namespace std;
@@ -146,11 +145,11 @@ BOOST_AUTO_TEST_CASE( test_passwd )
146145
// tom host3 3143 x12ggg # sdsdsd
147146

148147
std::vector<Pass_wd> expected_passwds;
149-
expected_passwds.emplace_back("fred", "host", "3141", crypt("x12ggg","fred") );
150-
expected_passwds.emplace_back("fred", "host3", "3143", crypt("passwd","fred") );
151-
expected_passwds.emplace_back("fred", "host4", "3145", crypt("x12ggg","fred") );
152-
expected_passwds.emplace_back("jake", "host", "3141", crypt("x12ggg","jake") );
153-
expected_passwds.emplace_back("tom", "host3", "3143", crypt("x12ggg","tom") );
148+
expected_passwds.emplace_back("fred", "host", "3141", PasswordEncryption::encrypt("x12ggg","fred") );
149+
expected_passwds.emplace_back("fred", "host3", "3143", PasswordEncryption::encrypt("passwd","fred") );
150+
expected_passwds.emplace_back("fred", "host4", "3145", PasswordEncryption::encrypt("x12ggg","fred") );
151+
expected_passwds.emplace_back("jake", "host", "3141", PasswordEncryption::encrypt("x12ggg","jake") );
152+
expected_passwds.emplace_back("tom", "host3", "3143", PasswordEncryption::encrypt("x12ggg","tom") );
154153

155154
BOOST_REQUIRE_MESSAGE(expected_passwds == theFile.passwds() ,"expected passwords to match");
156155
}

ACore/test/TestPasswordEncryption.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//============================================================================
2+
// Name :
3+
// Author :
4+
// Revision :
5+
//
6+
// Copyright 2009- ECMWF.
7+
// This software is licensed under the terms of the Apache Licence version 2.0
8+
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
9+
// In applying this licence, ECMWF does not waive the privileges and immunities
10+
// granted to it by virtue of its status as an intergovernmental organisation
11+
// nor does it submit to any jurisdiction.
12+
//
13+
// Description : Tests the functionality provided by PasswordEncryption
14+
//============================================================================
15+
16+
#include <boost/test/unit_test.hpp>
17+
18+
#include "PasswordEncryption.hpp"
19+
20+
BOOST_AUTO_TEST_SUITE( CoreTestSuite )
21+
22+
BOOST_AUTO_TEST_CASE( test_is_able_to_encrypt_password )
23+
{
24+
PasswordEncryption::username_t user = "username";
25+
PasswordEncryption::plain_password_t plain = "password";
26+
PasswordEncryption::encrypted_password_t expected = "usjRS48E8ZADM";
27+
// Expected was obtained by calling `$ openssl passwd -salt username password`
28+
29+
auto encrypted = PasswordEncryption::encrypt(plain, user);
30+
31+
BOOST_REQUIRE(encrypted == expected);
32+
}
33+
34+
BOOST_AUTO_TEST_SUITE_END()

Client/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ SET_TARGET_PROPERTIES(ecflow_client PROPERTIES
7272

7373
list( APPEND test_srcs
7474
test/TestClientEnvironment.cpp
75+
test/TestClientOptions.cpp
7576
test/TestClientInterface.cpp
7677
test/TestJobGenOnly.cpp
7778
test/TestLifeCycle.cpp

Client/src/ClientOptions.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "Ecf.hpp"
2727
#include "Child.hpp"
2828
#include "TaskApi.hpp"
29+
#include "PasswordEncryption.hpp"
2930

3031
using namespace std;
3132
using namespace ecf;
@@ -137,6 +138,11 @@ Cmd_ptr ClientOptions::parse(int argc, char* argv[],ClientEnvironment* env) cons
137138
if (env->debug()) std::cout << " user " << user << " overridden at the command line\n";
138139
env->set_user_name(user);
139140
}
141+
if ( vm.count( "password" ) ) {
142+
std::string password = vm[ "password" ].as< std::string > ();
143+
if (env->debug()) std::cout << " password overridden at the command line\n";
144+
env->set_password(PasswordEncryption::encrypt(password, env->get_user_name()));
145+
}
140146

141147
#ifdef ECF_OPENSSL
142148
if ( vm.count( "ssl" )) {

Client/test/TestClientOptions.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//============================================================================
2+
// Name :
3+
// Author : Avi
4+
// Revision : $Revision: #9 $
5+
//
6+
// Copyright 2009- ECMWF.
7+
// This software is licensed under the terms of the Apache Licence version 2.0
8+
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
9+
// In applying this licence, ECMWF does not waive the privileges and immunities
10+
// granted to it by virtue of its status as an intergovernmental organisation
11+
// nor does it submit to any jurisdiction.
12+
//
13+
// Description : Tests the capabilities of ClientOptions
14+
//============================================================================
15+
#include <boost/test/unit_test.hpp>
16+
17+
#include "ClientEnvironment.hpp"
18+
#include "ClientOptions.hpp"
19+
#include "PasswordEncryption.hpp"
20+
21+
BOOST_AUTO_TEST_SUITE(ClientTestSuite)
22+
23+
BOOST_AUTO_TEST_CASE(test_is_able_to_process_username_and_password) {
24+
const char* expected_username = "username";
25+
const char* plain_password = "password";
26+
std::string expected_password = PasswordEncryption::encrypt(plain_password, expected_username);
27+
28+
const char* argv[]{"ecflow_client", "--user", expected_username, "--password", plain_password, "--ping"};
29+
int argc = boost::size(argv);
30+
31+
ClientOptions options;
32+
ClientEnvironment environment(false);
33+
options.parse(argc, const_cast<char**>(argv), &environment);
34+
35+
std::string actual_username = environment.get_user_name();
36+
BOOST_REQUIRE(expected_username == actual_username);
37+
38+
std::string actual_password = environment.get_user_password(expected_username);
39+
BOOST_REQUIRE(expected_password == actual_password);
40+
}
41+
42+
BOOST_AUTO_TEST_SUITE_END()

Http/src/BasicAuth.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
1616

1717
#include "BasicAuth.hpp"
18+
19+
#include "Base64.hpp"
1820
#include "HttpServerException.hpp"
19-
#include <Base64.hpp>
20-
#include <Str.hpp>
21+
#include "PasswordEncryption.hpp"
22+
#include "Str.hpp"
2123

2224
std::pair<std::string, std::string> BasicAuth::get_credentials(const std::string& token) {
2325
const std::string decoded = base64_decode(token);
2426
std::vector<std::string> elems;
2527
ecf::Str::split(decoded, elems, ":");
2628

27-
return std::make_pair(elems[0], crypt(elems[1].c_str(), elems[0].c_str()));
29+
return std::make_pair(elems[0], PasswordEncryption::encrypt(elems[1], elems[0]));
2830
}

0 commit comments

Comments
 (0)