]> diplodocus.org Git - nmh/commitdiff
Rototill credentials code so that we only prompt for the username and
authorKen Hornstein <kenh@pobox.com>
Thu, 20 Oct 2016 17:37:29 +0000 (13:37 -0400)
committerKen Hornstein <kenh@pobox.com>
Thu, 20 Oct 2016 17:37:29 +0000 (13:37 -0400)
password when it is necessary.

h/mh.h
h/popsbr.h
h/prototypes.h
sbr/credentials.c
sbr/netsec.c
sbr/ruserpass.c
uip/inc.c
uip/mhparse.c
uip/msgchk.c
uip/popsbr.c

diff --git a/h/mh.h b/h/mh.h
index 3c2fb061dbc3f2a91c4be13e679fdd56a68ae5d8..55825da03e2f941917dbd925132b717a550f0677 100644 (file)
--- a/h/mh.h
+++ b/h/mh.h
@@ -396,12 +396,7 @@ typedef struct m_getfld_state *m_getfld_state_t;
 /*
  * credentials management
  */
 /*
  * credentials management
  */
-struct nmh_creds {
-    char *host;
-    char *user;
-    char *password;
-};
-
+struct nmh_creds;
 typedef struct nmh_creds *nmh_creds_t;
 
 /*
 typedef struct nmh_creds *nmh_creds_t;
 
 /*
index c155fd12c9847565c24bef0e98be2896d0649bd0..96d21a33db151544e6ae3e0088ffe4c2dec9224c 100644 (file)
@@ -3,8 +3,8 @@
  * popsbr.h -- header for POP client subroutines
  */
 
  * popsbr.h -- header for POP client subroutines
  */
 
-int pop_init (char *, char *, char *, char *, char *, int, int, char *, int,
-              const char *);
+int pop_init (char *, char *, char *, char *, int, int, char *, int,
+             const char *);
 int pop_fd (char *, int, char *, int);
 int pop_stat (int *, int *);
 int pop_retr (int, int (*)(char *));
 int pop_fd (char *, int, char *, int);
 int pop_stat (int *, int *);
 int pop_retr (int, int (*)(char *));
index f06322b508c6ef0fdb91c3132a7dc7bb09d740db..a17d12f9cbad6d2a7109e9f3f03535a65ec926c2 100644 (file)
@@ -325,7 +325,23 @@ char *pwd (void);
 char *r1bindex(char *, int);
 void readconfig (struct node **, FILE *, const char *, int);
 int refile (char **, char *);
 char *r1bindex(char *, int);
 void readconfig (struct node **, FILE *, const char *, int);
 int refile (char **, char *);
-void ruserpass (char *, char **, char **);
+
+/*
+ * Read our credentials file and (optionally) ask the user for anything
+ * missing.
+ *
+ * Arguments:
+ *
+ * host                - Hostname (to scan credentials file)
+ * aname       - Pointer to filled-in username
+ * apass       - Pointer to filled-in password
+ * flags       - One or more of RUSERPASS_NO_PROMPT_USER,
+ *                RUSERPASS_NO_PROMPT_PASSWORD
+ */
+void ruserpass (const char *host, char **aname, char **apass, int flags);
+#define RUSERPASS_NO_PROMPT_USER       0x01
+#define RUSERPASS_NO_PROMPT_PASSWORD   0x02
+
 int remdir (char *);
 void scan_detect_mbox_style (FILE *);
 void scan_finished ();
 int remdir (char *);
 void scan_detect_mbox_style (FILE *);
 void scan_finished ();
@@ -497,7 +513,46 @@ void hexify (const unsigned char *, size_t, char **);
  * credentials management
  */
 void init_credentials_file ();
  * credentials management
  */
 void init_credentials_file ();
