Switch to side-by-side view

--- a/src/ohcredentials.cxx
+++ b/src/ohcredentials.cxx
@@ -142,7 +142,7 @@
     // server gateway module, from which we only use a separate method
     // which logs-in and returns the auth data (token, etc.)
     bool maybeStartCmd() {
-        LOGDEB("ServiceCreds: " << servicename << " maybeStartCmd()\n");
+        LOGDEB1("ServiceCreds: " << servicename << " maybeStartCmd()\n");
         if (nullptr == cmd) {
             cmd = new CmdTalk(30);
         }
@@ -267,7 +267,7 @@
             LOGERR("OHCredentials: could not read public key\n");
             return;
         }
-
+        tryLoad();
         LOGDEB1("OHCredentials: my public key:\n" << pubkey << endl);
     }
 
@@ -293,18 +293,15 @@
     }
 
     bool save() {
-        bool saveohcredentials = true;
-        string val;
-        if (g_config && g_config->get("saveohcredentials", val)) {
-            saveohcredentials = stringToBool(val);
-        }
+        bool saveohcredentials = doingsavetofile();
         // We share the creds with the media server process because it
         // needs them for url translation If saveohcredentials is
         // true, we use a file, which can also be used by the regular
         // media server plugin, for possible later access without
-        // ohcredentials. If it's false, we use a shared mem segment,
-        // and the user/pass would have to be set in
-        // /etc/upmpdcli.conf for the regular plugin to work.
+        // ohcredentials (e.g. with another non-kazoo CP). If it's
+        // false, we use a shared mem segment, and the user/pass would
+        // have to be set in /etc/upmpdcli.conf for the media server
+        // plugin to work.
         if (saveohcredentials) {
             string credsfile = path_cat(cachedir, "screds");
             ConfSimple credsconf(credsfile.c_str());
@@ -313,31 +310,80 @@
                        " errno " << errno << endl);
                 return false;
             }
-            for (const auto& cred : creds) {
-                credsconf.set(cred.second.servicename + "user", cred.second.user);
-                credsconf.set(cred.second.servicename + "pass", cred.second.password);
-            }
+            saveToConfTree(credsconf);
             chmod(credsfile.c_str(), 0600);
         } else {
             string data;
             ConfSimple credsconf(data);
-            for (const auto& cred : creds) {
-                credsconf.set(cred.second.servicename + "user", cred.second.user);
-                credsconf.set(cred.second.servicename + "pass", cred.second.password);
-            }
-            LockableShmSeg seg(ohcreds_segpath, ohcreds_segid, ohcreds_segsize, true);
+            saveToConfTree(credsconf);
+            LockableShmSeg seg(ohcreds_segpath, ohcreds_segid, ohcreds_segsize,
+                               true);
             if (!seg.ok()) {
-                LOGERR("OHCredentials: shared memory segment allocate/attach failed\n");
+                LOGERR("OHCredentials: shared memory segment allocate/attach "
+                       "failed\n");
                 return false;
             }
             LockableShmSeg::Accessor access(seg);
             char *cp = (char *)(access.getseg());
             ostringstream strm;
             credsconf.write(strm);
-            strcpy(cp, strm.str().c_str());
+            if (strm.str().size() >= ohcreds_segsize - 1) {
+                LOGERR("OHCredentials: creds size " << strm.str().size() <<
+                       "won't fit in SHM segment\n");
+                return false;
+            }
+            strncpy(cp, strm.str().c_str(), ohcreds_segsize);
             LOGDEB1("OHCredentials: shm seg content: [" << cp << "]\n");
         }
         return true;
+    }
+
+    //// This could be a private part if we were not all friends here /////
+    
+    bool doingsavetofile() {
+        bool saveohcredentials = true;
+        string val;
+        if (g_config && g_config->get("saveohcredentials", val)) {
+            saveohcredentials = stringToBool(val);
+        }
+        return saveohcredentials;
+    }        
+
+    void saveToConfTree(ConfSimple& credsconf) {
+        for (const auto& cred : creds) {
+            const string& shortid = cred.second.servicename;
+            credsconf.set(shortid + "user", cred.second.user);
+            credsconf.set(shortid + "pass", cred.second.password);
+            // Saving the encrypted version is redundant, but it
+            // avoids having to run encrypt on load.
+            credsconf.set(shortid + "epass", cred.second.encryptedpass);
+        }
+    }
+
+    // Try to load from configuration file at startup. Avoids having
+    // to enter the password on the CP if it was previously saved.
+    void tryLoad() {
+        if (!doingsavetofile()) {
+            return;
+        }
+        string credsfile = path_cat(cachedir, "screds");
+        ConfSimple credsconf(credsfile.c_str(), 1);
+        if (!credsconf.ok()) {
+            LOGDEB("OHCredentials: error opening for read (probably not an "
+                   "error)" << credsfile << " errno " << errno << endl);
+            return;
+        }
+        for (const auto& service : idmap) {
+            const string& id = service.first;
+            const string& shortid = service.second;
+            string user, pass, epass;
+            if (credsconf.get(shortid + "user", user) && 
+                credsconf.get(shortid + "pass", pass) && 
+                credsconf.get(shortid + "epass", epass)) {
+                LOGDEB("OHCreds: using saved creds for " << id << endl);
+                creds[id] = ServiceCreds(shortid, user, pass, epass);
+            }
+        }
     }
     
     ExecCmd cmd;