commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg-269-g558a5b1
Date: Mon, 25 May 2009 20:53:13 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=558a5b14c77602a3e416cd37e1e9bb4685967370

The branch, master has been updated
       via  558a5b14c77602a3e416cd37e1e9bb4685967370 (commit)
      from  cbdb11e15c5c46c7e68602fde5de16bcd6ed4842 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 558a5b14c77602a3e416cd37e1e9bb4685967370
Author: Sergey Poznyakoff <address@hidden>
Date:   Mon May 25 23:52:32 2009 +0300

    * include/mailutils/secret.h: New file.
    * include/mailutils/types.hin (mu_secret_t): New type.
    * include/mailutils/auth.h (mu_ticket_destroy): Remove 2nd arg (owner).
    (mu_ticket_ref, mu_ticket_unref): New functions.
    (mu_ticket_set_destroy): New function.
    (mu_ticket_set_pop): Remove.
    (mu_ticket_get_cred, mu_ticket_set_get_cred): New functions.
    (mu_ticket_get_data): Return data pointer.
    (mu_ticket_set_secret, mu_ticket_set_plain): New functions.
    (mu_wicket_create): Remove 2nd arg.
    (mu_wicket_set_filename, mu_wicket_get_filename): Remove.
    (mu_wicket_set_ticket): Remove.
    (mu_wicket_get_ticket): Change proto.
    (mu_wicket_set_destroy, mu_wicket_set_data)
    (mu_wicket_get_data, mu_wicket_set_get_ticket): New functions.
    (mu_file_wicket_create): New function.
    * include/mailutils/mailutils.h: Include secret.h
    [MU_COMPAT]: Remove.
    * include/mailutils/url.h (mu_url_sget_passwd, mu_url_aget_passwd)
    (mu_url_get_passwd)
    (mu_url_get_secret): New function.
    
    * libproto/include/auth0.h: Rewrite.
    * libproto/include/imap0.h (struct _f_imap): Replace passwd with
    mu_secret_t secret.
    * libproto/include/url0.h (struct _mu_url): Replace passwd with
    mu_secret_t secret.
    (_get_passwd): Replace with _get_secret
    
    * mailbox/secret.c: New function.
    * mailbox/Makefile.am (libmailutils_la_SOURCES): Add secret.c.
    
    * mailbox/ticket.c: Rewrite from scratch.
    * mailbox/wicket.c: Rewrite from scratch.
    
    * libproto/imap/folder.c: Rewrite using mu_secret_t.
    * libproto/pop/mbox.c: Rewrite using mu_secret_t.
    
    * libproto/mailer/prog.c, libproto/mailer/sendmail.c,
    mailbox/auth.c, mailbox/url.c, movemail/movemail.c: Reflect changes
    to ticket/wicket system.
    * mailbox/mbx_default.c: Use new mu_wicket_t functions.
    
    * python/libmu_py/auth.c (api_wicket_get_filename)
    (api_wicket_set_filename): Remove. Not applicable any more.
    * python/libmu_py/url.c (api_url_get_passwd): Temporarly
    commented out.
    
    * include/mailutils/Makefile.am (pkginclude_HEADERS): Add secret.h.
    * examples/url-parse.c: Use mu_secret_t calls.
    
    * imap4d/namespace.c: Minor changes.
    * libmu_auth/pam.c: Likewise.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                 |    6 +-
 examples/url-parse.c                 |   20 ++-
 imap4d/namespace.c                   |    6 +-
 include/mailutils/Makefile.am        |    1 +
 include/mailutils/auth.h             |   56 +++--
 include/mailutils/mailutils.h        |    5 +-
 include/mailutils/{io.h => secret.h} |   21 +-
 include/mailutils/types.hin          |    1 +
 include/mailutils/url.h              |    4 +-
 libmu_auth/pam.c                     |    6 +-
 libproto/imap/folder.c               |   39 ++--
 libproto/include/auth0.h             |   23 +-
 libproto/include/imap0.h             |    5 +-
 libproto/include/url0.h              |    4 +-
 libproto/mailer/prog.c               |    2 +-
 libproto/mailer/sendmail.c           |    2 +-
 libproto/pop/mbox.c                  |   64 +++--
 mailbox/Makefile.am                  |    1 +
 mailbox/auth.c                       |    6 +-
 mailbox/mbx_default.c                |    4 +-
 mailbox/secret.c                     |  135 +++++++++
 mailbox/ticket.c                     |  159 +++++++---
 mailbox/url.c                        |  248 ++++++++++------
 mailbox/wicket.c                     |  545 ++++++++++++++-------------------
 movemail/movemail.c                  |   33 +--
 python/libmu_py/auth.c               |   42 +---
 python/libmu_py/url.c                |    6 +
 27 files changed, 831 insertions(+), 613 deletions(-)
 copy include/mailutils/{io.h => secret.h} (65%)
 create mode 100644 mailbox/secret.c

diff --git a/NEWS b/NEWS
index 832d30f..b6babd8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2009-04-14
+GNU mailutils NEWS -- history of user-visible changes. 2009-05-25
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 
 2008, 2009 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -20,6 +20,10 @@ namespace and visible home directory.
 
 * API
 
+* Wicket/Ticket functions
+
+[FIXME: Describe]
+
 * New mailbox formats
 
 Three new append-only mailbox formats are introduced.  The URL syntax of
diff --git a/examples/url-parse.c b/examples/url-parse.c
index f53c3eb..d1a35c4 100644
--- a/examples/url-parse.c
+++ b/examples/url-parse.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2007, 2009 Free Software Foundation, Inc.
 
    GNU Mailutils is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include <mailutils/error.h>
 #include <mailutils/errno.h>
 #include <mailutils/url.h>
+#include <mailutils/secret.h>
 
 #define CAT2(a,b) a ## b
 
