Guard XMPP password with option guard

  * instead of filtering access to stored in public place
    restricted data, better store restricted data somewhere else
  * add xmpp_init() and xmpp_have_password (non-api)

diff -r d5d7361a99c0 mcabber/mcabber/commands.c
--- a/mcabber/mcabber/commands.c	Tue Nov 11 21:10:14 2014 +0200
+++ b/mcabber/mcabber/commands.c	Tue Nov 11 21:12:47 2014 +0200
@@ -2286,10 +2286,8 @@
 
 static void list_option_cb(char *k, char *v, void *f)
 {
-  if (strcmp(k, "password")) {
-    GSList **list = f;
-    *list = g_slist_insert_sorted(*list, k, (GCompareFunc)strcmp);
-  }
+  GSList **list = f;
+  *list = g_slist_insert_sorted(*list, k, (GCompareFunc)strcmp);
 }
 
 static void do_set(char *arg)
diff -r d5d7361a99c0 mcabber/mcabber/main.c
--- a/mcabber/mcabber/main.c	Tue Nov 11 21:10:14 2014 +0200
+++ b/mcabber/mcabber/main.c	Tue Nov 11 21:12:47 2014 +0200
@@ -389,6 +389,7 @@
   scr_init_locale_charset();
   ut_init_debug();
   help_init();
+  xmpp_init();
 
   /* Parsing config file... */
   ret = cfg_read_file(configFile, TRUE);
@@ -410,8 +411,9 @@
 
   /* If no password is stored, we ask for it before entering
      ncurses mode -- unless the username is unknown. */
-  if (settings_opt_get("jid") && !settings_opt_get("password")) {
+  if (settings_opt_get("jid") && !xmpp_have_password) {
     char *pwd = ask_password("your Jabber password");
+    /* Will be intercepted by guard */
     settings_set(SETTINGS_TYPE_OPTION, "password", pwd);
     g_free(pwd);
   }
diff -r d5d7361a99c0 mcabber/mcabber/xmpp.c
--- a/mcabber/mcabber/xmpp.c	Tue Nov 11 21:10:14 2014 +0200
+++ b/mcabber/mcabber/xmpp.c	Tue Nov 11 21:12:47 2014 +0200
@@ -23,6 +23,8 @@
  */
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
 
 #include "xmpp.h"
 #include "xmpp_helper.h"
@@ -54,6 +56,9 @@
 static enum imstatus mywantedstatus = available;
 gchar *mystatusmsg;
 
+static char *xmpp_password = NULL;
+gboolean xmpp_have_password = FALSE;
+
 char imstatus2char[imstatus_size+1] = {
     '_', 'o', 'f', 'd', 'n', 'a', 'i', '\0'
 };
@@ -778,16 +783,15 @@
   GError *error = NULL;
 
   if (success) {
-    const char *password, *resource;
+    const char *resource;
     char *username;
     username   = jid_get_username(settings_opt_get("jid"));
-    password   = settings_opt_get("password");
     resource   = strchr(lm_connection_get_jid(connection),
                         JID_RESOURCE_SEPARATOR);
     if (resource)
       resource++;
 
-    if (!lm_connection_authenticate(lconnection, username, password, resource,
+    if (!lm_connection_authenticate(lconnection, username, xmpp_password, resource,
                                     connection_auth_cb, NULL, FALSE, &error)) {
       scr_LogPrint(LPRINT_LOGNORM, "Failed to authenticate: %s",
                    error->message);
@@ -1687,13 +1691,37 @@
   }
 }
 
+static gchar *xmpp_password_guard(const gchar *key, const gchar *new_value)
+{
+  if (xmpp_password) {
+    size_t len = strlen(xmpp_password);
+    memset(xmpp_password, '\0', len);
+    if (munlock(xmpp_password, len))
+      scr_LogPrint(LPRINT_DEBUG, "password guard: Cannot unlock memory: %s.",
+                   strerror(errno));
+    g_free(xmpp_password);
+  }
+  xmpp_password = g_strdup(new_value);
+  if (xmpp_password) {
+    if (mlock(xmpp_password, strlen(xmpp_password)))
+      scr_LogPrint(LPRINT_DEBUG, "password guard: Cannot lock memory: %s.",
+                   strerror(errno));
+    xmpp_have_password = TRUE;
+  }
+  return NULL;
+}
+
+void xmpp_init(void)
+{
+  settings_set_guard("password", xmpp_password_guard);
+}
 
 //  xmpp_connect()
 // Return a non-zero value if there's an obvious problem
 // (no JID, no password, etc.)
 gint xmpp_connect(void)
 {
-  const char *userjid, *password, *resource, *servername, *ssl_fpr;
+  const char *userjid, *resource, *servername, *ssl_fpr;
   char *dynresource = NULL;
   char fpr[16];
   const char *proxy_host;
@@ -1710,7 +1738,6 @@
 
   servername  = settings_opt_get("server");
   userjid     = settings_opt_get("jid");
-  password    = settings_opt_get("password");
   resource    = settings_opt_get("resource");
   proxy_host  = settings_opt_get("proxy_host");
   ssl_fpr     = settings_opt_get("ssl_fingerprint");
@@ -1719,7 +1746,7 @@
     scr_LogPrint(LPRINT_LOGNORM, "Your JID has not been specified!");
     return -1;
   }
-  if (!password) {
+  if (!xmpp_password) {
     scr_LogPrint(LPRINT_LOGNORM, "Your password has not been specified!");
     return -1;
   }
diff -r d5d7361a99c0 mcabber/mcabber/xmpp.h
--- a/mcabber/mcabber/xmpp.h	Tue Nov 11 21:10:14 2014 +0200
+++ b/mcabber/mcabber/xmpp.h	Tue Nov 11 21:12:47 2014 +0200
@@ -34,7 +34,9 @@
 
 extern LmConnection* lconnection;
 extern LmSSL* lssl;
+extern gboolean xmpp_have_password; /* private */
 
+void xmpp_init(void); /* private */
 int  xmpp_connect(void);
 void xmpp_disconnect(void);
 gboolean xmpp_is_online(void);
