|
a/src/ohcredentials.cxx |
|
b/src/ohcredentials.cxx |
|
... |
|
... |
140 |
|
140 |
|
141 |
// We need a Python helper to perform the login. That's the media
|
141 |
// We need a Python helper to perform the login. That's the media
|
142 |
// server gateway module, from which we only use a separate method
|
142 |
// server gateway module, from which we only use a separate method
|
143 |
// which logs-in and returns the auth data (token, etc.)
|
143 |
// which logs-in and returns the auth data (token, etc.)
|
144 |
bool maybeStartCmd() {
|
144 |
bool maybeStartCmd() {
|
145 |
LOGDEB("ServiceCreds: " << servicename << " maybeStartCmd()\n");
|
145 |
LOGDEB1("ServiceCreds: " << servicename << " maybeStartCmd()\n");
|
146 |
if (nullptr == cmd) {
|
146 |
if (nullptr == cmd) {
|
147 |
cmd = new CmdTalk(30);
|
147 |
cmd = new CmdTalk(30);
|
148 |
}
|
148 |
}
|
149 |
if (cmd->running()) {
|
149 |
if (cmd->running()) {
|
150 |
return true;
|
150 |
return true;
|
|
... |
|
... |
265 |
vector<string> acmd{"openssl", "pkey", "-in", keyfile, "-pubout"};
|
265 |
vector<string> acmd{"openssl", "pkey", "-in", keyfile, "-pubout"};
|
266 |
if (!cmd.backtick(acmd, pubkey)) {
|
266 |
if (!cmd.backtick(acmd, pubkey)) {
|
267 |
LOGERR("OHCredentials: could not read public key\n");
|
267 |
LOGERR("OHCredentials: could not read public key\n");
|
268 |
return;
|
268 |
return;
|
269 |
}
|
269 |
}
|
270 |
|
270 |
tryLoad();
|
271 |
LOGDEB1("OHCredentials: my public key:\n" << pubkey << endl);
|
271 |
LOGDEB1("OHCredentials: my public key:\n" << pubkey << endl);
|
272 |
}
|
272 |
}
|
273 |
|
273 |
|
274 |
bool decrypt(const string& in, string& out) {
|
274 |
bool decrypt(const string& in, string& out) {
|
275 |
vector<string> acmd{"openssl", "pkeyutl", "-inkey",
|
275 |
vector<string> acmd{"openssl", "pkeyutl", "-inkey",
|
|
... |
|
... |
291 |
it->second.enabled = enabled;
|
291 |
it->second.enabled = enabled;
|
292 |
return true;
|
292 |
return true;
|
293 |
}
|
293 |
}
|
294 |
|
294 |
|
295 |
bool save() {
|
295 |
bool save() {
|
296 |
bool saveohcredentials = true;
|
296 |
bool saveohcredentials = doingsavetofile();
|
297 |
string val;
|
|
|
298 |
if (g_config && g_config->get("saveohcredentials", val)) {
|
|
|
299 |
saveohcredentials = stringToBool(val);
|
|
|
300 |
}
|
|
|
301 |
// We share the creds with the media server process because it
|
297 |
// We share the creds with the media server process because it
|
302 |
// needs them for url translation If saveohcredentials is
|
298 |
// needs them for url translation If saveohcredentials is
|
303 |
// true, we use a file, which can also be used by the regular
|
299 |
// true, we use a file, which can also be used by the regular
|
304 |
// media server plugin, for possible later access without
|
300 |
// media server plugin, for possible later access without
|
305 |
// ohcredentials. If it's false, we use a shared mem segment,
|
301 |
// ohcredentials (e.g. with another non-kazoo CP). If it's
|
306 |
// and the user/pass would have to be set in
|
302 |
// false, we use a shared mem segment, and the user/pass would
|
307 |
// /etc/upmpdcli.conf for the regular plugin to work.
|
303 |
// have to be set in /etc/upmpdcli.conf for the media server
|
|
|
304 |
// plugin to work.
|
308 |
if (saveohcredentials) {
|
305 |
if (saveohcredentials) {
|
309 |
string credsfile = path_cat(cachedir, "screds");
|
306 |
string credsfile = path_cat(cachedir, "screds");
|
310 |
ConfSimple credsconf(credsfile.c_str());
|
307 |
ConfSimple credsconf(credsfile.c_str());
|
311 |
if (!credsconf.ok()) {
|
308 |
if (!credsconf.ok()) {
|
312 |
LOGERR("OHCredentials: error opening " << credsfile <<
|
309 |
LOGERR("OHCredentials: error opening " << credsfile <<
|
313 |
" errno " << errno << endl);
|
310 |
" errno " << errno << endl);
|
314 |
return false;
|
311 |
return false;
|
315 |
}
|
312 |
}
|
316 |
for (const auto& cred : creds) {
|
313 |
saveToConfTree(credsconf);
|
317 |
credsconf.set(cred.second.servicename + "user", cred.second.user);
|
|
|
318 |
credsconf.set(cred.second.servicename + "pass", cred.second.password);
|
|
|
319 |
}
|
|
|
320 |
chmod(credsfile.c_str(), 0600);
|
314 |
chmod(credsfile.c_str(), 0600);
|
321 |
} else {
|
315 |
} else {
|
322 |
string data;
|
316 |
string data;
|
323 |
ConfSimple credsconf(data);
|
317 |
ConfSimple credsconf(data);
|
324 |
for (const auto& cred : creds) {
|
318 |
saveToConfTree(credsconf);
|
325 |
credsconf.set(cred.second.servicename + "user", cred.second.user);
|
|
|
326 |
credsconf.set(cred.second.servicename + "pass", cred.second.password);
|
|
|
327 |
}
|
|
|
328 |
LockableShmSeg seg(ohcreds_segpath, ohcreds_segid, ohcreds_segsize, true);
|
319 |
LockableShmSeg seg(ohcreds_segpath, ohcreds_segid, ohcreds_segsize,
|
|
|
320 |
true);
|
329 |
if (!seg.ok()) {
|
321 |
if (!seg.ok()) {
|
330 |
LOGERR("OHCredentials: shared memory segment allocate/attach failed\n");
|
322 |
LOGERR("OHCredentials: shared memory segment allocate/attach "
|
|
|
323 |
"failed\n");
|
331 |
return false;
|
324 |
return false;
|
332 |
}
|
325 |
}
|
333 |
LockableShmSeg::Accessor access(seg);
|
326 |
LockableShmSeg::Accessor access(seg);
|
334 |
char *cp = (char *)(access.getseg());
|
327 |
char *cp = (char *)(access.getseg());
|
335 |
ostringstream strm;
|
328 |
ostringstream strm;
|
336 |
credsconf.write(strm);
|
329 |
credsconf.write(strm);
|
|
|
330 |
if (strm.str().size() >= ohcreds_segsize - 1) {
|
|
|
331 |
LOGERR("OHCredentials: creds size " << strm.str().size() <<
|
|
|
332 |
"won't fit in SHM segment\n");
|
|
|
333 |
return false;
|
|
|
334 |
}
|
337 |
strcpy(cp, strm.str().c_str());
|
335 |
strncpy(cp, strm.str().c_str(), ohcreds_segsize);
|
338 |
LOGDEB1("OHCredentials: shm seg content: [" << cp << "]\n");
|
336 |
LOGDEB1("OHCredentials: shm seg content: [" << cp << "]\n");
|
339 |
}
|
337 |
}
|
340 |
return true;
|
338 |
return true;
|
|
|
339 |
}
|
|
|
340 |
|
|
|
341 |
//// This could be a private part if we were not all friends here /////
|
|
|
342 |
|
|
|
343 |
bool doingsavetofile() {
|
|
|
344 |
bool saveohcredentials = true;
|
|
|
345 |
string val;
|
|
|
346 |
if (g_config && g_config->get("saveohcredentials", val)) {
|
|
|
347 |
saveohcredentials = stringToBool(val);
|
|
|
348 |
}
|
|
|
349 |
return saveohcredentials;
|
|
|
350 |
}
|
|
|
351 |
|
|
|
352 |
void saveToConfTree(ConfSimple& credsconf) {
|
|
|
353 |
for (const auto& cred : creds) {
|
|
|
354 |
const string& shortid = cred.second.servicename;
|
|
|
355 |
credsconf.set(shortid + "user", cred.second.user);
|
|
|
356 |
credsconf.set(shortid + "pass", cred.second.password);
|
|
|
357 |
// Saving the encrypted version is redundant, but it
|
|
|
358 |
// avoids having to run encrypt on load.
|
|
|
359 |
credsconf.set(shortid + "epass", cred.second.encryptedpass);
|
|
|
360 |
}
|
|
|
361 |
}
|
|
|
362 |
|
|
|
363 |
// Try to load from configuration file at startup. Avoids having
|
|
|
364 |
// to enter the password on the CP if it was previously saved.
|
|
|
365 |
void tryLoad() {
|
|
|
366 |
if (!doingsavetofile()) {
|
|
|
367 |
return;
|
|
|
368 |
}
|
|
|
369 |
string credsfile = path_cat(cachedir, "screds");
|
|
|
370 |
ConfSimple credsconf(credsfile.c_str(), 1);
|
|
|
371 |
if (!credsconf.ok()) {
|
|
|
372 |
LOGDEB("OHCredentials: error opening for read (probably not an "
|
|
|
373 |
"error)" << credsfile << " errno " << errno << endl);
|
|
|
374 |
return;
|
|
|
375 |
}
|
|
|
376 |
for (const auto& service : idmap) {
|
|
|
377 |
const string& id = service.first;
|
|
|
378 |
const string& shortid = service.second;
|
|
|
379 |
string user, pass, epass;
|
|
|
380 |
if (credsconf.get(shortid + "user", user) &&
|
|
|
381 |
credsconf.get(shortid + "pass", pass) &&
|
|
|
382 |
credsconf.get(shortid + "epass", epass)) {
|
|
|
383 |
LOGDEB("OHCreds: using saved creds for " << id << endl);
|
|
|
384 |
creds[id] = ServiceCreds(shortid, user, pass, epass);
|
|
|
385 |
}
|
|
|
386 |
}
|
341 |
}
|
387 |
}
|
342 |
|
388 |
|
343 |
ExecCmd cmd;
|
389 |
ExecCmd cmd;
|
344 |
string cachedir;
|
390 |
string cachedir;
|
345 |
string keyfile;
|
391 |
string keyfile;
|