@@ -84,6 +85,7 @@ main ()
     {
       int rc;
       const char *buf;
+      mu_secret_t secret;
       
       str[strlen (str) - 1] = '\0';     /* chop newline */
       if (strspn (str, " \t") == strlen (str))
@@ -104,7 +106,21 @@ main ()
 
       GET_AND_PRINT (scheme, u, buf, rc);
       GET_AND_PRINT (user, u, buf, rc);
-      GET_AND_PRINT (passwd, u, buf, rc);
+
+      rc = mu_url_get_secret (u, &secret);
+      if (rc == MU_ERR_NOENT)
+       printf ("\tpasswd <>\n");
+      else if (rc)
+       {
+         mu_error ("cannot get %s: %s", "passwd", mu_strerror (rc));
+         exit (1);
+        }
+      else
+       {
+         printf ("\tpasswd <%s>\n", mu_secret_password (secret));
+         mu_secret_password_unref (secret);
+       }
+      
       GET_AND_PRINT (auth, u, buf, rc);
       GET_AND_PRINT (host, u, buf, rc);
 
diff --git a/imap4d/namespace.c b/imap4d/namespace.c
index 63636cf..c6d344d 100644
--- a/imap4d/namespace.c
+++ b/imap4d/namespace.c
@@ -23,8 +23,8 @@ typedef int (*nsfp_t) (void *closure, int ns, char *path, int 
delim);
 
 mu_list_t namespace[NS_MAX];
 
-static char *
-printable_pathname (char *str)
+static const char *
+printable_pathname (const char *str)
 {
   if (strncmp (str, imap4d_homedir, strlen (imap4d_homedir)) == 0)
     {
@@ -39,7 +39,7 @@ static int
 print_namespace_fun (void *item, void *data)
 {
   int *pcount = data;
-  char *dir = printable_pathname (item);
+  const char *dir = printable_pathname (item);
   char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
   if ((*pcount)++)
     util_send (" ");
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index f9198c1..3d9efc6 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -85,6 +85,7 @@ pkginclude_HEADERS = \
  refcount.h\
  registrar.h\
  sha1.h\
+ secret.h\
  server.h\
  sieve.h\
  stream.h\
diff --git a/include/mailutils/auth.h b/include/mailutils/auth.h
index 3112e03..7876b95 100644
--- a/include/mailutils/auth.h
+++ b/include/mailutils/auth.h
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2005, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -25,16 +26,29 @@
 extern "C" {
 #endif
 
-extern int  mu_ticket_create          (mu_ticket_t *, void *owner);
-extern void mu_ticket_destroy         (mu_ticket_t *, void *owner);
-extern int  mu_ticket_set_destroy     (mu_ticket_t, void (*) (mu_ticket_t), 
void *);
+extern int  mu_ticket_create          (mu_ticket_t *, void *);
+extern int mu_ticket_ref              (mu_ticket_t);
+extern int mu_ticket_unref            (mu_ticket_t);
+extern void mu_ticket_destroy         (mu_ticket_t *);
+extern int  mu_ticket_set_destroy     (mu_ticket_t,
+                                      void (*) (mu_ticket_t), void *);
 extern void *mu_ticket_get_owner      (mu_ticket_t);
 
-extern int mu_ticket_set_pop          (mu_ticket_t, 
-                                    int (*_pop) (mu_ticket_t, mu_url_t, const 
char *, char **), void *);
-extern int mu_ticket_pop              (mu_ticket_t, mu_url_t, const char *, 
char **);
+extern int mu_ticket_get_cred         (mu_ticket_t ticket,
+                                      mu_url_t url, const char *challenge,
+                                      char **pplain, mu_secret_t *psec);
+
+extern int mu_ticket_set_get_cred     (mu_ticket_t,
+                                      int  (*) (mu_ticket_t, mu_url_t,
+                                                const char *,
+                                                char **, mu_secret_t *),
+                                      void *);
+
 extern int mu_ticket_set_data         (mu_ticket_t, void *, void *owner);
-extern int mu_ticket_get_data         (mu_ticket_t, void **);
+extern void *mu_ticket_get_data       (mu_ticket_t);
+
+extern int mu_ticket_set_secret (mu_ticket_t ticket, mu_secret_t secret);
+int mu_ticket_set_plain (mu_ticket_t ticket, const char *text);
 
 extern int mu_authority_create           (mu_authority_t *, mu_ticket_t, void 
*);
 extern void mu_authority_destroy         (mu_authority_t *, void *);
@@ -42,19 +56,25 @@ extern void *mu_authority_get_owner      (mu_authority_t);
 extern int mu_authority_set_ticket       (mu_authority_t, mu_ticket_t);
 extern int mu_authority_get_ticket       (mu_authority_t, mu_ticket_t *);
 extern int mu_authority_authenticate     (mu_authority_t);
-extern int mu_authority_set_authenticate (mu_authority_t, 
-                                            int (*_authenticate) 
(mu_authority_t), void *);
+extern int mu_authority_set_authenticate (mu_authority_t,
+                                           int (*_authenticate) 
(mu_authority_t), void *);
 
 extern int mu_authority_create_null      (mu_authority_t *pauthority, void 
*owner);
 
-extern int  mu_wicket_create       (mu_wicket_t *, const char *);
-extern void mu_wicket_destroy      (mu_wicket_t *);
-extern int  mu_wicket_set_filename (mu_wicket_t, const char *);
-extern int  mu_wicket_get_filename (mu_wicket_t, char *, size_t, size_t *);
-extern int  mu_wicket_set_ticket   (mu_wicket_t, 
-                                 int (*) (mu_wicket_t, const char *,
-                                const char *, mu_ticket_t *));
-extern int  mu_wicket_get_ticket   (mu_wicket_t, mu_ticket_t *, const char *, 
const char *);
+extern int mu_wicket_create       (mu_wicket_t *);
+extern int mu_wicket_get_ticket (mu_wicket_t wicket, const char *user,
+                                mu_ticket_t *pticket);
+extern int mu_wicket_ref (mu_wicket_t wicket);
+extern int mu_wicket_unref (mu_wicket_t wicket);
+extern void mu_wicket_destroy (mu_wicket_t *pwicket);
+extern int mu_wicket_set_destroy (mu_wicket_t wicket,
+                                 void (*_destroy) (mu_wicket_t));
+extern int mu_wicket_set_data (mu_wicket_t wicket, void *data);
+extern void *mu_wicket_get_data (mu_wicket_t wicket);
+extern int mu_wicket_set_get_ticket (mu_wicket_t wicket,
+                             int (*_get_ticket) (mu_wicket_t, void *,
+                                                 const char *, mu_ticket_t *));
+extern int mu_file_wicket_create (mu_wicket_t *pwicket, const char *filename);
 
 #ifdef __cplusplus
 }
diff --git a/include/mailutils/mailutils.h b/include/mailutils/mailutils.h
index b8b38dd..a297ed7 100644
--- a/include/mailutils/mailutils.h
+++ b/include/mailutils/mailutils.h
@@ -62,9 +62,6 @@
 #include <mailutils/version.h>
 #include <mailutils/vartab.h>
 #include <mailutils/io.h>
-
-#ifdef MU_COMPAT
-# error "Version 0.6 is no longer supported. Please, update your program."
-#endif
+#include <mailutils/secret.h>
 
 /* EOF */
diff --git a/include/mailutils/io.h b/include/mailutils/secret.h
similarity index 65%
copy from include/mailutils/io.h
copy to include/mailutils/secret.h
index b108743..24df73a 100644
--- a/include/mailutils/io.h
+++ b/include/mailutils/secret.h
@@ -16,19 +16,26 @@
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301 USA */
 
-#ifndef _MAILUTILS_IO_H
-#define _MAILUTILS_IO_H
+#ifndef _MAILUTILS_SECRET_H
+#define _MAILUTILS_SECRET_H
+
+#include <mailutils/types.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-int mu_asprintf (char **pbuf, const char *fmt, ...);
-int mu_asnprintf (char **pbuf, size_t *psize, const char *fmt, ...);
-int mu_vasnprintf (char **pbuf, size_t *psize, const char *fmt, va_list ap);
-
+int mu_secret_create (mu_secret_t *psec, const char *value, size_t len);
+int mu_secret_dup (mu_secret_t sec, mu_secret_t *newsec);
+void mu_secret_destroy (mu_secret_t *psec);
+const char *mu_secret_password (mu_secret_t sec);
+void mu_secret_password_unref (mu_secret_t sec);
+size_t mu_secret_length (mu_secret_t sec);
+void mu_secret_ref (mu_secret_t sec);
+int mu_secret_unref (mu_secret_t sec);
+  
 #ifdef __cplusplus
 }
 #endif
-
+  
 #endif
diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin
index 94fcc02..9c60249 100644
--- a/include/mailutils/types.hin
+++ b/include/mailutils/types.hin
@@ -112,6 +112,7 @@ typedef struct _mu_ip_server *mu_ip_server_t;
 typedef struct _mu_m_server *mu_m_server_t;
 typedef struct _mu_opool *mu_opool_t;
 typedef struct _mu_progmailer *mu_progmailer_t;
+typedef struct _mu_secret *mu_secret_t;
   
 #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
 #define MU_FOLDER_ATTRIBUTE_FILE      0x002
diff --git a/include/mailutils/url.h b/include/mailutils/url.h
index 6a43bc1..ea61f84 100644
--- a/include/mailutils/url.h
+++ b/include/mailutils/url.h
@@ -41,9 +41,7 @@ extern int mu_url_sget_user  (const mu_url_t, const char **);
 extern int mu_url_aget_user  (const mu_url_t, char **);  
 extern int mu_url_get_user  (const mu_url_t, char *, size_t, size_t *);
 
-extern int mu_url_sget_passwd  (const mu_url_t, const char **);
-extern int mu_url_aget_passwd  (const mu_url_t, char **);  
-extern int mu_url_get_passwd  (const mu_url_t, char *, size_t, size_t *);
+extern int mu_url_get_secret (const mu_url_t url, mu_secret_t *psecret);
   
 extern int mu_url_sget_auth  (const mu_url_t, const char **);
 extern int mu_url_aget_auth  (const mu_url_t, char **);  
diff --git a/libmu_auth/pam.c b/libmu_auth/pam.c
index 903ba24..e6a3332 100644
--- a/libmu_auth/pam.c
+++ b/libmu_auth/pam.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2002, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -64,6 +64,10 @@ static char *_user;
   while (0)
 
 
+#ifndef PAM_AUTHTOK_RECOVER_ERR
+# define PAM_AUTHTOK_RECOVER_ERR PAM_CONV_ERR
+#endif
+
 static int
 mu_pam_conv (int num_msg, const struct pam_message **msg,
             struct pam_response **resp, void *appdata_ptr MU_ARG_UNUSED)
diff --git a/libproto/imap/folder.c b/libproto/imap/folder.c
index 85a7ba8..e34e874 100644
--- a/libproto/imap/folder.c
+++ b/libproto/imap/folder.c
@@ -50,6 +50,7 @@
 #include <mailutils/argcv.h>
 #include <mailutils/tls.h>
 #include <mailutils/nls.h>
+#include <mailutils/secret.h>
 
 /* For dbg purposes set to one to see different level of traffic.  */
 /* Print to stderr the command sent to the IMAP server.  */
@@ -181,40 +182,42 @@ authenticate_imap_login (mu_authority_t auth)
        mu_authority_get_ticket (auth, &ticket);
        if (f_imap->user)
          free (f_imap->user);
-       if (f_imap->passwd)
-         free (f_imap->passwd);
        /* Was it in the URL?  */
        status = mu_url_aget_user (folder->url, &f_imap->user);
         if (status == MU_ERR_NOENT)
-         mu_ticket_pop (ticket, folder->url, "Imap User: ",  &f_imap->user);
+         status = mu_ticket_get_cred (ticket, folder->url,
+                                      "Imap User: ", &f_imap->user, NULL);
+       if (status == MU_ERR_NOENT || f_imap->user == NULL)
+         return MU_ERR_NOUSERNAME;
        else if (status)
          return status;
 
-       status = mu_url_aget_passwd (folder->url, &f_imap->passwd);
+       status = mu_url_get_secret (folder->url, &f_imap->secret);
         if (status == MU_ERR_NOENT)
-         mu_ticket_pop (ticket, folder->url, "Imap Passwd: ",  
-                        &f_imap->passwd);
+         status = mu_ticket_get_cred (ticket, folder->url,
+                                      "Imap Passwd: ",
+                                      NULL, &f_imap->secret);
+       
+       if (status == MU_ERR_NOENT || !f_imap->secret)
+         /* FIXME: Is this always right? The user might legitimately have
+            no password */
+         return MU_ERR_NOPASSWORD;
        else if (status)
          return status;
-
-       if (f_imap->user == NULL)
-         return MU_ERR_NOUSERNAME;
-         
-       if (f_imap->passwd == NULL)
-         return MU_ERR_NOPASSWORD;
-         
+       
        status = imap_writeline (f_imap, "g%u LOGIN \"%s\" \"%s\"\r\n",
-                                f_imap->seq, f_imap->user, f_imap->passwd);
+                                f_imap->seq, f_imap->user,
+                                mu_secret_password (f_imap->secret));
+       mu_secret_password_unref (f_imap->secret);
+       mu_secret_unref (f_imap->secret);
+       f_imap->secret = NULL;
        CHECK_ERROR_CLOSE (folder, f_imap, status);
        MU_DEBUG2 (folder->debug, MU_DEBUG_TRACE, "g%u LOGIN %s *\n",
                   f_imap->seq, f_imap->user);
        f_imap->seq++;
        free (f_imap->user);
        f_imap->user = NULL;
-       /* We have to nuke the passwd.  */
-       memset (f_imap->passwd, '\0', strlen (f_imap->passwd));
-       free (f_imap->passwd);
-       f_imap->passwd = NULL;
+       f_imap->secret = NULL;
        f_imap->state = IMAP_LOGIN;
       }
 
diff --git a/libproto/include/auth0.h b/libproto/include/auth0.h
index 0e108b8..a2db8ca 100644
--- a/libproto/include/auth0.h
+++ b/libproto/include/auth0.h
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2005, 2007  Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2005, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -33,11 +34,17 @@ extern "C" {
 
 struct _mu_ticket
 {
-  void *owner;
-  char *challenge;
+  void *owner;           /* Object owner.  Not actually needed, but retained
+                           for a while. */
+  unsigned int refcnt;   /* Reference counter */
+  char *plain;           /* Plaintext credential (if any) */
+  mu_secret_t secret;    /* Secret credential (if any) */
+  void (*_destroy)  (mu_ticket_t); /* Destroy function */
+  /* Function for obtaining credentials */
+  int  (*_get_cred) (mu_ticket_t, mu_url_t, const char *, char **,
+                    mu_secret_t *);
+  /* Additional data for _get_cred */
   void *data;
-  int  (*_pop)      (mu_ticket_t, mu_url_t, const char *challenge, char **);
-  void (*_destroy)  (mu_ticket_t);
 };
 
 struct _mu_authority
@@ -49,8 +56,10 @@ struct _mu_authority
 
 struct _mu_wicket
 {
-  char *filename;
-  int (*_get_ticket) (mu_wicket_t, const char *, const char *, mu_ticket_t *);
+  unsigned int refcnt;   /* Reference counter */
+  void *data;
+  int (*_get_ticket) (mu_wicket_t, void *, const char *, mu_ticket_t *);
+  void (*_destroy) (mu_wicket_t);
 };
 
 
diff --git a/libproto/include/imap0.h b/libproto/include/imap0.h
index 52c0601..a19d9c1 100644
--- a/libproto/include/imap0.h
+++ b/libproto/include/imap0.h
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2005, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -178,7 +179,7 @@ struct _f_imap
 
   /* Login  */
   char *user;
-  char *passwd;
+  mu_secret_t secret;
 
   /* AUTHENTICATE states */
   enum imap_auth_state auth_state;
diff --git a/libproto/include/url0.h b/libproto/include/url0.h
index 5931d0e..f5de62d 100644
--- a/libproto/include/url0.h
+++ b/libproto/include/url0.h
@@ -35,7 +35,7 @@ struct _mu_url
   char  *name;
   char  *scheme;
   char  *user;
-  char  *passwd;
+  mu_secret_t secret;
   char  *auth;
   char  *host;
   long  port;
@@ -53,7 +53,7 @@ struct _mu_url
   /* Methods */
   int   (*_get_scheme) (const mu_url_t, char *, size_t, size_t *);
   int   (*_get_user)   (const mu_url_t, char *, size_t, size_t *);
-  int   (*_get_passwd) (const mu_url_t, char *, size_t, size_t *);
+  int   (*_get_secret) (const mu_url_t, mu_secret_t *);
   int   (*_get_auth)   (const mu_url_t, char *, size_t, size_t *);
   int   (*_get_host)   (const mu_url_t, char *, size_t, size_t *);
   int   (*_get_port)   (const mu_url_t, long *);
diff --git a/libproto/mailer/prog.c b/libproto/mailer/prog.c
index 4f02b6b..67b4271 100644
--- a/libproto/mailer/prog.c
+++ b/libproto/mailer/prog.c
@@ -69,7 +69,7 @@ static int
 _url_prog_init (mu_url_t url)
 {
   /* not valid in a prog url */
-  if (url->passwd || url->auth || url->host || url->port)
+  if (url->secret || url->auth || url->host || url->port)
     return EINVAL;
   if (!url->path)
     return EINVAL;
diff --git a/libproto/mailer/sendmail.c b/libproto/mailer/sendmail.c
index 8588267..cb42f27 100644
--- a/libproto/mailer/sendmail.c
+++ b/libproto/mailer/sendmail.c
@@ -53,7 +53,7 @@ static int
 _url_sendmail_init (mu_url_t url)
 {
   /* not valid in a sendmail url */
-  if (url->user || url->passwd || url->auth || url->qargc
+  if (url->user || url->secret || url->auth || url->qargc
       || url->host || url->port)
     return EINVAL;
 
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index 1e5182e..655af16 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -51,6 +51,7 @@
 #include <mailutils/property.h>
 #include <mailutils/stream.h>
 #include <mailutils/url.h>
+#include <mailutils/secret.h>
 #include <mailutils/tls.h>
 #include <mailutils/md5.h>
 #include <mailutils/io.h>
@@ -207,7 +208,8 @@ struct _pop_data
 
   int is_updated;
   char *user;     /* Temporary holders for user and passwd.  */
-  char *passwd;   /* Temporary holders for passwd memset (0) when finish.  */
+  mu_secret_t secret;
+  char *digest;
   mu_mailbox_t mbox; /* Back pointer.  */
 } ;
 
@@ -532,22 +534,23 @@ _pop_user (mu_authority_t auth)
          CHECK_ERROR_CLOSE (mbox, mpd, EACCES);
        }
       status = pop_get_passwd (auth);
-      if (status != 0 || mpd->passwd == NULL || mpd->passwd[0] == '\0')
+      if (status != 0 || mpd->secret == NULL)
        {
          pop_writeline (mpd, "QUIT\r\n");
          MU_DEBUG (mbox->debug, MU_DEBUG_PROT, mpd->buffer);
          pop_write (mpd);
          CHECK_ERROR_CLOSE (mbox, mpd, MU_ERR_NOPASSWORD);
        }
-      status = pop_writeline (mpd, "PASS %s\r\n", mpd->passwd);
+      status = pop_writeline (mpd, "PASS %s\r\n",
+                             mu_secret_password (mpd->secret));
+      mu_secret_password_unref (mpd->secret);
+      mu_secret_unref (mpd->secret);
+      mpd->secret = NULL;
       MU_DEBUG (mbox->debug, MU_DEBUG_PROT, "PASS ***\n");
-      /* Leave not trail of the passwd.  */
-      memset (mpd->passwd, '\0', strlen (mpd->passwd));
-      free (mpd->passwd);
-      mpd->passwd = NULL;
       CHECK_ERROR_CLOSE (mbox, mpd, status);
       mpd->state = POP_AUTH_PASS;
-
+      /* FIXME: Merge these two cases */
+        
     case POP_AUTH_PASS:
       /* Send passwd.  */
       status = pop_write (mpd);
@@ -599,7 +602,7 @@ _pop_apop (mu_authority_t auth)
 
       /* Fetch the secret from them.  */
       status = pop_get_passwd (auth);
-      if (status != 0 || mpd->passwd == NULL || mpd->passwd[0] == '\0')
+      if (status != 0 || mpd->secret == NULL)
        {
          CHECK_ERROR_CLOSE (mbox, mpd, EINVAL);
        }
@@ -610,14 +613,14 @@ _pop_apop (mu_authority_t auth)
        {
          CHECK_ERROR_CLOSE (mbox, mpd, status);
        }
-      status = pop_writeline (mpd, "APOP %s %s\r\n", mpd->user, mpd->passwd);
+      status = pop_writeline (mpd, "APOP %s %s\r\n", mpd->user, mpd->digest);
       MU_DEBUG (mbox->debug, MU_DEBUG_PROT, mpd->buffer);
       /* We have to obscure the md5 string.  */
-      memset (mpd->passwd, '\0', strlen (mpd->passwd));
+      memset (mpd->digest, '\0', strlen (mpd->digest));
       free (mpd->user);
-      free (mpd->passwd);
+      free (mpd->digest);
       mpd->user = NULL;
-      mpd->passwd = NULL;
+      mpd->digest = NULL;
       CHECK_ERROR_CLOSE (mbox, mpd, status);
       mpd->state = POP_APOP;
 
@@ -2114,10 +2117,11 @@ pop_get_user (mu_authority_t auth)
   /* Was it in the URL? */
   status = mu_url_aget_user (mbox->url, &mpd->user);
   if (status == MU_ERR_NOENT)
-    mu_ticket_pop (ticket, mbox->url, "Pop User: ",  &mpd->user);
-  else if (status)
-    return status;
-  return 0;
+    status = mu_ticket_get_cred (ticket, mbox->url, "Pop User: ",
+                                &mpd->user, NULL);
+  if (status == MU_ERR_NOENT || mpd->user == NULL)
+    return MU_ERR_NOUSERNAME;  
+  return status;
 }
 
 /* Extract the User from the URL or the ticket.  */
@@ -2131,17 +2135,15 @@ pop_get_passwd (mu_authority_t auth)
   int status;
 
   mu_authority_get_ticket (auth, &ticket);
-  if (mpd->passwd)
-    {
-      free (mpd->passwd);
-      mpd->passwd = NULL;
-    }
   /* Was it in the URL? */
-  status = mu_url_aget_passwd (mbox->url, &mpd->passwd);
+  status = mu_url_get_secret (mbox->url, &mpd->secret);
   if (status == MU_ERR_NOENT)
-    mu_ticket_pop (ticket, mbox->url, "Pop Passwd: ",  &mpd->passwd);
-  else if (status)
-    return status;
+    status = mu_ticket_get_cred (ticket, mbox->url, "Pop Passwd: ",
+                                NULL, &mpd->secret);
+  if (status == MU_ERR_NOENT || !mpd->secret)
+    /* FIXME: Is this always right? The user might legitimately have
+       no password */
+    return MU_ERR_NOPASSWORD;
   return 0;
 }
 
@@ -2189,15 +2191,19 @@ pop_get_md5 (pop_data_t mpd)
 
   mu_md5_init_ctx (&md5context);
   mu_md5_process_bytes (timestamp, strlen (timestamp), &md5context);
-  mu_md5_process_bytes (mpd->passwd, strlen (mpd->passwd), &md5context);
+  mu_md5_process_bytes (mu_secret_password (mpd->secret),
+                       mu_secret_length (mpd->secret),
+                       &md5context);
+  mu_secret_password_unref (mpd->secret);
+  mu_secret_unref (mpd->secret);
+  mpd->secret = NULL;
   mu_md5_finish_ctx (&md5context, md5digest);
   
   for (tmp = digest, n = 0; n < 16; n++, tmp += 2)
     sprintf (tmp, "%02x", md5digest[n]);
   *tmp = '\0';
   free (timestamp);
-  free (mpd->passwd);
-  mpd->passwd = strdup (digest);
+  mpd->digest = strdup (digest);
   return 0;
 }
 
diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am
index 546f853..d115eac 100644
--- a/mailbox/Makefile.am
+++ b/mailbox/Makefile.am
@@ -113,6 +113,7 @@ libmailutils_la_SOURCES = \
  refcount.c\
  rfc2047.c\
  sha1.c\
+ secret.c\
  server.c\
  socket_stream.c\
  stream.c\
diff --git a/mailbox/auth.c b/mailbox/auth.c
index cd05e14..6ffeb08 100644
--- a/mailbox/auth.c
+++ b/mailbox/auth.c
@@ -1,6 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 1999, 2000, 2001, 2004, 2005,
-   2007 Free Software Foundation, Inc.
+   2007, 2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -68,7 +68,7 @@ mu_authority_destroy (mu_authority_t *pauthority, void *owner)
       mu_authority_t authority = *pauthority;
       if (authority->owner == owner)
        {
-         mu_ticket_destroy (&(authority->ticket), authority);
+         mu_ticket_destroy (&authority->ticket);
          free (authority);
        }
       *pauthority = NULL;
@@ -87,7 +87,7 @@ mu_authority_set_ticket (mu_authority_t authority, 
mu_ticket_t ticket)
   if (authority == NULL)
     return EINVAL;
   if (authority->ticket)
-    mu_ticket_destroy (&(authority->ticket), authority);
+    mu_ticket_destroy (&authority->ticket);
   authority->ticket = ticket;
   return 0;
 }
