password when it is necessary.
/*
* credentials management
*/
-struct nmh_creds {
- char *host;
- char *user;
- char *password;
-};
-
+struct nmh_creds;
typedef struct nmh_creds *nmh_creds_t;
/*
* 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 *));
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 ();
* 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
#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) {
}
}
-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 ();
- 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)) {
/*
* 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);
- 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);
}
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);
}
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);
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)
- *len = strlen(nsc->ns_userid);
+ *len = strlen(*result);
return SASL_OK;
}
sasl_secret_t **psecret)
{
netsec_context *nsc = (netsec_context *) context;
+ const char *password;
int len;
NMH_UNUSED(conn);
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
return SASL_NOMEM;
(*psecret)->len = len;
- strcpy((char *) (*psecret)->data, nsc->sasl_creds->password);
+ strcpy((char *) (*psecret)->data, password);
nsc->sasl_secret = *psecret;
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;
}
}
- if (!*aname) {
+ if (!*aname && ! (flags & RUSERPASS_NO_PROMPT_USER)) {
char tmp[80];
char *myname;
*aname = mh_xstrdup(myname);
}
- if (!*apass) {
+ if (!*apass && ! (flags & RUSERPASS_NO_PROMPT_PASSWORD)) {
char prompt[256];
char *mypass;
* 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");
}
- nmh_get_credentials (host, user, sasl, &creds);
} else {
if (user == NULL) {
adios (NULL, "must specify -user with -saslmech xoauth2");
}
- creds.user = user;
}
/*
* 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 */
LocalName (1));
pass = buffer;
} else {
- ruserpass (e->eb_site, &username, &password);
+ ruserpass (e->eb_site, &username, &password, 0);
user = username;
pass = password;
}
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");
}
- nmh_get_credentials (host, user, sasl, &creds);
} else {
if (user == NULL) {
adios (NULL, "must specify -user with -saslmech xoauth2");
}
- creds.user = user;
}
/* 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);
#define TRMLEN (sizeof TRM - 1)
static int poprint = 0;
-static int pophack = 0;
char response[BUFSIZ];
static netsec_context *nsc = NULL;
}
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];
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");