TJAlienCredentials.cxx 6.55 KB
Newer Older
Nikola Hardi's avatar
Nikola Hardi committed
1
2
3
4
#include "TJAlienCredentials.h"
#include <sstream>
#include <cstdlib>
#include <unistd.h>
Nikola Hardi's avatar
Nikola Hardi committed
5
#include <fstream>
6
7
#include <cstdlib>
#include <iostream>
8
#include <fcntl.h>
Nikola Hardi's avatar
Nikola Hardi committed
9
10

using std::ifstream;
11
12
13
14
15
16
17
using std::ofstream;
using std::stringstream;
using std::endl;
using std::getenv;

const char* TJAlienCredentials::ENV_JOBTOKEN_KEY = "JALIEN_TOKEN_KEY";
const char* TJAlienCredentials::ENV_JOBTOKEN_CERT = "JALIEN_TOKEN_CERT";
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

const char* TJAlienCredentials::TMP_JOBTOKEN_KEY_FNAME_PREFIX = "tmpjobtokenkey_";
const char* TJAlienCredentials::TMP_JOBTOKEN_CERT_FNAME_PREFIX = "tmpjobtokencert_";

bool fileExists(const string &filename)
{
    bool fileExists = false;
    FILE *f = fopen(filename.c_str(), "r");

    if (f != NULL ) {
        fclose(f);
        fileExists = true;
    } else {
        fileExists = false;
    }

    return fileExists;
}


bool TJAlienCredentialsObject::exists() {
    return fileExists(certpath) && fileExists(keypath);
}

void TJAlienCredentials::writeSafeFile(const string& filename, const string& content) {
    if(gDebug) printf("writing safe file %s\n", filename.c_str());
    int fd = open(filename.c_str(), O_RDWR | O_CREAT, 0600);
    write(fd, content.c_str(), content.length());
    close(fd);
}

string TJAlienCredentials::getSafeFilename(const string& prefix) {
    string filename = TJAlienCredentials::getTmpDir() + "/" + prefix;

    const char *JOB_ID = getenv("ALIEN_PROC_ID");

    if(JOB_ID != NULL) {
        filename += JOB_ID;
    } else {
        pid_t pid = getpid();
        unsigned int rnd = random() % 100 + 1;

        do {
            filename += std::to_string(pid) + "_" + std::to_string(rnd);
        } while(fileExists(filename));
    }


    return filename;
}
Nikola Hardi's avatar
Nikola Hardi committed
68
69

string TJAlienCredentials::getTmpDir() {
70
	string tmpdir;
Nikola Hardi's avatar
Nikola Hardi committed
71

72
73
74
75
76
77
78
79
	if (getenv("TMPDIR") != NULL)
		tmpdir = getenv("TMPDIR");
	else if (getenv("TMP") != NULL)
		tmpdir = getenv("TMP");
	else if (getenv("TEMP") != NULL)
		tmpdir = getenv("TEMP");
	else
		tmpdir = P_tmpdir;
Nikola Hardi's avatar
Nikola Hardi committed
80

81
	return tmpdir;
Nikola Hardi's avatar
Nikola Hardi committed
82
83
84
}

string TJAlienCredentials::getHomeDir() {
85
	string homedir;
Nikola Hardi's avatar
Nikola Hardi committed
86

87
88
89
90
	if (getenv("HOME") != NULL)
		homedir = getenv("HOME");
	else
		homedir = "~";
Nikola Hardi's avatar
Nikola Hardi committed
91

92
	return homedir;
Nikola Hardi's avatar
Nikola Hardi committed
93
94
95
96
}

string TJAlienCredentials::getTokencertPath()
{
97
98
99
100
	std::stringstream tokencert_s;
	tokencert_s << tmpdir << "/tokencert_" << getuid() << ".pem";
	std::string tokencert = tokencert_s.str();
	std::string tokencertpath = std::getenv("JALIEN_TOKEN_CERT") ? : tokencert;
Nikola Hardi's avatar
Nikola Hardi committed
101

102
	return tokencertpath;
Nikola Hardi's avatar
Nikola Hardi committed
103
104
105
106
}

string TJAlienCredentials::getTokenkeyPath()
{
107
108
109
110
	std::stringstream tokenkey_s;
	tokenkey_s << tmpdir << "/tokenkey_" << getuid() << ".pem";
	std::string tokenkey = tokenkey_s.str();
	std::string tokenkeypath = std::getenv("JALIEN_TOKEN_KEY") ? : tokenkey;
Nikola Hardi's avatar
Nikola Hardi committed
111

112
	return tokenkeypath;
Nikola Hardi's avatar
Nikola Hardi committed
113
114
115
116
}

string TJAlienCredentials::getUsercertPath()
{
117
    std::string usercert = homedir + "/.globus/usercert.pem";
Nikola Hardi's avatar
Nikola Hardi committed
118
119
120
121
122
123
    std::string usercertpath = std::getenv("X509_USER_CERT") ? : usercert;
    return usercertpath;
}

string TJAlienCredentials::getUserkeyPath()
{
124
    std::string userkey = homedir + "/.globus/userkey.pem";
Nikola Hardi's avatar
Nikola Hardi committed
125
126
127
128
129
130
131
132
133
134
    std::string userkeypath = std::getenv("X509_USER_KEY") ? : userkey;
    return userkeypath;
}