diff --git a/mailbox/mbx_default.c b/mailbox/mbx_default.c
index ac7f9b1..e83435a 100644
--- a/mailbox/mbx_default.c
+++ b/mailbox/mbx_default.c
@@ -350,11 +350,11 @@ attach_auth_ticket (mu_mailbox_t mbox)
   
       MU_DEBUG1 (mbox->debug, MU_DEBUG_TRACE1,
                 "Reading user ticket file %s\n", filename);
-      if ((rc = mu_wicket_create (&wicket, filename)) == 0)
+      if ((rc = mu_file_wicket_create (&wicket, filename)) == 0)
        {
          mu_ticket_t ticket;
       
-         if ((rc = mu_wicket_get_ticket (wicket, &ticket, 0, 0)) == 0)
+         if ((rc = mu_wicket_get_ticket (wicket, NULL, &ticket)) == 0)
            {
              rc = mu_authority_set_ticket (auth, ticket);
              MU_DEBUG1 (mbox->debug, MU_DEBUG_TRACE1,
diff --git a/mailbox/secret.c b/mailbox/secret.c
new file mode 100644
index 0000000..d34bc02
--- /dev/null
+++ b/mailbox/secret.c
@@ -0,0 +1,135 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General
+   Public License along with this library; if not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/types.h>
+#include <mailutils/secret.h>
+#include <mailutils/errno.h>
+
+struct _mu_secret
+{
+  unsigned int refcnt;      /* Number of references to this object */
+  size_t length;            /* Secret length */
+  unsigned char *obptr;     /* Obfuscated data */
+  unsigned char *clptr;     /* Cleartext data */
+  unsigned int clref;       /* Number of references to clptr returned
+                              this far */
+};
+
+static unsigned char xchar;
+
+static void
+obfuscate (const unsigned char *input, unsigned char *output, size_t len)
+{
+  if (!xchar)
+    xchar = random () % 255;
+  while (len--)
+    *output++ = *input++ ^ xchar;
+}
+  
+int
+mu_secret_create (mu_secret_t *psec, const char *value, size_t len)
+{
+  mu_secret_t sec;
+  sec = calloc (1, sizeof (sec[0]) + 2 * (len + 1));
+  if (!sec)
+    return ENOMEM;
+  sec->obptr = (unsigned char*)(sec + 1);
+  sec->clptr = sec->obptr + len + 1;
+  obfuscate (value, sec->obptr, len);
+  sec->length = len;
+  *psec = sec;
+  mu_secret_ref (sec);
+  return 0;
+}
+
+int
+mu_secret_dup (mu_secret_t sec, mu_secret_t *newsec)
+{
+  const char *pass = mu_secret_password (sec);
+  int rc = mu_secret_create (newsec, pass, strlen (pass));
+  mu_secret_password_unref (sec);
+  return rc;
+}
+
+void
+mu_secret_ref (mu_secret_t sec)
+{
+  if (sec)
+    sec->refcnt++;
+}
+
+/* Decrement reference counter in SEC. If it falls to 0, free memory
+   allocated for SEC and return 0. Otherwise, return MU_ERR_EXISTS,
+   indicating that someone else is still holding it.
+   Return EINVAL if sec==NULL. */
+int
+mu_secret_unref (mu_secret_t sec)
+{
+  if (sec)
+    {
+      if (sec->refcnt)
+       sec->refcnt--;
+      if (sec->refcnt == 0)
+       {
+         memset (sec->clptr, 0, sec->length);
+         memset (sec->obptr, 0, sec->length);
+         free (sec);
+         return 0;
+       }
+      return MU_ERR_EXISTS;
+    }
+  return EINVAL;
+}
+
+void
+mu_secret_destroy (mu_secret_t *psec)
+{
+  if (psec && *psec && mu_secret_unref (*psec) == 0)
+    *psec = NULL;
+}
+
+const char *
+mu_secret_password (mu_secret_t sec)
+{
+  if (!sec)
+    return 0;
+  if (sec->clref++ == 0)
+    obfuscate (sec->obptr, sec->clptr, sec->length);
+  return (const char*) sec->clptr;
+}
+
+size_t
+mu_secret_length (mu_secret_t sec)
+{
+  if (!sec)
+    return 0;
+  return sec->length;
+}
+
+void
+mu_secret_password_unref (mu_secret_t sec)
+{
+  if (--sec->clref == 0)
+    memset (sec->clptr, 0, sec->length);
+}
+
diff --git a/mailbox/ticket.c b/mailbox/ticket.c
index 48fea2f..5fabb35 100644
--- a/mailbox/ticket.c
+++ b/mailbox/ticket.c
@@ -1,6 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 1999, 2000, 2001, 2004, 2005,
-   2007 Free Software Foundation, Inc.
+   2007, 2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -31,10 +31,11 @@
 
 #include <mailutils/mutil.h>
 #include <mailutils/errno.h>
+#include <mailutils/secret.h>
 #include <auth0.h>
 
 static void
-echo_off(struct termios *stored_settings)
+echo_off (struct termios *stored_settings)
 {
   struct termios new_settings;
   tcgetattr (0, stored_settings);
@@ -44,7 +45,7 @@ echo_off(struct termios *stored_settings)
 }
 
 static void
-echo_on(struct termios *stored_settings)
+echo_on (struct termios *stored_settings)
 {
   tcsetattr (0, TCSANOW, stored_settings);
 }
@@ -59,31 +60,51 @@ mu_ticket_create (mu_ticket_t *pticket, void *owner)
   if (ticket == NULL)
     return ENOMEM;
   ticket->owner = owner;
+  mu_ticket_ref (ticket);
   *pticket = ticket;
   return 0;
 }
 
-void
-mu_ticket_destroy (mu_ticket_t *pticket, void *owner)
+int
+mu_ticket_ref (mu_ticket_t ticket)
 {
-  if (pticket && *pticket)
+  if (!ticket)
+    return EINVAL;
+  ticket->refcnt++;
+  return 0;
+}
+  
+int
+mu_ticket_unref (mu_ticket_t ticket)
+{
+  if (!ticket)
+    return EINVAL;
+  if (ticket->refcnt)
+    ticket->refcnt--;
+  if (ticket->refcnt == 0)
     {
-      mu_ticket_t ticket = *pticket;
-      if (ticket->owner == owner)
-       {
-         if (ticket->_destroy)
-           ticket->_destroy (ticket);
-         if (ticket->challenge)
-           free (ticket->challenge);
-         free (ticket);
-       }
-      *pticket = NULL;
+      if (ticket->plain)
+       free (ticket->plain);
+      if (ticket->secret)
+       mu_secret_destroy (&ticket->secret);
+      if (ticket->_destroy)
+       ticket->_destroy (ticket);
+      free (ticket);
+      return 0;
     }
+  return MU_ERR_EXISTS;
+}
+      
+void
+mu_ticket_destroy (mu_ticket_t *pticket)
+{
+  if (pticket && *pticket && mu_ticket_unref (*pticket) == 0)
+    *pticket = NULL;
 }
 
 int
-mu_ticket_set_destroy (mu_ticket_t ticket, void (*_destroy) (mu_ticket_t),
-                   void *owner)
+mu_ticket_set_destroy (mu_ticket_t ticket,
+                      void (*_destroy) (mu_ticket_t), void *owner)
 {
   if (ticket == NULL)
     return EINVAL;
@@ -100,39 +121,83 @@ mu_ticket_get_owner (mu_ticket_t ticket)
 }
 
 int
-mu_ticket_set_pop (mu_ticket_t ticket,
-               int (*_pop) (mu_ticket_t, mu_url_t, const char *, char **),
-               void *owner)
+mu_ticket_set_get_cred (mu_ticket_t ticket,
+                       int  (*_get_cred) (mu_ticket_t, mu_url_t,
+                                          const char *,
+                                          char **, mu_secret_t *),
+                       void *owner)
 {
   if (ticket == NULL)
     return EINVAL;
   if (ticket->owner != owner)
     return EACCES;
-  ticket->_pop = _pop;
+  ticket->_get_cred = _get_cred;
   return 0;
 }
 
 int
-mu_ticket_pop (mu_ticket_t ticket, mu_url_t url, const char *challenge, char 
**parg)
+mu_ticket_set_secret (mu_ticket_t ticket, mu_secret_t secret)
+{
+  if (ticket == NULL)
+    return EINVAL;
+  if (ticket->secret)
+    mu_secret_unref (ticket->secret);
+  mu_secret_ref (secret);
+  ticket->secret = secret;
+  return 0;
+}
+
+int
+mu_ticket_set_plain (mu_ticket_t ticket, const char *text)
 {
-  int rc = -1;
-  
   if (ticket == NULL)
     return EINVAL;
-  if (parg == NULL)
+  if (ticket->plain)
+    free (ticket->plain);
+  ticket->plain = strdup (text);
+  if (!ticket->plain)
+    return ENOMEM;
+  return 0;
+}
+
+int
+mu_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge,
+                   char **pplain, mu_secret_t *psec)
+{
+  int rc = 0;
+  char arg[256];
+  
+  if (ticket == NULL || (pplain && psec))
+    return EINVAL;
+  if (pplain == NULL && psec == NULL)
     return MU_ERR_OUT_PTR_NULL;
-  if (ticket->_pop)
-    rc = ticket->_pop (ticket, url, challenge, parg);
-  if (rc != 0 && isatty (fileno (stdin)))
+
+  if (ticket->_get_cred)
+    {
+      int res = ticket->_get_cred (ticket, url, challenge, pplain, psec);
+      if (res == 0)
+       return res;
+    }
+
+  if (pplain && ticket->plain)
+    {
+      *pplain = strdup (ticket->plain);
+      if (!*pplain)
+       return ENOMEM;
+    }
+  
+  if (psec && ticket->secret)
+    {
+      mu_secret_ref (ticket->secret);
+      *psec = ticket->secret;
+      return 0;
+    }
+  
+  if (isatty (fileno (stdin)))
     {
-      char arg[256];
       struct termios stored_settings;
-      int echo = 1;
+      int echo = pplain != NULL;
 
-      /* Being smart if we see "Passwd" and turning off echo.  */
-      if (strstr (challenge, "ass") != NULL
-         || strstr (challenge, "ASS") != NULL)
-       echo = 0;
       printf ("%s", challenge);
       fflush (stdout);
       if (!echo)
@@ -145,21 +210,25 @@ mu_ticket_pop (mu_ticket_t ticket, mu_url_t url, const 
char *challenge, char **p
          fflush (stdout);
        }
       arg [strlen (arg) - 1] = '\0'; /* nuke the trailing line.  */
-      *parg = strdup (arg);
-      rc = 0;
     }
+
+  if (pplain)
+    {
+      *pplain = strdup (arg);
+      if (!*pplain)
+       return ENOMEM;
+    }
+  else
+    rc = mu_secret_create (psec, arg, strlen (arg));
   return rc;
 }
 
-int
-mu_ticket_get_data (mu_ticket_t ticket, void **data)
+void *
+mu_ticket_get_data (mu_ticket_t ticket)
 {
-  if (ticket == NULL)
-    return EINVAL;
-  if (data == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  *data = ticket->data;
-  return 0;
+  if (!ticket)
+    return NULL;
+  return ticket->data;
 }
 
 int
diff --git a/mailbox/url.c b/mailbox/url.c
index 8bbdfba..5156dea 100644
--- a/mailbox/url.c
+++ b/mailbox/url.c
@@ -32,12 +32,13 @@
 #include <mailutils/mutil.h>
 #include <mailutils/errno.h>
 #include <mailutils/argcv.h>
+#include <mailutils/secret.h>
 #include <url0.h>
 
 #define AC2(a,b) a ## b
 #define AC4(a,b,c,d) a ## b ## c ## d
 
-static int url_parse0 (mu_url_t, char *);
+static int url_parse0 (mu_url_t, char *, size_t *poff);
 
 static int
 parse_query (const char *query,
@@ -62,7 +63,7 @@ parse_query (const char *query,
   if (p == query)
     return 0;
   count++;
-  
+
   v = calloc (count + 1, sizeof (v[0]));
   for (i = 0, p = query; i < count; i++)
     {
@@ -81,7 +82,7 @@ parse_query (const char *query,
   *pargv = v;
   return 0;
 }
-  
+
 int
 mu_url_create (mu_url_t *purl, const char *name)
 {
@@ -123,7 +124,8 @@ mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
   size_t argc;
   char **argv;
   int rc;
-  
+  mu_secret_t sec;
+
 #define URLCOPY(what)                                          \
   do                                                           \
     {                                                          \
@@ -132,7 +134,7 @@ mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
        {                                                       \
          if ((new_url->what = strdup (str)) == NULL)           \
            return ENOMEM;                                      \
-       }                                                       \
+       }                                                       \
       else if (rc != MU_ERR_NOENT)                             \
        return rc;                                              \
     }                                                          \
@@ -140,7 +142,19 @@ mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
 
   URLCOPY (scheme);
   URLCOPY (user);
-  URLCOPY (passwd);
+
+  rc = mu_url_get_secret (old_url, &sec);
+  if (rc == MU_ERR_NOENT)
+    new_url->secret = NULL;
+  else if (rc)
+    return rc;
+  else
+    {
+      rc = mu_secret_dup (sec, &new_url->secret);
+      if (rc)
+       return rc;
+    }
+  
   URLCOPY (auth);
   URLCOPY (host);
   new_url->port = old_url->port;
@@ -153,7 +167,7 @@ mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
        return ENOMEM;
       new_url->fvcount = argc;
     }
-  
+
   rc = mu_url_sget_query (old_url, &argc, &argv);
   if (rc == 0 && argc)
     {
@@ -163,14 +177,14 @@ mu_url_copy0 (mu_url_t old_url, mu_url_t new_url)
     }
   return 0;
 #undef URLCOPY
-} 
-  
+}
+
 int
 mu_url_dup (mu_url_t old_url, mu_url_t *new_url)
 {
   mu_url_t url;
   int rc = mu_url_create (&url, mu_url_to_string (old_url));
-  
+
   if (rc)
     return rc;
 
@@ -191,11 +205,11 @@ mu_url_uplevel (mu_url_t url, mu_url_t *upurl)
 
   if (url->_uplevel)
     return url->_uplevel (url, upurl);
-  
+
   if (!url->path)
     return MU_ERR_NOENT;
   p = strrchr (url->path, '/');
-  
+
   rc = mu_url_dup (url, &new_url);
   if (rc == 0)
     {
@@ -240,8 +254,7 @@ mu_url_destroy (mu_url_t * purl)
       if (url->user)
        free (url->user);
 
-      if (url->passwd)
-       free (url->passwd);
+      mu_secret_destroy (&url->secret);
 
       if (url->auth)
        free (url->auth);
@@ -269,13 +282,15 @@ mu_url_parse (mu_url_t url)
   int err = 0;
   char *n = NULL;
   struct _mu_url u;
+  size_t pstart;
+  mu_secret_t newsec;
 
   if (!url || !url->name)
     return EINVAL;
 
   memset (&u, 0, sizeof u);
   /* can't have been parsed already */
-  if (url->scheme || url->user || url->passwd || url->auth ||
+  if (url->scheme || url->user || url->secret || url->auth ||
       url->host || url->path || url->qargc)
     return EINVAL;
 
@@ -284,14 +299,34 @@ mu_url_parse (mu_url_t url)
   if (!n)
     return ENOMEM;
 
-  err = url_parse0 (&u, n);
+  err = url_parse0 (&u, n, &pstart);
 
   if (!err)
     {
+      if (u.secret)
+       {
+         /* Obfuscate the password */
+#define PASS_REPL "***"
+#define PASS_REPL_LEN (sizeof (PASS_REPL) - 1)
+         size_t plen = mu_secret_length (u.secret);
+         size_t nlen = strlen (url->name);
+         size_t len = nlen - plen + PASS_REPL_LEN + 1;
+         char *newname;
+
+         memset (url->name + pstart, 0, plen);
+         newname = realloc (url->name, len);
+         if (!newname)
+           goto CLEANUP;
+         memmove (newname + pstart + PASS_REPL_LEN, newname + pstart + plen,
+                  nlen - (pstart + plen) + 1);
+         memcpy (newname + pstart, PASS_REPL, PASS_REPL_LEN);
+         url->name = newname;
+       }
+
       /* Dup the strings we found. We wouldn't have to do this
-         if we did a single alloc of the source url name, and
-         kept it around. It's also a good time to do hex decoding,
-         though.
+        if we did a single alloc of the source url name, and
+        kept it around. It's also a good time to do hex decoding,
+        though.
        */
 
 #define UALLOC(X)                                          \
@@ -308,22 +343,35 @@ mu_url_parse (mu_url_t url)
 
       UALLOC (scheme);
       UALLOC (user);
-      UALLOC (passwd);
+
+      if (u.secret)
+       {
+         char *pass = mu_url_decode (mu_secret_password (u.secret));
+         err = mu_secret_create (&newsec, pass, strlen (pass));
+         memset (pass, 0, strlen (pass));
+         mu_secret_destroy (&u.secret);
+         if (err)
+           goto CLEANUP;
+
+         url->secret = newsec;
+       }
+
       UALLOC (auth);
       UALLOC (host);
       UALLOC (path);
-      
+
 #undef UALLOC
       url->fvcount = u.fvcount;
       url->fvpairs = u.fvpairs;
 
       url->qargc = u.qargc;
       url->qargv = u.qargv;
-      
+
       url->port = u.port;
     }
 
 CLEANUP:
+  memset (n, 0, strlen (n));
   free (n);
 
   if (err)
@@ -332,7 +380,7 @@ CLEANUP:
 
       UFREE (url->scheme);
       UFREE (url->user);
-      UFREE (url->passwd);
+      mu_secret_destroy (&u.secret);
       UFREE (url->auth);
       UFREE (url->host);
       UFREE (url->path);
@@ -370,8 +418,9 @@ Is this required to be % quoted, though? I hope so!
 */
 
 static int
-url_parse0 (mu_url_t u, char *name)
+url_parse0 (mu_url_t u, char *name, size_t *poff)
 {
+  char *start = name;
   char *p;                     /* pointer into name */
 
   /* reject the obvious */
@@ -409,10 +458,10 @@ url_parse0 (mu_url_t u, char *name)
       /* RFC 1738, section 2.1, lower the scheme case */
       for (; name < p; name++)
        *name = tolower (*name);
-  
+
       name = p;
     }
-  
+
   /* Check for nothing following the scheme. */
   if (!*name)
     return 0;
@@ -434,6 +483,8 @@ url_parse0 (mu_url_t u, char *name)
            u->host = name;
          else
            {
+             char *pass = NULL;
+
              /* Parse the LHS into an identification/authentication pair. */
              *u->host++ = 0;
 
@@ -450,7 +501,8 @@ url_parse0 (mu_url_t u, char *name)
                  if (*name == ':')
                    {
                      *name++ = 0;
-                     u->passwd = name;
+                     pass = name;
+                     *poff = pass - start;
                    }
                  else if (*name == ';')
                    {
@@ -464,6 +516,15 @@ url_parse0 (mu_url_t u, char *name)
                        }
                    }
                }
+
+             if (pass)
+               {
+                 if (mu_secret_create (&u->secret, pass, strlen (pass)))
+                   return ENOMEM;
+                 else
+                   /* Obfuscate password */
+                   memset (pass, 0, strlen (pass));
+               }
            }
 
          /* Parse the host and port from the RHS. */
@@ -487,7 +548,7 @@ url_parse0 (mu_url_t u, char *name)
       u->path = name;
       p = u->path + strcspn (u->path, ";?");
     }
-  
+
   /* Either way, if we're not at a nul, we're at a path or query. */
   if (u->path == NULL && *p == '/')
     {
@@ -531,31 +592,31 @@ ACCESSOR(sget,field) (mu_url_t url, char const **sptr)    
                  \
        {                                                                 \
          size_t n;                                                       \
          char *buf;                                                      \
-                                                                         \
+                                                                         \
          int status = url->AC2(_get_,field) (url, NULL, 0, &n);          \
          if (status)                                                     \
            return status;                                                \
-                                                                         \
+                                                                         \
          buf = malloc (n + 1);                                           \
          if (!buf)                                                       \
            return ENOMEM;                                                \
-                                                                         \
+                                                                         \
          status = url->AC2(_get_,field) (url, buf, n + 1, NULL);         \
-         if (status)                                                     \
-            return status;                                               \
-                                                                         \
-          if (buf[0])                                                     \
-            {                                                             \
+         if (status)                                     \
+           return status;                                                \
+                                                                         \
+         if (buf[0])                                                     \
+           {                                                             \
               url->field = mu_url_decode (buf);                          \
               free (buf);                                                \
            }                                                             \
-          else                                                            \
-            url->field = buf;                                             \
+         else                                                            \
+           url->field = buf;                                             \
          if (!url->field)                                                \
            return ENOMEM;                                                \
        }                                                                 \
       else                                                               \
-        return MU_ERR_NOENT;                                             \
+       return MU_ERR_NOENT;                                              \
     }                                                                    \
   *sptr = url->field;                                                    \
   return 0;                                                              \
@@ -568,7 +629,7 @@ ACCESSOR(get,field) (mu_url_t url, char *buf, size_t len, 
size_t *n)      \
   size_t i;                                                              \
   const char *str;                                                       \
   int status = ACCESSOR(sget, field) (url, &str);                        \
-                                                                         \
+                                                                         \
   if (status)                                                            \
     return status;                                                       \
                                                                          \
@@ -628,17 +689,26 @@ DECL_CMP(field)
 /* Declare particular accessors */
 DECL_ACCESSORS (scheme)
 DECL_ACCESSORS (user)
-/* FIXME: We should not store passwd in clear, but rather
-   have a simple encoding, and decoding mechanism */
-DECL_ACCESSORS (passwd)
 DECL_ACCESSORS (auth)
 DECL_ACCESSORS (host)
 DECL_ACCESSORS (path)
 
 int
+mu_url_get_secret (const mu_url_t url, mu_secret_t *psecret)
+{
+  if (url->_get_secret)
+    return url->_get_secret (url, psecret);
+  if (url->secret == NULL)
+    return MU_ERR_NOENT;
+  mu_secret_ref (url->secret);
+  *psecret = url->secret;
+  return 0;
+}
+
+int
 mu_url_sget_query (const mu_url_t url, size_t *qc, char ***qv)
 {
-  if (url == NULL)                                                       
+  if (url == NULL)
     return EINVAL;
   /* See FIXME below */
   *qc = url->qargc;
@@ -652,7 +722,7 @@ mu_url_aget_query (const mu_url_t url, size_t *qc, char 
***qv)
   size_t qargc, i;
   char **qargv;
   char **qcopy;
-  
+
   int rc = mu_url_sget_fvpairs (url, &qargc, &qargv);
   if (rc)
     return rc;
@@ -677,8 +747,8 @@ mu_url_aget_query (const mu_url_t url, size_t *qc, char 
***qv)
 /* field-value pairs accessors */
 int
 mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp)
-{                                                                        
-  if (url == NULL)                                                       
+{
+  if (url == NULL)
     return EINVAL;
   /* FIXME: no _get_fvpairs method, but the method stuff needs to be rewritten
      anyway */
@@ -686,14 +756,14 @@ mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, 
char ***fvp)
   *fvp = url->fvpairs;
   return 0;
 }
-     
+
 int
 mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp)
 {
   size_t fvc, i;
   char **fvp;
   char **fvcopy;
-  
+
   int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
   if (rc)
     return rc;
@@ -898,7 +968,7 @@ _url_path_hashed (const char *spooldir, const char *user, 
int param)
 
   if (param > ulen)
     param = ulen;
-  for (i = 0, hash = 0; i < param; i++) 
+  for (i = 0, hash = 0; i < param; i++)
     hash += user[i];
 
   mbox = malloc (ulen + strlen (spooldir) + 5);
@@ -908,36 +978,36 @@ _url_path_hashed (const char *spooldir, const char *user, 
int param)
 
 static int transtab[] = {
   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
-  'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 
-  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
-  'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
-  'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 
-  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 
-  'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 
-  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 
-  'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 
-  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 
-  'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 
-  'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 
-  'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 
-  'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 
-  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 
-  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 
-  'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 
-  'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
-  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
-  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g', 
-  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 
-  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 
-  'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+  'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
+  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+  'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+  'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
+  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+  'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
+  'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
+  'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+  'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
+  'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+  'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
+  'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+  'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+  'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
   'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
 };
 
@@ -948,10 +1018,10 @@ _url_path_index (const char *spooldir, const char 
*iuser, int index_depth)
   const unsigned char* user = (const unsigned char*) iuser;
   int i, ulen = strlen (iuser);
   char *mbox, *p;
-  
+
   if (ulen == 0)
     return NULL;
-  
+
   mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
   strcpy (mbox, spooldir);
   p = mbox + strlen (mbox);
@@ -977,10 +1047,10 @@ _url_path_rev_index (const char *spooldir, const char 
*iuser, int index_depth)
   const unsigned char* user = (const unsigned char*) iuser;
   int i, ulen = strlen (iuser);
   char *mbox, *p;
-  
+
   if (ulen == 0)
     return NULL;
-  
+
   mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
   strcpy (mbox, spooldir);
   p = mbox + strlen (mbox);
@@ -1003,10 +1073,10 @@ static int
 rmselector (const char *p, void *data MU_ARG_UNUSED)
 {
   return strncmp (p, "type=", 5) == 0
-         || strncmp (p, "user=", 5) == 0
-         || strncmp (p, "param=", 6) == 0;
+        || strncmp (p, "user=", 5) == 0
+        || strncmp (p, "param=", 6) == 0;
 }
-  
+
 int
 mu_url_expand_path (mu_url_t url)
 {
@@ -1015,7 +1085,7 @@ mu_url_expand_path (mu_url_t url)
   int param = 0;
   char *p;
   char *(*fun) (const char *, const char *, int) = _url_path_default;
-  
+
   if (url->fvcount == 0)
     return 0;
 
@@ -1044,7 +1114,7 @@ mu_url_expand_path (mu_url_t url)
          param = strtoul (p + 6, NULL, 0);
        }
     }
-  
+
   if (user)
     {
       char *p = fun (url->path, user, param);
diff --git a/mailbox/wicket.c b/mailbox/wicket.c
index 30392b6..ca2401d 100644
--- a/mailbox/wicket.c
+++ b/mailbox/wicket.c
@@ -1,6 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 1999, 2000, 2001, 2003, 2004, 
-   2005, 2007 Free Software Foundation, Inc.
+   2005, 2007, 2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -34,410 +34,327 @@
 #include <mailutils/errno.h>
 #include <mailutils/mutil.h>
 #include <mailutils/mu_auth.h>
+#include <mailutils/stream.h>
 
 #include <auth0.h>
 #include <url0.h>
 
-struct myticket_data
+int
+mu_wicket_create (mu_wicket_t *pwicket)
 {
-  char *user;
-  char *pass;
-  char *filename;
-};
-
-static int   myticket_create  (mu_ticket_t *, const char *, const char *, 
const char *);
-static void  myticket_destroy (mu_ticket_t);
-static int   myticket_pop     (mu_ticket_t, mu_url_t, const char *, char **);
-static int   get_pass         (mu_url_t, const char *, const char *, char**);
-static int   get_user         (mu_url_t, const char *, char **);
+  mu_wicket_t wicket = calloc (1, sizeof (*wicket));
+  if (!wicket)
+    return ENOMEM;
+  wicket->refcnt = 1;
+  return 0;
+}
 
 int
-mu_wicket_create (mu_wicket_t *pwicket, const char *filename)
+mu_wicket_get_ticket (mu_wicket_t wicket, const char *user, mu_ticket_t 
*pticket)
 {
-  struct stat st;
+  if (!wicket)
+    return EINVAL;
+  if (!pticket)
+    return EINVAL;
+  if (!wicket->_get_ticket)
+    return ENOSYS;
+  return wicket->_get_ticket (wicket, wicket->data, user, pticket);
+}
 
-  if (pwicket == NULL)
-    return MU_ERR_OUT_PTR_NULL;
+int
+mu_wicket_ref (mu_wicket_t wicket)
+{
+  if (!wicket)
+    return EINVAL;
+  wicket->refcnt++;
+  return 0;
+}
 
-  if (filename)
+int
+mu_wicket_unref (mu_wicket_t wicket)
+{
+  if (!wicket)
+    return EINVAL;
+  if (wicket->refcnt)
+    wicket->refcnt--;
+  if (wicket->refcnt == 0)
     {
-      if (stat (filename, &st) == -1)
-       return errno;
-      if ((st.st_mode & S_IRWXG) || (st.st_mode & S_IRWXO))
-       return MU_ERR_UNSAFE_PERMS;
+      if (wicket->_destroy)
+       wicket->_destroy (wicket);
+      free (wicket);
+      return 0;
     }
-
-  *pwicket = calloc (1, sizeof (**pwicket));
-  if (*pwicket == NULL)
-    return ENOMEM;
-
-  if (filename)
-    (*pwicket)->filename = strdup (filename);
-  return 0;
+  return MU_ERR_EXISTS;
 }
 
+
 void
 mu_wicket_destroy (mu_wicket_t *pwicket)
 {
-  if (pwicket && *pwicket)
-    {
-      mu_wicket_t wicket = *pwicket;
-      if (wicket->filename)
-       free (wicket->filename);
-      free (wicket);
-      *pwicket = NULL;
-    }
+  if (pwicket && *pwicket && mu_wicket_unref (*pwicket) == 0)
+    *pwicket = NULL;
 }
 
 int
-mu_wicket_get_filename (mu_wicket_t wicket, char *filename, size_t len,
-                       size_t *pwriten)
+mu_wicket_set_destroy (mu_wicket_t wicket, void (*_destroy) (mu_wicket_t))
 {
-  size_t n;
-  if (wicket == NULL)
+  if (!wicket)
     return EINVAL;
-  n = mu_cpystr (filename, wicket->filename, len);
-  if (pwriten)
-    *pwriten = n;
+  wicket->_destroy = _destroy;
   return 0;
 }
 
 int
-mu_wicket_set_filename (mu_wicket_t wicket, const char *filename)
+mu_wicket_set_data (mu_wicket_t wicket, void *data)
 {
-  if (wicket == NULL)
+  if (!wicket)
     return EINVAL;
-  
-  if (wicket->filename)
-    free (wicket->filename);
-  
-  wicket->filename = (filename) ? strdup (filename) : NULL;
+  wicket->data = data;
   return 0;
 }
 
-int
-mu_wicket_set_ticket (mu_wicket_t wicket, int (*get_ticket)
-                     (mu_wicket_t, const char *, const char *, mu_ticket_t *))
+void *
+mu_wicket_get_data (mu_wicket_t wicket)
 {
-  if (wicket == NULL)
-    return EINVAL;
-
-  wicket->_get_ticket = get_ticket;
-  return 0;
+  if (!wicket)
+    return NULL;
+  return wicket->data;
 }
 
 int
-mu_wicket_get_ticket (mu_wicket_t wicket, mu_ticket_t *pticket,
-                     const char *user,
-                     const char *type)
+mu_wicket_set_get_ticket (mu_wicket_t wicket,
+                         int (*_get_ticket) (mu_wicket_t, void *,
+                                             const char *, mu_ticket_t *))
 {
-  if (wicket == NULL || pticket == NULL)
+  if (!wicket)
     return EINVAL;
+  wicket->_get_ticket = _get_ticket;
+  return 0;
+}
 
-  if (wicket->filename == NULL)
-    return EINVAL;
+
+/* A "file wicket" implementation */
 
-  if (wicket->_get_ticket)
-    return wicket->_get_ticket (wicket, user, type, pticket);
-  return myticket_create (pticket, user, NULL, wicket->filename);
+struct file_wicket
+{
+  char *filename;
+};
+
+static void
+_file_wicket_destroy (mu_wicket_t wicket)
+{
+  struct file_wicket *fw = mu_wicket_get_data (wicket);
+  free (fw->filename);
+  free (fw);
 }
 
-static int
-myticket_create (mu_ticket_t *pticket, const char *user,
-                const char *pass, const char *filename)
+struct file_ticket
 {
-  struct myticket_data *mdata;
-  int status = mu_ticket_create (pticket, NULL);
-  if (status != 0)
-    return status;
+  char *filename;
+  char *user;
+  mu_url_t tickurl;
+};
 
-  mdata = calloc (1, sizeof *mdata);
-  if (mdata == NULL)
+static void
+file_ticket_destroy (mu_ticket_t ticket)
+{
+  struct file_ticket *ft = mu_ticket_get_data (ticket);
+  if (ft)
     {
-      mu_ticket_destroy (pticket, NULL);
-      return ENOMEM;
+      free (ft->filename);
+      free (ft->user);
+      mu_url_destroy (&ft->tickurl);
+      free (ft);
     }
+}
 
-  mu_ticket_set_destroy (*pticket, myticket_destroy, NULL);
-  mu_ticket_set_pop (*pticket, myticket_pop, NULL);
-  mu_ticket_set_data (*pticket, mdata, NULL);
+static int get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t 
*pticket_url);
 
-  if (filename)
-    {
-      mdata->filename = strdup (filename);
-      if (mdata->filename == NULL)
-       {
-         mu_ticket_destroy (pticket, NULL);
-         status = ENOMEM;
-         return status;
-       }
-    }
+int
+file_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge,
+                     char **pplain, mu_secret_t *psec)
+{
+  struct file_ticket *ft = mu_ticket_get_data (ticket);
 
-  if (user)
+  if (!ft->tickurl)
     {
-      mdata->user = strdup (user);
-      if (mdata->user == NULL)
-       {
-         mu_ticket_destroy (pticket, NULL);
-         status = ENOMEM;
-         return status;
-       }
+      int rc = get_ticket_url (ticket, url, &ft->tickurl);
+      if (rc)
+       return rc;
     }
-
-  if (pass)
+  if (pplain)
     {
-      mdata->pass = strdup (pass);
-      if (mdata->pass == NULL)
+      if (ft->user)
        {
-         mu_ticket_destroy (pticket, NULL);
-         status = ENOMEM;
-         return status;
+         *pplain = strdup (ft->user);
+         if (!*pplain)
+           return ENOMEM;
        }
+      else
+       return mu_url_aget_user (ft->tickurl, pplain);
     }
-
-  return 0;
+  else
+    return mu_url_get_secret (ft->tickurl, psec);
 }
 
 static int
