diff options
-rw-r--r-- | alpine/alpine.c | 1 | ||||
-rw-r--r-- | alpine/imap.c | 75 | ||||
-rw-r--r-- | alpine/imap.h | 2 | ||||
-rw-r--r-- | imap/src/c-client/imap4r1.c | 6 | ||||
-rw-r--r-- | imap/src/c-client/mail.c | 14 | ||||
-rw-r--r-- | imap/src/c-client/mail.h | 5 | ||||
-rw-r--r-- | imap/src/c-client/nntp.c | 5 | ||||
-rw-r--r-- | imap/src/c-client/pop3.c | 4 | ||||
-rw-r--r-- | imap/src/c-client/smtp.c | 3 | ||||
-rw-r--r-- | pith/imap.c | 58 | ||||
-rw-r--r-- | pith/imap.h | 2 | ||||
-rw-r--r-- | pith/pine.hlp | 5 |
12 files changed, 175 insertions, 5 deletions
diff --git a/alpine/alpine.c b/alpine/alpine.c index 545406bf..7ca1047c 100644 --- a/alpine/alpine.c +++ b/alpine/alpine.c @@ -333,6 +333,7 @@ main(int argc, char **argv) mail_parameters(NULL, SET_FREESTREAMSPAREP, (void *) sp_free_callback); mail_parameters(NULL, SET_FREEELTSPAREP, (void *) free_pine_elt); mail_parameters(NULL, SET_FREEBODYSPAREP, (void *) free_body_sparep); + mail_parameters(NULL, SET_ERASEPASSWORD, (void *) pine_delete_pwd); mail_parameters(NULL, SET_OA2CLIENTGETACCESSCODE, (void *) oauth2_get_access_code); mail_parameters(NULL, SET_OA2CLIENTINFO, (void *) oauth2_get_client_info); mail_parameters(NULL, SET_OA2DEVICEINFO, (void *) oauth2_set_device_info); diff --git a/alpine/imap.c b/alpine/imap.c index 39edda1f..95ce4396 100644 --- a/alpine/imap.c +++ b/alpine/imap.c @@ -904,6 +904,16 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method, if(registered) oa2list->param[OA2_State].value = login->param[OA2_State].value; + if(login->cancel_refresh_token){ + login->cancel_refresh_token = 0; + imap_delete_passwd_auth(&mm_login_list, user, + registered ? hostlist2 : hostlist, + (mb->sslflag||mb->tlsflag), OA2NAME); +#ifdef LOCAL_PASSWD_CACHE + write_passfile(ps_global->pinerc, mm_login_list); +#endif /* LOCAL_PASSWD_CACHE */ + } + /* * We check if we have a refresh token saved somewhere, if so * we use it to get a new access token, otherwise we need to @@ -947,7 +957,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method, NewExpirationTime = 0L; ChangeAccessToken = ChangeRefreshToken = ChangeExpirationTime = 0; - if(token && *token && !login->cancel_refresh_token){ + if(token && *token){ char *s, *t; s = token; @@ -1002,7 +1012,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method, /* Default to saving what we already had saved */ - SaveRefreshToken = login->cancel_refresh_token ? NULL : NewRefreshToken; + SaveRefreshToken = NewRefreshToken; SaveAccessToken = NewAccessToken; SaveExpirationTime = NewExpirationTime; @@ -1068,7 +1078,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method, } if(token) fs_give((void **) &token); - if(!ChangeAccessToken && !ChangeRefreshToken && !login->cancel_refresh_token) + if(!ChangeAccessToken && !ChangeRefreshToken) return; /* get ready to save this information. The format will be @@ -1121,6 +1131,65 @@ set_alpine_id(char *pname, char *pversion) return id; } +void +pine_delete_pwd(NETMBX *mb, char *user) +{ + char hostlist0[MAILTMPLEN], hostlist1[MAILTMPLEN]; + char port[20], non_def_port[20]; + STRLIST_S hostlist[2]; + MMLOGIN_S *l; + struct servent *sv; + /* do not invalidate password on cancel */ + if(ps_global->user_says_cancel != 0) + return; + + dprint((9, "pine_delete_pwd\n")); + + /* setup hostlist */ + non_def_port[0] = '\0'; + if(mb->port && mb->service && + (sv = getservbyname(mb->service, "tcp")) && + (mb->port != ntohs(sv->s_port))){ + snprintf(non_def_port, sizeof(non_def_port), ":%lu", mb->port); + non_def_port[sizeof(non_def_port)-1] = '\0'; + dprint((9, "mm_login: using non-default port=%s\n", + non_def_port ? non_def_port : "?")); + } + + if(*non_def_port){ + strncpy(hostlist0, mb->host, sizeof(hostlist0)-1); + hostlist0[sizeof(hostlist0)-1] = '\0'; + strncat(hostlist0, non_def_port, sizeof(hostlist0)-strlen(hostlist0)-1); + hostlist0[sizeof(hostlist0)-1] = '\0'; + hostlist[0].name = hostlist0; + if(mb->orighost && mb->orighost[0] && strucmp(mb->host, mb->orighost)){ + strncpy(hostlist1, mb->orighost, sizeof(hostlist1)-1); + hostlist1[sizeof(hostlist1)-1] = '\0'; + strncat(hostlist1, non_def_port, sizeof(hostlist1)-strlen(hostlist1)-1); + hostlist1[sizeof(hostlist1)-1] = '\0'; + hostlist[0].next = &hostlist[1]; + hostlist[1].name = hostlist1; + hostlist[1].next = NULL; + } + else + hostlist[0].next = NULL; + } + else{ + hostlist[0].name = mb->host; + if(mb->orighost && mb->orighost[0] && strucmp(mb->host, mb->orighost)){ + hostlist[0].next = &hostlist[1]; + hostlist[1].name = mb->orighost; + hostlist[1].next = NULL; + } + else + hostlist[0].next = NULL; + } + imap_delete_passwd(&mm_login_list, user, hostlist, mb->sslflag||mb->tlsflag); +#ifdef LOCAL_PASSWD_CACHE + write_passfile(ps_global->pinerc, mm_login_list); +#endif /* LOCAL_PASSWD_CACHE */ +} + /*---------------------------------------------------------------------- receive notification from IMAP diff --git a/alpine/imap.h b/alpine/imap.h index 5e1b7703..7885b21e 100644 --- a/alpine/imap.h +++ b/alpine/imap.h @@ -32,11 +32,13 @@ int url_local_certdetails(char *); void pine_sslfailure(char *, char *, unsigned long); void mm_expunged_current(long unsigned int); IDLIST *set_alpine_id(char *, char *); +void pine_delete_pwd(NETMBX *mb, char *user); char *oauth2_get_access_code(unsigned char *, char *, OAUTH2_S *, int *); void oauth2_set_device_info(OAUTH2_S *, char *); int oauth2_elapsed_done(void *); UCS oauth2device_decode_reply(void *, void *); + #ifdef LOCAL_PASSWD_CACHE int get_passfile_passwd(char *, char **, char *, STRLIST_S *, int); int get_passfile_passwd_auth(char *, char **, char *, STRLIST_S *, int, char *); diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c index 155b4d5c..b29d7201 100644 --- a/imap/src/c-client/imap4r1.c +++ b/imap/src/c-client/imap4r1.c @@ -1206,6 +1206,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); mm_log (tmp,NIL); + delete_password(mb, usr); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -1215,6 +1216,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); mm_log (tmp,WARN); fs_give ((void **) &lsterr); + delete_password(mb, usr); } LOCAL->saslcancel = NIL; sprintf (tag,"%08lx",0xffffffff & (stream->gensym++)); @@ -1233,6 +1235,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) if(base && !trial){ /* do it now, instead of later */ mm_log ("IMAP Authentication cancelled",ERROR); + delete_password(mb, usr); return NIL; } /* make sure have a response */ @@ -1250,6 +1253,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) } if (!trial) { /* if main program requested cancellation */ mm_log ("IMAP Authentication cancelled",ERROR); + delete_password(mb, usr); return NIL; } /* no error if protocol-initiated cancel */ @@ -1264,6 +1268,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) sprintf (tmp,"Can not authenticate to IMAP server: %.80s",lsterr); mm_log (tmp,ERROR); } + delete_password(mb, usr); fs_give ((void **) &lsterr); } if(mb && *mb->auth){ @@ -1316,6 +1321,7 @@ long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) if (imap_OK (stream,reply = imap_send (stream,"LOGIN",args))) ret = LONGT; /* success */ else { + delete_password(mb, usr); mm_log (reply->text,WARN); if (!LOCAL->referral && (trial == imap_maxlogintrials)) mm_log ("Too many login failures",ERROR); diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c index 730201c2..471269c0 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -58,6 +58,8 @@ static mailcache_t mailcache = mm_cache; static rfc822out_t mail822out = NIL; /* RFC-822 output generator (new style) */ static rfc822outfull_t mail822outfull = NIL; + /* Erase password (client side) */ +static deletepwd_t erase_password = NIL; /* SMTP verbose callback */ static smtpverbose_t mailsmtpverbose = mm_dlog; /* proxy copy routine */ @@ -581,6 +583,11 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) case GET_SENDCOMMAND: ret = (void *) mailsendcommand; break; + case SET_ERASEPASSWORD: + erase_password = (deletepwd_t) value; + case GET_ERASEPASSWORD: + ret = (void *) erase_password; + break; case SET_SERVICENAME: servicename = (char *) value; @@ -6242,7 +6249,12 @@ unsigned int mail_lookup_auth_name (char *mechanism,long flags) return i; return 0; } - +/* Client side callback warning to delete wrong password */ +void delete_password(NETMBX *mb, char *user) +{ + deletepwd_t ep = mail_parameters(NULL, GET_ERASEPASSWORD, NULL); + if (ep) (ep)(mb, user); +} /* Standard TCP/IP network driver */ static NETDRIVER tcpdriver = { diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index d40d7ebe..8e848201 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -308,6 +308,8 @@ #define SET_IDLETIMEOUT (long) 453 #define GET_FETCHLOOKAHEADLIMIT (long) 454 #define SET_FETCHLOOKAHEADLIMIT (long) 455 +#define GET_ERASEPASSWORD (long) 456 +#define SET_ERASEPASSWORD (long) 457 /* HTTP SUPPORT DEFINES THEIR OWN SET_ AND GET_ CONSTANTS (490..493). See http.h */ /* 5xx: local file drivers */ @@ -1416,6 +1418,7 @@ typedef ADDRESS *(*parsephrase_t) (char *phrase,char *end,char *host); typedef void *(*blocknotify_t) (int reason,void *data); typedef long (*kinit_t) (char *host,char *reason); typedef void (*sendcommand_t) (MAILSTREAM *stream,char *cmd,long flags); +typedef void (*deletepwd_t) (NETMBX *mb,char *user); typedef char *(*newsrcquery_t) (MAILSTREAM *stream,char *mulname,char *name); typedef void (*getacl_t) (MAILSTREAM *stream,char *mailbox,ACLLIST *acl); typedef void (*listrights_t) (MAILSTREAM *stream,char *mailbox,char *id, @@ -1698,6 +1701,8 @@ long mm_diskerror (MAILSTREAM *stream,long errcode,long serious); void mm_fatal (char *string); void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op); +void delete_password (NETMBX *mb, char *user); + extern STRINGDRIVER mail_string; void mail_versioncheck (char *version); void mail_link (DRIVER *driver); diff --git a/imap/src/c-client/nntp.c b/imap/src/c-client/nntp.c index b8d89893..3875b351 100644 --- a/imap/src/c-client/nntp.c +++ b/imap/src/c-client/nntp.c @@ -2058,6 +2058,7 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); mm_log (tmp,NIL); + delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -2066,6 +2067,7 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) if (lsterr) { sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); mm_log (tmp,WARN); + delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } stream->saslcancel = NIL; @@ -2096,6 +2098,7 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) sprintf (tmp,"Can not authenticate to NNTP server: %.80s",lsterr); mm_log (tmp,ERROR); } + delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } else if (mb->secflag) /* no SASL, can't do /secure */ @@ -2124,6 +2127,8 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) stream->sensitive = T; /* hide this command */ if (nntp_send_work (stream,"AUTHINFO PASS",pwd2) == NNTPAUTHED) ret = LONGT; /* password OK */ + else + delete_password(mb, mb ? mb->user : NULL); stream->sensitive = NIL; /* unhide */ if (ret) break; /* OK if successful */ default: /* authentication failed */ diff --git a/imap/src/c-client/pop3.c b/imap/src/c-client/pop3.c index 89c3d9cb..ea8a64f5 100644 --- a/imap/src/c-client/pop3.c +++ b/imap/src/c-client/pop3.c @@ -628,12 +628,14 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) at->name,t); mm_log (pwd,NIL); fs_give ((void **) &t); + delete_password(mb, usr); } trial = 0; /* initial trial count */ do { if (t) { sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t); mm_log (pwd,WARN); + delete_password(mb, usr); fs_give ((void **) &t); } if(at->flags & AU_SINGLE){ @@ -664,6 +666,7 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) sprintf (pwd,"Can not authenticate to POP3 server: %.80s",t); mm_log (pwd,ERROR); } + delete_password(mb, usr); fs_give ((void **) &t); } if(mb && *mb->auth){ @@ -696,6 +699,7 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) LOCAL->sensitive=NIL; /* unhide */ } if (!ret) { /* failure */ + delete_password(mb, usr); mm_log (LOCAL->reply,WARN); if (trial == pop3_maxlogintrials) mm_log ("Too many login failures",ERROR); diff --git a/imap/src/c-client/smtp.c b/imap/src/c-client/smtp.c index bee34565..7c1f9936 100644 --- a/imap/src/c-client/smtp.c +++ b/imap/src/c-client/smtp.c @@ -301,6 +301,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); mm_log (tmp,NIL); + delete_password(mb, usr); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -310,6 +311,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); mm_log (tmp,WARN); fs_give ((void **) &lsterr); + delete_password(mb, usr); } if(at->flags & AU_SINGLE){ sprintf(tmp, "AUTH %s", at->name); @@ -343,6 +345,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) sprintf (tmp,"Can not authenticate to SMTP server: %.80s",lsterr); mm_log (tmp,ERROR); } + delete_password(mb, usr); fs_give ((void **) &lsterr); } if(mb && *mb->auth){ diff --git a/pith/imap.c b/pith/imap.c index f91937b1..7c74efaf 100644 --- a/pith/imap.c +++ b/pith/imap.c @@ -1149,6 +1149,64 @@ imap_flush_passwd_cache(int dumpcache) } } +void +imap_delete_passwd(MMLOGIN_S **m_list, char *user, STRLIST_S *hostlist, int altflag) +{ + if(m_list == NULL || *m_list == NULL) return; + imap_delete_passwd_auth(m_list, user, hostlist, altflag, + strchr((*m_list)->user, PWDAUTHSEP) != NULL ? OA2NAME : NULL); +} + +void +imap_delete_passwd_auth(MMLOGIN_S **m_list, char *user, + STRLIST_S *hostlist, int altflag, char *authtype) +{ + MMLOGIN_S *l, *p; + int len, offset; + + if(m_list == NULL || *m_list == NULL) return; + + dprint((9, "imap_delete_password: user=%s, host=%s, authtype=%s.", + user ? user : "no user!?", + hostlist && hostlist->name ? hostlist->name : "unknown host", + authtype ? authtype : "password authentication")); + + len = authtype ? strlen(authtype) : 0; + offset = authtype ? 1 : 0; + for(p = *m_list; p; p = p->next){ + if(imap_same_host_auth(p->hosts, hostlist, authtype) + && *user + && (len == 0 || (!struncmp(p->user, authtype, len) + && p->user[len] == PWDAUTHSEP)) + && !strcmp(user, p->user + len + offset) + && p->altflag == altflag) + break; + } + + dprint((9, "imap_delete_password: %s", + p ? "found a match!" : "did not find a match!")); + + if(!p) return; + + /* relink *mlist */ + if(p == *m_list) + *m_list = (*m_list)->next; + else{ + for(l = *m_list; l && l->next != p; l = l->next); + l->next = p->next; + } + /* so now p is out of the list. Free it */ + p->next = NULL; + if(p->user) fs_give((void **) &p->user); + + if(!(p->passwd >= (char *) private_store + && p->passwd <= (char *) private_store + sizeof(private_store))) + fs_give((void **) &p->passwd); + + free_strlist(&p->hosts); + fs_give((void **) &p); + dprint((9, "imap_delete_password: done with deletion.")); +} /* * Mimics fs_get except it only works for char * (no alignment hacks), it diff --git a/pith/imap.h b/pith/imap.h index b6575565..8c78a9c6 100644 --- a/pith/imap.h +++ b/pith/imap.h @@ -131,6 +131,8 @@ int imap_get_passwd_auth (MMLOGIN_S *, char **, char *, STRLIST_S *, int, char * void imap_set_passwd(MMLOGIN_S **, char *, char *, STRLIST_S *, int, int, int); void imap_set_passwd_auth(MMLOGIN_S **, char *, char *, STRLIST_S *, int, int, int, char *); void imap_flush_passwd_cache(int); +void imap_delete_passwd_auth (MMLOGIN_S **, char *, STRLIST_S *, int, char *); +void imap_delete_passwd (MMLOGIN_S **, char *, STRLIST_S *, int); /* currently mandatory to implement stubs */ diff --git a/pith/pine.hlp b/pith/pine.hlp index 2b865435..0e3f27cc 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any reasonable place to be called from. Dummy change to get revision in pine.hlp ============= h_revision ================= -Alpine Commit 587 2021-09-07 08:43:39 +Alpine Commit 588 2021-09-09 21:01:05 ============= h_news ================= <HTML> <HEAD> @@ -237,6 +237,9 @@ New features include: <LI> Add option -xoauth2-flow to the command line, so that users can specify the parameters to set up an xoauth2 connection through the command line. + +<LI> Alpine deletes, from its internal memory and external cache, passwords + that do not work, even if they were saved by the user. </UL> <P> |