TJAlienCredentials::TJAlienCredentials() {
    tmpdir = getTmpDir();
    homedir = getHomeDir();
}

void TJAlienCredentials::loadCredentials() {
135
  removeCredentials(cJOB_TOKEN);
136
137
138
139
	found_credentials.clear();
	loadTokenCertificate();
	loadFullGridCertificate();
	loadJobTokenCertificate();
Nikola Hardi's avatar
Nikola Hardi committed
140
141
142
143
144
145
146
147
148
149
150
151
152
}

void TJAlienCredentials::loadTokenCertificate() {
    TJAlienCredentialsObject token_credentials(getTokencertPath(), getTokenkeyPath(), cJBOX_TOKEN);

    if(token_credentials.exists()) {
        found_credentials[cJBOX_TOKEN] = token_credentials;
    }
}

void TJAlienCredentials::loadFullGridCertificate() {
    TJAlienCredentialsObject grid_certificate(getUsercertPath(), getUserkeyPath(), cFULL_GRID_CERT);

153
    if (grid_certificate.exists()) {
Nikola Hardi's avatar
Nikola Hardi committed
154
155
156
157
        found_credentials[cFULL_GRID_CERT] = grid_certificate;
    }
}

158
159
160
161
162
163
164
165
166
void TJAlienCredentials::loadJobTokenCertificate() {
    const char *env_cert = getenv(ENV_JOBTOKEN_CERT);
    const char *env_key = getenv(ENV_JOBTOKEN_KEY);

    // if it doesn't have both environment variables
    if(!env_cert || !env_key) {
        return;
    }

167
168
169
170
171
172
    // environment variables contain valid filepaths instead of the actual token
    if(fileExists(env_cert) && fileExists(env_key)) {
        found_credentials[cJOB_TOKEN] = TJAlienCredentialsObject(env_cert, env_key, cJOB_TOKEN);
    } else {
        const string& tmpcertpath = getSafeFilename(TMP_JOBTOKEN_CERT_FNAME_PREFIX);
        writeSafeFile(tmpcertpath, env_cert);
173

174
175
        const string& tmpkeypath = getSafeFilename(TMP_JOBTOKEN_KEY_FNAME_PREFIX);
        writeSafeFile(tmpkeypath, env_key);
176

177
        found_credentials[cJOB_TOKEN] = TJAlienCredentialsObject(tmpcertpath, tmpkeypath, cJOB_TOKEN, true);
178
179
180
    }
}

Nikola Hardi's avatar
Nikola Hardi committed
181
182
183
184
185
186
187
bool TJAlienCredentials::has(CredentialsKind kind) {
    return found_credentials.count(kind) == 1;
}

TJAlienCredentialsObject TJAlienCredentials::get(CredentialsKind kind) {
    if(this->has(kind)) {
        return found_credentials[kind];
188
189
    } else {
      return TJAlienCredentialsObject();
Nikola Hardi's avatar
Nikola Hardi committed
190
191
    }
}
Nikola Hardi's avatar
Nikola Hardi committed
192

193
194
void TJAlienCredentials::removeCredentials(CredentialsKind kind) {
	if (this->has(kind)) {
195
196
197
      if(kind == cJOB_TOKEN)
          get(kind).wipe();

198
199
200
201
202
203
204
205
		found_credentials.erase(kind);
	}
}

short TJAlienCredentials::count() {
	return found_credentials.size();
}

206
207
208
209
210
211
212
213
214
215
216
217
218
string readFile(const char* filename) {
    string line;
    stringstream contents;
    ifstream f(filename);

    if(f.is_open()) {
        while(getline(f, line)) {
            contents << line << endl;
        }
    }
    return contents.str();
}

219
const string TJAlienCredentialsObject::getKey() {
220
    return readFile(keypath.c_str());
Nikola Hardi's avatar
Nikola Hardi committed
221
222
}

223
const string TJAlienCredentialsObject::getCertificate() {
224
225
226
    return readFile(certpath.c_str());
}

227
228
229
230
231
232
233
234
235
236
237
238
void TJAlienCredentialsObject::readPassword() {
	if (this->kind == cFULL_GRID_CERT && this->getKey().find("ENCRYPTED") != std::string::npos)
	{
		printf("[Grid certificate password: ]");
		struct termios termold, termnew;
		tcgetattr(fileno(stdin), &termold);
		termnew = termold;
		termnew.c_lflag &= ~ECHO;
		termnew.c_lflag |= ECHONL;
		tcsetattr(fileno(stdin), TCSANOW, &termnew);
		
		char password[64];
239
240
		if (!fgets(password, sizeof(password), stdin))
			printf("\nFailed to get password input\n");
241
242
243
244
245
		
		tcsetattr(0, TCSANOW, &termold);
		
		password[strlen(password) - 1] = 0;
		this->password = std::string(password);
246
		}
247
248
249
250
251
252
253
254
255
}

const string TJAlienCredentialsObject::getPassword() {
	if (this->password.empty())
		readPassword();

    return this->password;
}

256
TJAlienCredentials::~TJAlienCredentials() {
257
    removeCredentials(cJOB_TOKEN);
Nikola Hardi's avatar
Nikola Hardi committed
258
}