-myticket_pop (mu_ticket_t ticket, mu_url_t url,
-             const char *challenge, char **parg)
+_file_wicket_get_ticket (mu_wicket_t wicket, void *data,
+                        const char *user, mu_ticket_t *pticket)
 {
-  struct myticket_data *mdata = NULL;
-  int e = 0;
-  
-  mu_ticket_get_data (ticket, (void **)&mdata);
-  if (challenge && (strstr (challenge, "ass") != NULL ||
-                   strstr (challenge, "ASS") != NULL))
+  int rc;
+  mu_ticket_t ticket;
+  struct file_wicket *fw = data;
+  struct file_ticket *ft = calloc (1, sizeof (*ft));
+  ft->filename = strdup (fw->filename);
+  if (!ft->filename)
     {
-      if (mdata->pass)
-       {
-         *parg = strdup (mdata->pass);
-         if (!*parg)
-           e = ENOMEM;
-       }
-      else
-       e = get_pass (url, mdata->user, mdata->filename, parg);
+      free (ft);
+      return ENOMEM;
     }
-  else
+  if (user)
     {
-      if (mdata->user)
+      ft->user = strdup (user);
+      if (!ft->user)
        {
-         *parg = strdup(mdata->user);
-         if (!*parg)
-           e = ENOMEM;
+         free (ft->filename);
+         free (ft);
+         return ENOMEM;
        }
-      else
-       e = get_user (url, mdata->filename, parg);
-  }
-  return e;
-}
+    }
+  else
+    ft->user = NULL;
 