-int nmh_get_credentials (char *, char *, int, nmh_creds_t);
+
+/*
+ * Allocate and return a credentials structure.  The credentials structure
+ * is now opaque; you need to use accessors to get inside of it.  The
+ * accessors will only prompt the user for missing fields if they are
+ * needed.
+ *
+ * Arguments:
+ *
+ * host        - Hostname we're connecting to (used to search credentials file)
+ * user        - Username we are logging in as; can be NULL.
+ *
+ * Returns NULL on error, otherwise an allocated nmh_creds structure.
+ */
+nmh_creds_t nmh_get_credentials (const char *host, const char *user);
+
+/*
+ * Retrieve the user from a nmh_creds structure.  May prompt the user
+ * if one is not defined.
+ *
+ * Arguments:
+ *
+ * creds       - Structure from previous nmh_get_credentials() call
+ *
+ * Returns NULL on error, otherwise a NUL-termined string containing
+ * the username.  Points to allocated memory in the credentials structure
+ * that is free()d by nmh_free_credentials().
+ */
+const char *nmh_cred_get_user(nmh_creds_t creds);
+
+/*
+ * Retrieve the password from an nmh_creds structure.  Otherwise identical
+ * to nmh_cred_get_user().
+ */
+const char *nmh_cred_get_password(nmh_creds_t creds);
+
+/*
+ * Free an allocated nmh_creds structure.
+ */
+void nmh_credentials_free(nmh_creds_t creds);
 
 /*
  * program initialization
 
 /*
  * program initialization
index 9b5dd537791be7ce8406b93a11342796c6e8f842..9000e5edc6db2a574beefbd743bf16224506038b 100644 (file)
@@ -8,6 +8,12 @@
 #include <h/utils.h>
 #include <h/mts.h>
 
 #include <h/utils.h>
 #include <h/mts.h>
 
+struct nmh_creds {
+    char *host;                /* Hostname corresponding to credentials */
+    char *user;                /* Username corresponding to credentials */
+    char *pass;                /* (Optional) password used by credentials */
+};
+
 void
 init_credentials_file () {
     if (credentials_file == NULL) {
 void
 init_credentials_file () {
     if (credentials_file == NULL) {
@@ -44,21 +50,23 @@ init_credentials_file () {
     }
 }
 
     }
 }
 
-int
-nmh_get_credentials (char *host, char *user, int sasl, nmh_creds_t creds) {
+nmh_creds_t
+nmh_get_credentials (const char *host, const char *user)
+{
+    nmh_creds_t creds;
+
     char *cred_style = context_find ("credentials");
 
     init_credentials_file ();
     char *cred_style = context_find ("credentials");
 
     init_credentials_file ();
-    creds->host = host;
 
 
-    if (cred_style == NULL  ||  ! strcmp (cred_style, "legacy")) {
-       creds->user = user == NULL  ?  getusername ()  :  user;
-        if (sasl) {
+    creds = mh_xmalloc(sizeof(*creds));
 
 
-            /* This is what inc.c and msgchk.c used to contain. */
-            /* Only inc.c and msgchk.c do this.  smtp.c doesn't. */
-            creds->password = getusername ();
-        }
+    creds->host = getcpy(host);
+    creds->user = NULL;
+    creds->pass = NULL;
+
+    if (cred_style == NULL  ||  ! strcmp (cred_style, "legacy")) {
+       creds->user = user == NULL  ?  getcpy(getusername ())  :  getcpy(user);
     } else if (! strncasecmp (cred_style, "file:", 5) ||
               ! strncasecmp (cred_style, "file-nopermcheck:", 17)) {
         /*
     } else if (! strncasecmp (cred_style, "file:", 5) ||
               ! strncasecmp (cred_style, "file-nopermcheck:", 17)) {
         /*
@@ -69,12 +77,64 @@ nmh_get_credentials (char *host, char *user, int sasl, nmh_creds_t creds) {
          * 3) interactively request from user (as long as the
          *    credentials file didn't have a "default" token)
          */
          * 3) interactively request from user (as long as the
          *    credentials file didn't have a "default" token)
          */
-        creds->user = user;
+        creds->user = user == NULL ? NULL : getcpy(user);
     } else {
         admonish (NULL, "unknown credentials style %s", cred_style);
     } else {
         admonish (NULL, "unknown credentials style %s", cred_style);
-        return NOTOK;
+        return NULL;
+    }
+
+    ruserpass(creds->host, &creds->user, &creds->pass,
+             RUSERPASS_NO_PROMPT_USER | RUSERPASS_NO_PROMPT_PASSWORD);
+
+    return creds;
+}
+
+/*
+ * Retrieve the username
+ */
+
+const char *
+nmh_cred_get_user(nmh_creds_t creds)
+{
+    if (! creds->user) {
+       ruserpass(creds->host, &creds->user, &creds->pass,
+                 RUSERPASS_NO_PROMPT_PASSWORD);
+    }
+
+    return creds->user;
+}
+
+/*
+ * Retrieve the password
+ */
+
+const char *
+nmh_cred_get_password(nmh_creds_t creds)
+{
+    if (! creds->pass) {
+       ruserpass(creds->host, &creds->user, &creds->pass, 0);
+    }
+
+    return creds->pass;
+}
+
+/*
+ * Free our credentials
+ */
+
+void
+nmh_credentials_free(nmh_creds_t creds)
+{
+    if (creds->host)
+       free(creds->host);
+
+    if (creds->user)
+       free(creds->user);
+
+    if (creds->pass) {
+       memset(creds->pass, 0, strlen(creds->pass));
+       free(creds->pass);
     }
 
     }
 
-    ruserpass (host, &creds->user, &creds->password);
-    return OK;
+    free(creds);
 }
 }
index 788b23bf0411036821e695d771a25ad3e3536f84..990b2318a70d389e8889973401f5f66eaddce9be 100644 (file)
@@ -209,12 +209,8 @@ netsec_shutdown(netsec_context *nsc, int closeflag)
        free(nsc->sasl_hostname);
     if (nsc->sasl_cbs)
        free(nsc->sasl_cbs);
        free(nsc->sasl_hostname);
     if (nsc->sasl_cbs)
        free(nsc->sasl_cbs);
-    if (nsc->sasl_creds) {
-       if (nsc->sasl_creds->password)
-           memset(nsc->sasl_creds->password, 0,
-                  strlen(nsc->sasl_creds->password));
-       free(nsc->sasl_creds);
-    }
+    if (nsc->sasl_creds)
+       nmh_credentials_free(nsc->sasl_creds);
     if (nsc->sasl_secret) {
        if (nsc->sasl_secret->len > 0) {
            memset(nsc->sasl_secret->data, 0, nsc->sasl_secret->len);
     if (nsc->sasl_secret) {
        if (nsc->sasl_secret->len > 0) {
            memset(nsc->sasl_secret->data, 0, nsc->sasl_secret->len);
@@ -1003,6 +999,13 @@ netsec_set_sasl_params(netsec_context *nsc, const char *hostname,
     }
 
     nsc->sasl_hostname = mh_xstrdup(hostname);
     }
 
     nsc->sasl_hostname = mh_xstrdup(hostname);
+
+    /*
+     * Set up our credentials
+     */
+
+    nsc->sasl_creds = nmh_get_credentials(nsc->sasl_hostname, nsc->ns_userid);
+
 #else /* CYRUS_SASL */
     NMH_UNUSED(hostname);
     NMH_UNUSED(service);
 #else /* CYRUS_SASL */
     NMH_UNUSED(hostname);
     NMH_UNUSED(service);
@@ -1043,35 +1046,10 @@ int netsec_get_user(void *context, int id, const char **result,
     if (! result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
        return SASL_BADPARAM;
 
     if (! result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
        return SASL_BADPARAM;
 
-    if (nsc->ns_userid == NULL) {
-       /*
-        * Pass the 1 third argument to nmh_get_credentials() so that
-        * a default user if the -user switch wasn't supplied, and so
-        * that a default password will be supplied.  That's used when
-        * those values really don't matter, and only with legacy/.netrc,
-        * i.e., with a credentials profile entry.
-        */
-
-       if (nsc->sasl_creds == NULL) {
-           NEW(nsc->sasl_creds);
-           nsc->sasl_creds->user = NULL;
-           nsc->sasl_creds->password = NULL;
-       }
-
-       if (nmh_get_credentials(nsc->sasl_hostname, nsc->ns_userid, 1,
-                               nsc->sasl_creds) != OK)
-           return SASL_BADPARAM;
+    *result = nmh_cred_get_user(nsc->sasl_creds);
 
 
-       if (nsc->ns_userid != nsc->sasl_creds->user) {
-           if (nsc->ns_userid)
-               free(nsc->ns_userid);
-           nsc->ns_userid = getcpy(nsc->sasl_creds->user);
-       }
-    }
-
-    *result = nsc->ns_userid;
     if (len)
     if (len)
-       *len = strlen(nsc->ns_userid);
+       *len = strlen(*result);
 
     return SASL_OK;
 }
 
     return SASL_OK;
 }
@@ -1085,6 +1063,7 @@ netsec_get_password(sasl_conn_t *conn, void *context, int id,
                    sasl_secret_t **psecret)
 {
     netsec_context *nsc = (netsec_context *) context;
                    sasl_secret_t **psecret)
 {
     netsec_context *nsc = (netsec_context *) context;
+    const char *password;
     int len;
 
     NMH_UNUSED(conn);
     int len;
 
     NMH_UNUSED(conn);
@@ -1092,27 +1071,9 @@ netsec_get_password(sasl_conn_t *conn, void *context, int id,
     if (! psecret || id != SASL_CB_PASS)
        return SASL_BADPARAM;
 
     if (! psecret || id != SASL_CB_PASS)
        return SASL_BADPARAM;
 
-    if (nsc->sasl_creds == NULL) {
-       NEW(nsc->sasl_creds);
-       nsc->sasl_creds->user = NULL;
-       nsc->sasl_creds->password = NULL;
-    }
-
-    if (nsc->sasl_creds->password == NULL) {
-       /*
-        * Pass the 0 third argument to nmh_get_credentials() so
-        * that the default password isn't used.  With legacy/.netrc
-        * credentials support, we'll only get here if the -user
-        * switch to send(1)/post(8) wasn't used.
-        */
-
-       if (nmh_get_credentials(nsc->sasl_hostname, nsc->ns_userid, 0,
-                               nsc->sasl_creds) != OK) {
-           return SASL_BADPARAM;
-       }
-    }
+    password = nmh_cred_get_password(nsc->sasl_creds);
 
 
-    len = strlen(nsc->sasl_creds->password);
+    len = strlen(password);
 
     /*
      * sasl_secret_t includes 1 bytes for "data" already, so that leaves
 
     /*
      * sasl_secret_t includes 1 bytes for "data" already, so that leaves
@@ -1125,7 +1086,7 @@ netsec_get_password(sasl_conn_t *conn, void *context, int id,
        return SASL_NOMEM;
 
     (*psecret)->len = len;
        return SASL_NOMEM;
 
     (*psecret)->len = len;
-    strcpy((char *) (*psecret)->data, nsc->sasl_creds->password);
+    strcpy((char *) (*psecret)->data, password);
 
     nsc->sasl_secret = *psecret;
 
 
     nsc->sasl_secret = *psecret;
 
index de0f951bf32ef2d2314f3b972844a57599740407..610f32a5c3b9c16d6f6821a3f0695525f86c9707 100644 (file)
@@ -59,7 +59,7 @@ static int token(char *);
 
 
 void
 
 
 void
-ruserpass(char *host, char **aname, char **apass)
+ruserpass(const char *host, char **aname, char **apass, int flags)
 {
     int t, usedefault = 0;
     struct stat stb;
 {
     int t, usedefault = 0;
     struct stat stb;
@@ -133,7 +133,7 @@ ruserpass(char *host, char **aname, char **apass)
        }
     }
 
        }
     }
 
-    if (!*aname) {
+    if (!*aname && ! (flags & RUSERPASS_NO_PROMPT_USER)) {
        char tmp[80];
        char *myname;
 
        char tmp[80];
        char *myname;
 
@@ -156,7 +156,7 @@ ruserpass(char *host, char **aname, char **apass)
         *aname = mh_xstrdup(myname);
     }
 
         *aname = mh_xstrdup(myname);
     }
 
-    if (!*apass) {
+    if (!*apass && ! (flags & RUSERPASS_NO_PROMPT_PASSWORD)) {
        char prompt[256];
        char *mypass;
 
        char prompt[256];
        char *mypass;
 
index 83b6ec9695b2d3b64ea6e166063c1a45f10a7f3c..aadfe98b05f4cedb64e5536b0ef5dc0a06f338bf 100644 (file)
--- a/uip/inc.c
+++ b/uip/inc.c
@@ -413,25 +413,21 @@ main (int argc, char **argv)
      * a POP server?
      */
     if (inc_type == INC_POP) {
      * a POP server?
      */
     if (inc_type == INC_POP) {
-       struct nmh_creds creds = { 0, 0, 0 };
-
        if (auth_svc == NULL) {
            if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
                adios (NULL, "must specify -authservice with -saslmech xoauth2");
            }
        if (auth_svc == NULL) {
            if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
                adios (NULL, "must specify -authservice with -saslmech xoauth2");
            }
-           nmh_get_credentials (host, user, sasl, &creds);
        } else {
            if (user == NULL) {
                adios (NULL, "must specify -user with -saslmech xoauth2");
            }
        } else {
            if (user == NULL) {
                adios (NULL, "must specify -user with -saslmech xoauth2");
            }
-           creds.user = user;
        }
 
        /*
         * initialize POP connection
         */
        }
 
        /*
         * initialize POP connection
         */
-       if (pop_init (host, port, creds.user, creds.password, proxy, snoop,
-                     sasl, saslmech, tls, auth_svc) == NOTOK)
+       if (pop_init (host, port, user, proxy, snoop, sasl, saslmech,
+                     tls, auth_svc) == NOTOK)
            adios (NULL, "%s", response);
 
        /* Check if there are any messages */
            adios (NULL, "%s", response);
 
        /* Check if there are any messages */
index cb7d5652a04b4fb393a966803b015bff719439a0..69ed3bd416afd8924012f4431bef9aa6935a1e56 100644 (file)
@@ -2515,7 +2515,7 @@ openFTP (CT ct, char **file)
                  LocalName (1));
        pass = buffer;
     } else {
                  LocalName (1));
        pass = buffer;
     } else {
-       ruserpass (e->eb_site, &username, &password);
+       ruserpass (e->eb_site, &username, &password, 0);
        user = username;
        pass = password;
     }
        user = username;
        pass = password;
     }
index 0f164c39ff2a366b866d5b715edff2171e1cc18b..a4613c27dab71d1189b741c22e1d4b98c33a57c6 100644 (file)
@@ -350,23 +350,20 @@ remotemail (char *host, char *port, char *user, char *proxy, int notifysw,
            const char *auth_svc)
 {
     int nmsgs, nbytes, status;
            const char *auth_svc)
 {
     int nmsgs, nbytes, status;
-    struct nmh_creds creds = { 0, 0, 0 };
 
     if (auth_svc == NULL) {
        if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
            adios (NULL, "must specify -authservice with -saslmech xoauth2");
        }
 
     if (auth_svc == NULL) {
        if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
            adios (NULL, "must specify -authservice with -saslmech xoauth2");
        }
-       nmh_get_credentials (host, user, sasl, &creds);
     } else {
        if (user == NULL) {
            adios (NULL, "must specify -user with -saslmech xoauth2");
        }
     } else {
        if (user == NULL) {
            adios (NULL, "must specify -user with -saslmech xoauth2");
        }
-       creds.user = user;
     }
 
     /* open the POP connection */
     }
 
     /* open the POP connection */
-    if (pop_init (host, port, creds.user, creds.password, proxy, snoop, sasl,
-                 saslmech, tls, auth_svc) == NOTOK
+    if (pop_init (host, port, user, proxy, snoop, sasl, saslmech, tls,
+                 auth_svc) == NOTOK
            || pop_stat (&nmsgs, &nbytes) == NOTOK     /* check for messages  */
            || pop_quit () == NOTOK) {                 /* quit POP connection */
        advise (NULL, "%s", response);
            || pop_stat (&nmsgs, &nbytes) == NOTOK     /* check for messages  */
            || pop_quit () == NOTOK) {                 /* quit POP connection */
        advise (NULL, "%s", response);
index cf6b804223e5b77cbc998d7aac8a27aefa930b8f..50cdf09b12c79bc546f4e3470cad3fc4a72727f2 100644 (file)
@@ -18,7 +18,6 @@
 #define        TRMLEN  (sizeof TRM - 1)
 
 static int poprint = 0;
 #define        TRMLEN  (sizeof TRM - 1)
 
 static int poprint = 0;
-static int pophack = 0;
 
 char response[BUFSIZ];
 static netsec_context *nsc = NULL;
 
 char response[BUFSIZ];
 static netsec_context *nsc = NULL;
@@ -134,8 +133,8 @@ parse_proxy(char *proxy, char *host)
 }
 
 int
 }
 
 int
-pop_init (char *host, char *port, char *user, char *pass, char *proxy,
-         int snoop, int sasl, char *mech, int tls, const char *oauth_svc)
+pop_init (char *host, char *port, char *user, char *proxy, int snoop,
+         int sasl, char *mech, int tls, const char *oauth_svc)
 {
     int fd1, fd2;
     char buffer[BUFSIZ];
 {
     int fd1, fd2;
     char buffer[BUFSIZ];
@@ -253,11 +252,21 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy,
                        return NOTOK;
                    }
                    return OK;
                        return NOTOK;
                    }
                    return OK;
-               } else
-               if (command ("USER %s", user) != NOTOK
-                   && command ("%s %s", (pophack++, "PASS"),
-                                       pass) != NOTOK)
-               return OK;
+               } else {
+                   nmh_creds_t creds;
+
+                   if (!(creds = nmh_get_credentials(host, user)))
+                       return NOTOK;
+                   if (command ("USER %s", nmh_cred_get_user(creds))
+                                                               != NOTOK) {
+                       if (command("PASS %s", nmh_cred_get_password(creds))
+                                                               != NOTOK) {
+                           nmh_credentials_free(creds);
+                           return OK;
+                       }
+                   }
+                   nmh_credentials_free(creds);
+               }
            }
            strncpy (buffer, response, sizeof(buffer));
            command ("QUIT");
            }
            strncpy (buffer, response, sizeof(buffer));
            command ("QUIT");