From: David Levine Date: Sun, 14 Apr 2013 14:53:32 +0000 (-0500) Subject: A "credentials" mh-profile entry has been added. This allows X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/52a236230220232fd632b5aa88eb9bb31dba346e?hp=a431fb0f788cf93c9d93c3ad268fa0813e1bf2ef A "credentials" mh-profile entry has been added. This allows post(8), whom(1), send(1), inc(1), and msgchk(1) to (optionally) honour the username in the .netrc file [Bug #23168]. And, it allows specification of any valid filename in place of $HOME/.netrc. --- diff --git a/Makefile.am b/Makefile.am index 470a7635..78cce559 100644 --- a/Makefile.am +++ b/Makefile.am @@ -518,8 +518,8 @@ sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr/ambigsw.c sbr/atooi.c sbr/arglist.c \ sbr/context_find.c sbr/context_foil.c sbr/context_read.c \ sbr/context_replace.c sbr/context_save.c \ sbr/copy.c sbr/copyip.c sbr/cpydata.c \ - sbr/cpydgst.c sbr/crawl_folders.c sbr/discard.c \ - sbr/done.c sbr/dtimep.l sbr/dtime.c \ + sbr/cpydgst.c sbr/crawl_folders.c sbr/credentials.c \ + sbr/discard.c sbr/done.c sbr/dtimep.l sbr/dtime.c \ sbr/escape_addresses.c \ sbr/error.c sbr/ext_hook.c sbr/fdcompare.c \ sbr/folder_addmsg.c sbr/folder_delmsgs.c \ diff --git a/config/config.c b/config/config.c index 4024d305..151f7fc2 100644 --- a/config/config.c +++ b/config/config.c @@ -103,6 +103,9 @@ char *mh_defaults = nmhetcdir (/mh.profile); /* default name of user profile */ char *mh_profile = ".mh_profile"; +/* name of credentials file, defaults to .netrc in either Path or $HOME. */ +char *credentials_file; + /* name of current message "sequence" */ char *current = "cur"; diff --git a/docs/pending-release-notes b/docs/pending-release-notes index 3b225819..e88165de 100644 --- a/docs/pending-release-notes +++ b/docs/pending-release-notes @@ -120,3 +120,7 @@ BUG FIXES - Removed the artificial limit of 1000 messages at a time for rmmproc. - Fixed decoding of header fields when they contain a character that can't be converted. +- post(8) -sasl now honours username in .netrc [Bug #23168]. whom(1), + send(1), inc(1), and msgchk(1) also benefit from this fix. And, nmh + now supports specification of any valid filename in place of + $HOME/.netrc. diff --git a/h/mh.h b/h/mh.h index f5fd66be..354f3fa5 100644 --- a/h/mh.h +++ b/h/mh.h @@ -357,6 +357,17 @@ typedef struct m_getfld_state *m_getfld_state_t; #define NMH_ATTACH_HEADER "Nmh-Attachment" /* Default header for -attach */ +/* + * credentials management + */ +struct nmh_creds { + char *host; + char *user; + char *password; +}; + +typedef struct nmh_creds *nmh_creds_t; + /* * miscellaneous macros */ @@ -405,6 +416,7 @@ extern char *catproc; extern char *components; extern char *context; extern char *current; +extern char *credentials_file; extern char *defaultfolder; extern char *digestcomps; extern char *distcomps; diff --git a/h/prototypes.h b/h/prototypes.h index 8fa31576..94be46af 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -148,7 +148,7 @@ char *pwd (void); char *r1bindex(char *, int); void readconfig (struct node **, FILE *, char *, int); int refile (char **, char *); -void ruserpass(char *, char **, char **); +void ruserpass (char *, char **, char **); int remdir (char *); void scan_detect_mbox_style (FILE *); void scan_finished (); @@ -228,3 +228,9 @@ int what_now (char *, int, int, char *, char *, int WhatNow(int, char **); int writeBase64aux(FILE *, FILE *); int writeBase64 (unsigned char *, size_t, unsigned char *); + +/* + * credentials management + */ +void init_credentials_file (); +int nmh_get_credentials (char *, char *, int, nmh_creds_t); diff --git a/man/inc.man b/man/inc.man index b534d1b1..8d0a4626 100644 --- a/man/inc.man +++ b/man/inc.man @@ -1,4 +1,4 @@ -.TH INC %manext1% "February 16, 2013" "%nmhversion%" +.TH INC %manext1% "April 14, 2013" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -212,40 +212,11 @@ the environment variable. The switch specifies the port name or number used to connect to the POP server. If unspecified the default is \*(lqpop3\*(rq. .PP -The default is for -.B inc -to assume that your account name on -the POP server is the same as your current username. To specify -a different username, use the +To specify a username for authentication with the POP server, use the .B \-user .I username -switch. -.PP -When using POP, you will normally need to type the password for -your account on the POP server, in order to retrieve your messages. -It is possible to automate this process by creating a -.RI \*(lq .netrc \*(rq -file containing your login account information for this POP server. -For each POP server, this file should have a line of the following -form. Replace the words -.IR mypopserver , -.IR mylogin , -and -.I mypassword -with your own account information. -.PP -.RS 5 -.B machine -.I mypopserver -.B login -.I mylogin -.B password -.I mypassword -.RE -.PP -This -.RI \*(lq .netrc \*(rq -file should be owned and readable only by you. +switch. The credentials profile entry in the mh_profile(5) man page +describes the ways to supply a username and password. .PP If passed the .B \-proxy @@ -283,8 +254,9 @@ has been compiled with SASL support, the switch will enable the use of SASL authentication. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the -.RI \*(lq .netrc \*(rq -file can be used to store this password). The +.I netrc +file can be used to store this password, as described in the +mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism. .PP @@ -332,6 +304,7 @@ To name sequences denoting unseen messages. .IR mhmail (1), .IR scan (1), .IR mh\-mail (5), +.IR mh\-profile (5), .IR post (8), .IR rcvstore (1) .SH DEFAULTS diff --git a/man/mh-profile.man b/man/mh-profile.man index a85522b0..81d436a1 100644 --- a/man/mh-profile.man +++ b/man/mh-profile.man @@ -1,4 +1,4 @@ -.TH MH-PROFILE %manext5% "March 18, 2013" "%nmhversion%" +.TH MH-PROFILE %manext5% "April 14, 2013" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -374,6 +374,92 @@ puts in the \*(lqFrom:\*(rq header; do not include an address in the signature text. The \*(lqLocal\-Mailbox\*(rq profile component supersedes all of this. (profile, no default) .RE +.PP +.BR credentials : +\&legacy +.RS 5 +Indicates how the username and password credentials will be retrieved +for access to external servers, such as those that provide SMTP or POP +service. The supported entry values are \*(lqlegacy\*(rq and +.RI \*(lqfile: netrc \*(rq. +With \*(lqlegacy\*(rq, or if there is no credentials entry, the +username is the first of: +.PP +.RS 5 +1) +.B \-user +switch to +.BR send , +.BR post , +.BR whom , +.BR inc , +or +.B msgchk +program +.br +2) the login name on the local machine +.RE +.PP +The password for SMTP services is the first of: +.PP +.RS 5 +1) password value from matching entry in file named \*(lq.netrc\*(rq +in the user's home directory +.br +2) password obtained by interactively prompting the user +.RE +.PP +The password for POP service when the +.B \-sasl +switch is used with one of these programs is the login name on the +local machine. +.PP +With a +.RI \*(lqfile: netrc \*(rq +.B credentials +entry, the username is the first of: +.PP +.RS 5 +1) +.B \-user +switch to program +.br +2) login name from matching entry in +.I netrc +file +.br +3) value provided by user in response to interactive query +.RE +.PP +Similarly, the password is provided either in the +.I netrc +file or interactively. +.I netrc +can be any valid filename, either absolute or relative to Path or +$HOME. The +.I netrc +file contains authentication information, for each server, +using a line of the following form. Replace the words +.IR myserver , +.IR mylogin , +and +.I mypassword +with your own account information: +.PP +.RS 5 +.B machine +.I myserver +.B login +.I mylogin +.B password +.I mypassword +.RE +.PP +This +.I netrc +file must be owned and readable only by you. +(profile, default: legacy) +.RE .SS "Process Profile Entries" The following profile elements are used whenever an .B nmh diff --git a/man/msgchk.man b/man/msgchk.man index cadf46ca..80ea71b1 100644 --- a/man/msgchk.man +++ b/man/msgchk.man @@ -1,4 +1,4 @@ -.TH MSGCHK %manext1% "January 27, 2012" "%nmhversion%" +.TH MSGCHK %manext1% "April 14, 2013" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -87,38 +87,11 @@ switch is given, will query this POP service host as to the status of mail waiting. .PP -The default is for -.B msgchk -to assume that your account name -on the POP server is the same as your current username. To specify -a different username, use the `\-user\ username' switch. -.PP -When using POP, you will normally need to type the password for -your account on the POP server, in order to retrieve your messages. -It is possible to automate this process by creating a -.RI \*(lq \&.netrc \*(rq -file containing your login account information for this POP server. -For each POP server, this file should have a line of the following -form. Replace the words -.IR mypopserver , -.IR mylogin , -and -.I mypassword -with -your own account information. -.PP -.RS 5 -machine -.I mypopserver -login -.I mylogin -password -.I mypassword -.RE -.PP -This -.RI \*(lq \&.netrc \*(rq -file should be owned and readable only by you. +To specify a username for authentication with the POP server, use the +.B \-user +.I username +switch. The credentials profile entry in the mh_profile(5) man page +describes the ways to supply a username and password. .PP For debugging purposes, there is also a switch .BR \-snoop , @@ -133,8 +106,9 @@ has been compiled with SASL support, the switch will enable the use of SASL authentication. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the -.RI \*(lq \&.netrc \*(rq -file can be used to store this password). The +.I netrc +file can be used to store this password, as described in the +mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism. .PP @@ -162,7 +136,8 @@ switch. None .fi .SH "SEE ALSO" -.IR inc (1) +.IR inc (1), +.IR mh\-mail (5) .SH DEFAULTS .nf .RB ` user "' defaults to the current user" diff --git a/man/post.man b/man/post.man index 8b2c9435..5e811739 100644 --- a/man/post.man +++ b/man/post.man @@ -1,4 +1,4 @@ -.TH POST %manext8% "April 9, 2013" "%nmhversion%" +.TH POST %manext8% "April 14, 2013" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -204,14 +204,17 @@ switches will enable and disable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the -.RI \*(lq \&.netrc \*(rq -file can be used to store this password). +.I netrc +file can be used to store this password, as described in the +mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user -switch can be used to select a authorization userid -to provide to SASL other than the default. +switch can be used to select a authorization userid to provide to SASL +other than the default. The credentials profile entry in the +mh_profile(5) man page describes the ways to supply a username and +password. .PP If SASL authentication is successful, .BR nmh @@ -266,6 +269,7 @@ consult the user's .IR send (1), .IR mh\-mail (5), .IR mh\-alias (5), +.IR mh\-profile (5), .IR mh\-tailor (5) .PP .I "Standard for the Format of ARPA Internet Text Messages" diff --git a/man/send.man b/man/send.man index fe528cb7..ece0e5c8 100644 --- a/man/send.man +++ b/man/send.man @@ -1,7 +1,7 @@ .\" .\" %nmhwarning% .\" -.TH SEND %manext1% "April 9, 2013" "%nmhversion%" +.TH SEND %manext1% "April 14, 2013" "%nmhversion%" .SH NAME send \- send a message .SH SYNOPSIS @@ -395,14 +395,17 @@ switches will enable and disable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the -.RI \*(lq \&.netrc \*(rq -file can be used to store this password). +.I netrc +file can be used to store this password, as described in the +mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user -switch can be used to select a authorization userid -to provide to SASL other than the default. +switch can be used to select a authorization userid to provide to SASL +other than the default. The credentials profile entry in the +mh_profile(5) man page describes the ways to supply a username and +password. .PP If SASL authentication is successful, .BR nmh @@ -474,6 +477,7 @@ for more information. .IR repl (1), .IR whatnow (1), .IR mh\-alias (5), +.IR mh\-profile (5), .IR mh\-tailor (5), .IR post (8) .SH DEFAULTS diff --git a/man/whom.man b/man/whom.man index f11fc024..cccccd4c 100644 --- a/man/whom.man +++ b/man/whom.man @@ -1,4 +1,4 @@ -.TH WHOM %manext1% "April 9, 2013" "%nmhversion%" +.TH WHOM %manext1% "April 14, 2013" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -84,14 +84,17 @@ switch will enable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the -.RI \*(lq \&.netrc \*(rq -file can be used to store this password). +.I netrc +file can be used to store this password, as described in the +mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user -switch can be used to select a authorization userid -to provide to SASL other than the default. +switch can be used to select a authorization userid to provide to SASL +other than the default. The credentials profile entry in the +mh_profile(5) man page describes the ways to supply a username and +password. .PP If SASL authentication is successful, .BR nmh @@ -145,6 +148,7 @@ for more information. .fi .SH "SEE ALSO" .IR mh\-alias (5), +.IR mh\-profile (5), .IR post (8) .SH DEFAULTS .nf diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index c973c919..8b17042c 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -99,7 +99,7 @@ static FILE *sm_wfp = NULL; static sasl_conn_t *conn = NULL; /* SASL connection state */ static int sasl_complete = 0; /* Has authentication succeded? */ static sasl_ssf_t sasl_ssf; /* Our security strength factor */ -static char *sasl_pw_context[2]; /* Context to pass into sm_get_pass */ +static char *sasl_pw_context[3]; /* Context to pass into sm_get_pass */ static int maxoutbuf; /* Maximum crypto output buffer */ static char *sasl_outbuffer; /* SASL output buffer for encryption */ static int sasl_outbuflen; /* Current length of data in outbuf */ @@ -109,10 +109,10 @@ static int sm_get_pass(sasl_conn_t *, void *, int, sasl_secret_t **); static sasl_callback_t callbacks[] = { { SASL_CB_USER, (sasl_callback_ft) sm_get_user, NULL }, #define SM_SASL_N_CB_USER 0 - { SASL_CB_PASS, (sasl_callback_ft) sm_get_pass, NULL }, -#define SM_SASL_N_CB_PASS 1 { SASL_CB_AUTHNAME, (sasl_callback_ft) sm_get_user, NULL }, -#define SM_SASL_N_CB_AUTHNAME 2 +#define SM_SASL_N_CB_AUTHNAME 1 + { SASL_CB_PASS, (sasl_callback_ft) sm_get_pass, NULL }, +#define SM_SASL_N_CB_PASS 2 { SASL_CB_LIST_END, NULL, NULL }, }; @@ -820,17 +820,12 @@ sm_auth_sasl(char *user, int saslssf, char *mechlist, char *inhost) sasl_security_properties_t secprops; sasl_ssf_t *ssf; int *outbufmax; + char *pass = NULL; /* * Initialize the callback contexts */ - if (user == NULL) - user = getusername(); - - callbacks[SM_SASL_N_CB_USER].context = user; - callbacks[SM_SASL_N_CB_AUTHNAME].context = user; - /* * This is a _bit_ of a hack ... but if the hostname wasn't supplied * to us on the command line, then call getpeername and do a @@ -861,8 +856,12 @@ sm_auth_sasl(char *user, int saslssf, char *mechlist, char *inhost) strncpy(host, inhost, sizeof(host) - 1); } + callbacks[SM_SASL_N_CB_USER].context = user; + callbacks[SM_SASL_N_CB_AUTHNAME].context = user; + sasl_pw_context[0] = host; sasl_pw_context[1] = user; + sasl_pw_context[2] = pass; callbacks[SM_SASL_N_CB_PASS].context = sasl_pw_context; @@ -1072,7 +1071,6 @@ sm_get_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) { char **pw_context = (char **) context; - char *pass = NULL; int len; NMH_UNUSED (conn); @@ -1080,20 +1078,14 @@ sm_get_pass(sasl_conn_t *conn, void *context, int id, if (! psecret || id != SASL_CB_PASS) return SASL_BADPARAM; - ruserpass(pw_context[0], &(pw_context[1]), &pass); - - len = strlen(pass); - - *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len); + len = strlen (pw_context[2]); - if (! *psecret) { - free(pass); + if (! (*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len))) { return SASL_NOMEM; } (*psecret)->len = len; - strcpy((char *) (*psecret)->data, pass); -/* free(pass); */ + strcpy((char *) (*psecret)->data, pw_context[2]); return SASL_OK; } diff --git a/sbr/credentials.c b/sbr/credentials.c new file mode 100644 index 00000000..9d4e41c2 --- /dev/null +++ b/sbr/credentials.c @@ -0,0 +1,74 @@ +/* + * This code is Copyright (c) 2013, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. + */ + +#include +#include +#include + +void +init_credentials_file () { + if (credentials_file == NULL) { + char *cred_style = context_find ("credentials"); + + if (cred_style == NULL || ! strcmp (cred_style, "legacy")) { + char *hdir = getenv ("HOME"); + + credentials_file = concat (hdir ? hdir : ".", "/.netrc", NULL); + } else if (! strncasecmp (cred_style, "file:", 5)) { + struct stat st; + char *filename = cred_style + 5; + + while (*filename && isspace ((int) *filename)) ++filename; + + if (*filename == '/') { + credentials_file = filename; + } else { + credentials_file = m_maildir (filename); + if (stat (credentials_file, &st) != OK) { + credentials_file = + concat (mypath ? mypath : ".", "/", filename, NULL); + if (stat (credentials_file, &st) != OK) { + admonish (NULL, "unable to find credentials file %s", + filename); + } + } + } + } + } +} + +int +nmh_get_credentials (char *host, char *user, int sasl, nmh_creds_t creds) { + char *cred_style = context_find ("credentials"); + + init_credentials_file (); + creds->host = host; + + if (cred_style == NULL || ! strcmp (cred_style, "legacy")) { + /* This is what inc.c and msgchk.c used to contain. */ + if (user == NULL) { + creds->user = getusername (); + } + if (sasl) { + creds->password = getusername (); + } else { + ruserpass (host, &creds->user, &creds->password); + } + } else if (! strncasecmp (cred_style, "file:", 5)) { + /* + * Determine user using the first of: + * 1) -user switch + * 2) matching host entry with login in a credentials file + * such as ~/.netrc + * 3) interactively request from user (as long as the + * credentials file didn't have a "default" token) + */ + creds->user = user; + ruserpass (host, &creds->user, &creds->password); + } + + return OK; +} diff --git a/sbr/ruserpass.c b/sbr/ruserpass.c index d422f67d..f5ef74a4 100644 --- a/sbr/ruserpass.c +++ b/sbr/ruserpass.c @@ -14,6 +14,10 @@ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Portions of this code are Copyright (c) 2013, by the authors of + * nmh. See the COPYRIGHT file in the root directory of the nmh + * distribution for complete copyright information. */ #include @@ -23,10 +27,6 @@ static FILE *cfile; -#ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 64 -#endif - #define DEFAULT 1 #define LOGIN 2 #define PASSWD 3 @@ -62,78 +62,78 @@ static int token(void); void ruserpass(char *host, char **aname, char **apass) { - char *hdir, buf[BUFSIZ]; int t, usedefault = 0; struct stat stb; - hdir = getenv("HOME"); - if (hdir == NULL) - hdir = "."; - snprintf(buf, sizeof(buf), "%s/.netrc", hdir); - cfile = fopen(buf, "r"); + init_credentials_file (); + + cfile = fopen (credentials_file, "r"); if (cfile == NULL) { if (errno != ENOENT) - perror(buf); - goto done; - } - - while ((t = token())) { - switch(t) { - case DEFAULT: - usedefault = 1; - /* FALL THROUGH */ - - case MACH: - if (!usedefault) { - if (token() != ID) + perror (credentials_file); + } else { + while ((t = token())) { + switch(t) { + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's host name. + */ + if (strcasecmp(host, tokval) == 0) + goto match; continue; - /* - * Allow match either for user's host name. - */ - if (strcasecmp(host, tokval) == 0) - goto match; - continue; - } -match: - while ((t = token()) && t != MACH && t != DEFAULT) { - switch(t) { - case LOGIN: - if (token() && *aname == 0) { - *aname = mh_xmalloc((size_t) strlen(tokval) + 1); - strcpy(*aname, tokval); - } - break; - case PASSWD: - if (fstat(fileno(cfile), &stb) >= 0 && - (stb.st_mode & 077) != 0) { - /* We make this a fatal error to force the user to correct it */ - advise(NULL, "Error - ~/.netrc file must not be world or group readable."); - adios(NULL, "Remove password or correct file permissions."); - } - if (token() && *apass == 0) { - *apass = mh_xmalloc((size_t) strlen(tokval) + 1); - strcpy(*apass, tokval); + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) { + switch(t) { + case LOGIN: + if (token() && *aname == 0) { + *aname = mh_xmalloc((size_t) strlen(tokval) + 1); + strcpy(*aname, tokval); + } + break; + + case PASSWD: + if (fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + /* We make this a fatal error to force the + user to correct it. */ + advise(NULL, "Error - file %s must not be world or " + "group readable.", credentials_file); + adios(NULL, "Remove password or correct file " + "permissions."); + } + if (token() && *apass == 0) { + *apass = mh_xmalloc((size_t) strlen(tokval) + 1); + strcpy(*apass, tokval); + } + break; + + case ACCOUNT: + break; + + case MACDEF: + fclose(cfile); + return; + + default: + fprintf(stderr, + "Unknown keyword %s in credentials file %s\n", + tokval, credentials_file); + break; } - break; - case ACCOUNT: - break; - - case MACDEF: - goto done_close; - break; - default: - fprintf(stderr, "Unknown .netrc keyword %s\n", tokval); - break; } + return; } - goto done; } } -done_close: - fclose(cfile); - -done: if (!*aname) { char tmp[80]; char *myname; diff --git a/test/inc/test-pop b/test/inc/test-pop index 7724ae3c..2bb0bb4d 100755 --- a/test/inc/test-pop +++ b/test/inc/test-pop @@ -73,6 +73,34 @@ run_test "inc -file $MH_TEST_DIR/inc.mbox -truncate" \ 11+ 12/17 No Such User Hello< "$netrc" +chmod 600 "$netrc" +echo "credentials: file:${netrc}" >>$MH + +pid=`"${MH_OBJ_DIR}/test/fakepop" "$testmessage" "$testport" \ + "$TESTUSER" "$TESTPASS"` + +touch "$MH_TEST_DIR/inc.mbox" +run_test "inc -user ${TESTUSER} -host 127.0.0.1 -port $testport -width 65 \ + -pack $MH_TEST_DIR/inc.mbox" \ + "Incorporating new mail into (null)... + + 1 12/17 No Such User Hello<= MAXVEC-1) adios (NULL, "you can only check %d users at a time", MAXVEC-1); else - vec[vecp++] = cp; + user = vec[vecp++] = cp; continue; case SNOOPSW: @@ -206,26 +205,26 @@ main (int argc, char **argv) snoop, sasl, saslmech); } } else { - - if (vecp == 0) { - char *home; - - /* Not sure this check makes sense... */ - if (!geteuid() || NULL == (home = getenv("HOME"))) { - pw = getpwnam (user); - if (pw == NULL) - adios (NULL, "unable to get information about user"); - home = pw->pw_dir; - } - status = checkmail (user, home, datesw, notifysw, 1); - } else { - for (vecp = 0; vec[vecp]; vecp++) { - if ((pw = getpwnam (vec[vecp]))) - status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0); - else - advise (NULL, "no such user as %s", vec[vecp]); + if (user == NULL) user = getusername (); + if (vecp == 0) { + char *home; + + /* Not sure this check makes sense... */ + if (!geteuid() || NULL == (home = getenv("HOME"))) { + pw = getpwnam (user); + if (pw == NULL) + adios (NULL, "unable to get information about user"); + home = pw->pw_dir; + } + status = checkmail (user, home, datesw, notifysw, 1); + } else { + for (vecp = 0; vec[vecp]; vecp++) { + if ((pw = getpwnam (vec[vecp]))) + status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0); + else + advise (NULL, "no such user as %s", vec[vecp]); + } } - } } /* host == NULL */ done (status); @@ -327,19 +326,14 @@ remotemail (char *host, char *port, char *user, char *proxy, int notifysw, int personal, int snoop, int sasl, char *saslmech) { int nmsgs, nbytes, status; - char *pass = NULL; - - if (user == NULL) - user = getusername (); - if (sasl) - pass = getusername (); - else - ruserpass (host, &user, &pass); + struct nmh_creds creds = { 0, 0, 0 }; /* open the POP connection */ - if (pop_init (host, port, user, pass, proxy, snoop, sasl, saslmech) == NOTOK - || pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */ - || pop_quit () == NOTOK) { /* quit POP connection */ + nmh_get_credentials (host, user, sasl, &creds); + if (pop_init (host, port, creds.user, creds.password, proxy, snoop, sasl, + saslmech) == NOTOK + || pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */ + || pop_quit () == NOTOK) { /* quit POP connection */ advise (NULL, "%s", response); return 1; } diff --git a/uip/popsbr.c b/uip/popsbr.c index fb66a93b..bdd55c58 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -46,6 +46,7 @@ static int sasl_get_user(void *, int, const char **, unsigned *); static int sasl_get_pass(sasl_conn_t *, void *, int, sasl_secret_t **); struct pass_context { char *user; + char *password; char *host; }; @@ -71,7 +72,7 @@ static int command(const char *, ...); static int multiline(void); #ifdef CYRUS_SASL -static int pop_auth_sasl(char *, char *, char *); +static int pop_auth_sasl(char *, char *, char *, char *); static int sasl_fgetc(FILE *); #endif /* CYRUS_SASL */ @@ -91,7 +92,7 @@ static int putline (char *, FILE *); */ int -pop_auth_sasl(char *user, char *host, char *mech) +pop_auth_sasl(char *user, char *password, char *host, char *mech) { int result, status, sasl_capability = 0; unsigned int buflen, outlen; @@ -159,6 +160,7 @@ pop_auth_sasl(char *user, char *host, char *mech) callbacks[POP_SASL_CB_N_USER].context = user; p_context.user = user; p_context.host = host; + p_context.password = password; callbacks[POP_SASL_CB_N_PASS].context = &p_context; result = sasl_client_init(callbacks); @@ -351,7 +353,7 @@ static int sasl_get_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) { struct pass_context *p_context = (struct pass_context *) context; - char *pass = NULL; + char *pass = p_context->password; int len; NMH_UNUSED (conn); @@ -359,8 +361,6 @@ sasl_get_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) if (! psecret || id != SASL_CB_PASS) return SASL_BADPARAM; - ruserpass(p_context->user, &(p_context->host), &pass); - len = strlen(pass); *psecret = (sasl_secret_t *) mh_xmalloc(sizeof(sasl_secret_t) + len); @@ -510,7 +510,7 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, if (*response == '+') { # ifdef CYRUS_SASL if (sasl) { - if (pop_auth_sasl(user, host, mech) != NOTOK) + if (pop_auth_sasl(user, pass, host, mech) != NOTOK) return OK; } else # endif /* CYRUS_SASL */