-static void
-myticket_destroy (mu_ticket_t ticket)
-{
-  struct myticket_data *mdata = NULL;
-  mu_ticket_get_data (ticket, (void **)&mdata);
-  if (mdata)
+  rc = mu_ticket_create (&ticket, NULL);
+  if (rc)
     {
-      if (mdata->user)
-       free (mdata->user);
-      if (mdata->pass)
-       free (mdata->pass);
-      if (mdata->filename)
-       free (mdata->filename);
-      free (mdata);
+      free (ft->filename);
+      free (ft->user);
+      free (ft);
+      return rc;
     }
-}
+       
+  mu_ticket_set_destroy (ticket, file_ticket_destroy, NULL);
+  mu_ticket_set_data (ticket, ft, NULL);
+  mu_ticket_set_get_cred (ticket, file_ticket_get_cred, NULL);
 
+  *pticket = ticket;
+  return 0;
+}
+  
 static int
-get_ticket (mu_url_t url, const char *user, const char *filename,
-           mu_url_t * ticket)
+get_ticket_url (mu_ticket_t ticket, mu_url_t url, mu_url_t *pticket_url)
 {
-  int status = MU_ERR_NOENT;
-  FILE *fp = NULL;
-  size_t buflen = 128;
-  char *buf = NULL;
-
-  if (!filename || !url)
-    return EINVAL;
-
-  fp = fopen (filename, "r");
-
-  if (!fp)
-    return errno;
-
-  buf = malloc (buflen);
-
-  if (!buf)
+  mu_stream_t stream;
+  struct file_ticket *ft = mu_ticket_get_data (ticket);
+  int rc;
+  mu_url_t u = NULL;
+  
+  rc = mu_file_stream_create (&stream, ft->filename, MU_STREAM_READ);
+  if (rc)
+    return rc;
+  rc = mu_stream_open (stream);
+  if (rc == 0)
     {
-      fclose (fp);
-      return ENOMEM;
-    }
+      char *buf = NULL;
+      size_t bufsize = 0;
+      size_t len;
 
-  while (!feof (fp) && !ferror (fp))
-    {
-      char *ptr = buf;
-      int len = 0;
-      mu_url_t u = NULL;
-      int err;
-      
-      /* fgets:
-        1) return true, read some data
-           1a) read a newline, so break
-           1b) didn't read newline, so realloc & continue
-         2) returned NULL, so no more data
-       */
-      while (fgets (ptr, buflen, fp) != NULL)
+      while ((rc = mu_stream_sequential_getline (stream,
+                                                &buf, &bufsize, &len)) == 0
+            && len > 0)
        {
-         char *tmp = NULL;
-         len = strlen (buf);
-         /* Check if a complete line.  */
+         char *p;
+         int err;
+         
+         /* Truncate a trailing newline. */
          if (len && buf[len - 1] == '\n')
-           break;
-
-         buflen *= 2;
-         tmp = realloc (buf, buflen);
-         if (tmp == NULL)
+           buf[--len] = 0;
+
+         /* Skip leading spaces  */
+         for (p = buf; *p == ' ' || *p == '\t'; p++)
+           ;
+         /* Skip trailing spaces */
+         for (; len > 0 && (p[len-1] == ' ' || p[len-1] == '\t'); )
+           p[--len] = 0;
+         
+         /* Skip empty lines and comments. */
+         if (*p == 0 || *p == '#')
+           continue;
+
+         if ((err = mu_url_create (&u, p)) != 0)
            {
-             free (buf);
-             fclose (fp);
-             return ENOMEM;
+             /* Skip erroneous entry */
+             /* FIXME: Error message */
+             continue;
            }
-         buf = tmp;
-         ptr = buf + len;
-       }
-
-      len = strlen (buf);
-
-      /* Truncate a trailing newline. */
-      if (len && buf[len - 1] == '\n')
-       buf[--len] = 0;
-
-      /* Skip leading spaces.  */
-      ptr = buf;
-      while (isspace (*ptr))
-       ptr++;
-
-      /* Skip empty lines and comments. */
-      if (!*ptr || *ptr == '#')
-       continue;
-
-      if ((err = mu_url_create (&u, ptr)) != 0)
-       {
-         status = err;
-         break;
-       }
-      if ((err = mu_url_parse (u)) != 0)
-       {
-         /* TODO: send output to the debug stream */
-         /*
-            printf ("mu_url_parse %s failed: [%d] %s\n", str, err, mu_strerror 
(err));
-          */
-         mu_url_destroy (&u);
-         continue;
-       }
-
-
-      if (!mu_url_is_ticket (u, url))
-       {
-         mu_url_destroy (&u);
-         continue;
-       }
-      /* Also needs to be for name, if we required. */
-      if (user)
-       {
-         if (u->name && strcmp (u->name, "*") != 0
-             && strcmp (user, u->name) != 0)
+         if ((err = mu_url_parse (u)) != 0)
            {
+             /* FIXME: See above */
              mu_url_destroy (&u);
              continue;
            }
+         
+         if (!mu_url_is_ticket (u, url))
+           {
+             mu_url_destroy (&u);
+             continue;
+           }
+         
+         if (ft->user)
+           {
+             if (u->name && strcmp (u->name, "*") != 0
+                 && strcmp (ft->user, u->name) != 0)
+               {
+                 mu_url_destroy (&u);
+                 continue;
+               }
+           }
+         
+         break;
        }
-
-      /* Looks like a match! */
-      *ticket = u;
-      u = NULL;
-      status = 0;
-      break;
+      mu_stream_close (stream);
+      free (buf);
     }
+  mu_stream_destroy (&stream, NULL);
 
-  fclose (fp);
-  free (buf);
-
-  return status;
-}
-
-static int
-get_user (mu_url_t url, const char *filename, char **user)
-{
-  char *u = 0;
-  int status;
-
-  if (url)
-    {
-      status = mu_url_aget_user (url, &u);
-      if (status && status != MU_ERR_NOENT)
-        return status;
-    }
-
-  if (!u && filename)
+  if (rc == 0)
     {
-      mu_url_t ticket = 0;
-      status = get_ticket (url, NULL, filename, &ticket);
-      if (status)
-       return status;
-
-      if (ticket)
-       {
-         status = mu_url_aget_user (ticket, &u);
-          if (status && status != MU_ERR_NOENT)
-            return status;
-         mu_url_destroy (&ticket);
-       }
-    }
-  else
-    {
-      struct mu_auth_data *auth = mu_get_auth_by_uid (getuid ());
-      if (auth)
-       {
-         u = strdup (auth->name);
-         mu_auth_data_free (auth);
-         if (!u)
-           return ENOMEM;
-       }
+      if (u)
+       *pticket_url = u;
+      else
+       rc = MU_ERR_NOENT;
     }
-  *user = u;
-  return 0;
+  
+  return rc;
 }
 
-static int
-get_pass (mu_url_t url, const char *user, const char *filename, char **pass)
+int
+mu_file_wicket_create (mu_wicket_t *pwicket, const char *filename)
 {
-  int status;
-  char *u = 0;
+  mu_wicket_t wicket;
+  int rc;
+  struct file_wicket *fw = calloc (1, sizeof (*fw));
 
-  if (url)
+  if (!fw)
+    return ENOMEM;
+  fw->filename = strdup (filename);
+  if (!fw->filename)
     {
-      status = mu_url_aget_passwd (url, &u);
-      if (status && status != MU_ERR_NOENT)
-       return status;
+      free (fw);
+      return ENOMEM;
     }
-
-  if (!u && filename)
+  
+  rc = mu_wicket_create (&wicket);
+  if (rc)
     {
-      mu_url_t ticket = 0;
-      status = get_ticket (url, user, filename, &ticket);
-      if (status)
-       return status;
-
-      if (ticket)
-       {
-         status = mu_url_aget_passwd (ticket, &u);
-          if (status && status != MU_ERR_NOENT)
-           return status;
-         mu_url_destroy (&ticket);
-       }
+      free (fw->filename);
+      free (fw);
+      return rc;
     }
-  *pass = u;
+  mu_wicket_set_data (wicket, fw);
+  mu_wicket_set_destroy (wicket, _file_wicket_destroy);
+  mu_wicket_set_get_ticket (wicket, _file_wicket_get_ticket);
+  *pwicket = wicket;
   return 0;
 }
+
diff --git a/movemail/movemail.c b/movemail/movemail.c
index f3004ca..30bfa9c 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
 
    GNU Mailutils is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -161,34 +162,24 @@ lock_mailbox (mu_mailbox_t mbox)
 }
 
 
-/* A password ticket: returns the cleantext password. */
-void
-password_destroy (mu_ticket_t t)
-{
-  char *p = mu_ticket_get_owner (t);
-  free (p);
-}
-
-int
-password_pop (mu_ticket_t t, mu_url_t u, const char *challenge, char **ppwd)
-{
-  char *p = mu_ticket_get_owner (t);
-  *ppwd = strdup (p);
-  return 0;
-}
-
 void
 attach_passwd_ticket (mu_mailbox_t mbx, char *passwd)
 {
   mu_folder_t folder = NULL;
   mu_authority_t auth = NULL;
-  char *p = strdup (passwd);
+  mu_secret_t secret;
   mu_ticket_t t;
   int rc;
+
+  rc = mu_secret_create (&secret, passwd, strlen (passwd));
+  if (rc)
+    {
+      mu_error ("mu_secret_create: %s", mu_strerror (rc));
+      exit (1);
+    }
   
-  mu_ticket_create (&t, p);
-  mu_ticket_set_destroy (t, password_destroy, p);
-  mu_ticket_set_pop (t, password_pop, p);
+  mu_ticket_create (&t, NULL);
+  mu_ticket_set_secret (t, secret);
 
   if ((rc = mu_mailbox_get_folder (mbx, &folder)))
     die (mbx, _("mu_mailbox_get_folder failed"), rc);
diff --git a/python/libmu_py/auth.c b/python/libmu_py/auth.c
index 7cda3f5..a6e1b6d 100644
--- a/python/libmu_py/auth.c
+++ b/python/libmu_py/auth.c
@@ -434,7 +434,7 @@ api_ticket_destroy (PyObject *self, PyObject *args)
   if (!PyArg_ParseTuple (args, "O!", &PyTicketType, &py_ticket))
     return NULL;
 
-  mu_ticket_destroy (&py_ticket->ticket, NULL);
+  mu_ticket_destroy (&py_ticket->ticket);
   return _ro (Py_None);
 }
 
@@ -452,7 +452,7 @@ api_wicket_create (PyObject *self, PyObject *args)
   if (!PyArg_ParseTuple (args, "O!s", &PyWicketType, &py_wicket, &filename))
     return NULL;
 
-  status = mu_wicket_create (&py_wicket->wicket, filename);
+  status = mu_file_wicket_create (&py_wicket->wicket, filename);
   return _ro (PyInt_FromLong (status));
 }
 
@@ -468,38 +468,6 @@ api_wicket_destroy (PyObject *self, PyObject *args)
   return _ro (Py_None);
 }
 
-static PyObject *
-api_wicket_get_filename (PyObject *self, PyObject *args)
-{
-  int status;
-  size_t n;
-  char filename[512];
-  PyWicket *py_wicket;
-
-  memset (filename, 0, sizeof (filename));
-
-  if (!PyArg_ParseTuple (args, "O!", &PyWicketType, &py_wicket))
-    return NULL;
-
-  status = mu_wicket_get_filename (py_wicket->wicket, filename,
-                                  sizeof (filename), &n);
-  return status_object (status, PyString_FromString (filename));
-}
-
-static PyObject *
-api_wicket_set_filename (PyObject *self, PyObject *args)
-{
-  int status;
-  char *filename;
-  PyWicket *py_wicket;
-
-  if (!PyArg_ParseTuple (args, "O!s", &PyWicketType, &py_wicket, &filename))
-    return NULL;
-
-  status = mu_wicket_set_filename (py_wicket->wicket, filename);
-  return _ro (PyInt_FromLong (status));
-}
-
 /*
  *  mu_auth
  */
@@ -645,12 +613,6 @@ static PyMethodDef methods[] = {
   { "wicket_destroy", (PyCFunction) api_wicket_destroy, METH_VARARGS,
     "" },
 
-  { "wicket_get_filename", (PyCFunction) api_wicket_get_filename, METH_VARARGS,
-    "" },
-
-  { "wicket_set_filename", (PyCFunction) api_wicket_set_filename, METH_VARARGS,
-    "" },
-
   { "register_module", (PyCFunction) api_register_module, METH_VARARGS,
     "" },
 
diff --git a/python/libmu_py/url.c b/python/libmu_py/url.c
index 84619f7..cf0e066 100644
--- a/python/libmu_py/url.c
+++ b/python/libmu_py/url.c
@@ -160,6 +160,9 @@ api_url_get_user (PyObject *self, PyObject *args)
   return status_object (status, PyString_FromString (buf ? buf : ""));
 }
 
+#if 0
+/* FIXME: Returning plaintext (unobfuscated) password from
+   a secret actually makes the latter useless. */
 static PyObject *
 api_url_get_passwd (PyObject *self, PyObject *args)
 {
@@ -173,6 +176,7 @@ api_url_get_passwd (PyObject *self, PyObject *args)
   status = mu_url_sget_passwd (py_url->url, &buf);
   return status_object (status, PyString_FromString (buf ? buf : ""));
 }
+#endif
 
 static PyObject *
 api_url_get_auth (PyObject *self, PyObject *args)
@@ -267,7 +271,9 @@ static PyMethodDef methods[] = {
   { "get_port", (PyCFunction) api_url_get_port, METH_VARARGS, "" },
   { "get_scheme", (PyCFunction) api_url_get_scheme, METH_VARARGS, "" },
   { "get_user", (PyCFunction) api_url_get_user, METH_VARARGS, "" },
+#if 0 /*FIXME: See above */
   { "get_passwd", (PyCFunction) api_url_get_passwd, METH_VARARGS, "" },
+#endif
   { "get_auth", (PyCFunction) api_url_get_auth, METH_VARARGS, "" },
   { "get_host", (PyCFunction) api_url_get_host, METH_VARARGS, "" },
   { "get_path", (PyCFunction) api_url_get_path, METH_VARARGS, "" },


hooks/post-receive
-- 
GNU Mailutils




reply via email to

[Prev in Thread] Current Thread [Next in Thread]