⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pop3.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
    status.uidnext = tstream->uid_last + 1;    status.uidvalidity = tstream->uid_validity;				/* pass status to main program */    mm_status (tstream,mbx,&status);    if (stream != tstream) mail_close (tstream);    ret = LONGT;  }  return ret;			/* success */}/* POP3 mail open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *pop3_open (MAILSTREAM *stream){  unsigned long i,j;  char *s,*t,tmp[MAILTMPLEN],usr[MAILTMPLEN];  NETMBX mb;  MESSAGECACHE *elt;				/* return prototype for OP_PROTOTYPE call */  if (!stream) return &pop3proto;  mail_valid_net_parse (stream->mailbox,&mb);  usr[0] = '\0';		/* initially no user name */  if (stream->local) fatal ("pop3 recycle stream");				/* /anonymous not supported */  if (mb.anoflag || stream->anonymous) {    mm_log ("Anonymous POP3 login not available",ERROR);    return NIL;  }				/* /readonly not supported either */  if (mb.readonlyflag || stream->rdonly) {    mm_log ("Read-only POP3 access not available",ERROR);    return NIL;  }				/* copy other switches */  if (mb.dbgflag) stream->debug = T;  if (mb.secflag) stream->secure = T;  mb.trysslflag = stream->tryssl = (mb.trysslflag || stream->tryssl) ? T : NIL;  stream->local =		/* instantiate localdata */    (void *) memset (fs_get (sizeof (POP3LOCAL)),0,sizeof (POP3LOCAL));  stream->sequence++;		/* bump sequence number */  stream->perm_deleted = T;	/* deleted is only valid flag */  if ((LOCAL->netstream =	/* try to open connection */       net_open (&mb,NIL,pop3_port ? pop3_port : POP3TCPPORT,		 (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL),		 "*pop3s",pop3_sslport ? pop3_sslport : POP3SSLPORT)) &&      pop3_reply (stream)) {    mm_log (LOCAL->reply,NIL);	/* give greeting */    if (!pop3_auth (stream,&mb,tmp,usr)) pop3_close (stream,NIL);    else if (pop3_send (stream,"STAT",NIL)) {      int silent = stream->silent;      stream->silent = T;      sprintf (tmp,"{%.200s:%lu/pop3",	       (long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ?	       net_host (LOCAL->netstream) : mb.host,	       net_port (LOCAL->netstream));      if (mb.tlsflag) strcat (tmp,"/tls");      if (mb.tlssslv23) strcat (tmp,"/tls-sslv23");      if (mb.notlsflag) strcat (tmp,"/notls");      if (mb.sslflag) strcat (tmp,"/ssl");      if (mb.novalidate) strcat (tmp,"/novalidate-cert");      if (LOCAL->loser = mb.loser) strcat (tmp,"/loser");      if (stream->secure) strcat (tmp,"/secure");      sprintf (tmp + strlen (tmp),"/user=\"%s\"}%s",usr,mb.mailbox);      stream->inbox = T;	/* always INBOX */      fs_give ((void **) &stream->mailbox);      stream->mailbox = cpystr (tmp);				/* notify upper level */      mail_exists (stream,stream->uid_last = strtoul (LOCAL->reply,NIL,10));      mail_recent (stream,stream->nmsgs);				/* instantiate elt */      for (i = 0; i < stream->nmsgs;) {	elt = mail_elt (stream,++i);	elt->valid = elt->recent = T;	elt->private.uid = i;      }				/* trust LIST output if new server */      if (!LOCAL->loser && LOCAL->cap.capa && pop3_send (stream,"LIST",NIL)) {	while ((s = net_getline (LOCAL->netstream)) && (*s != '.')) {	  if ((i = strtoul (s,&t,10)) && (i <= stream->nmsgs) &&	      (j = strtoul (t,NIL,10))) mail_elt (stream,i)->rfc822_size = j;	  fs_give ((void **) &s);	}				/* flush final dot */	if (s) fs_give ((void **) &s);	else {			/* lost connection */	  mm_log ("POP3 connection broken while itemizing messages",ERROR);	  pop3_close (stream,NIL);	  return NIL;	}      }      stream->silent = silent;	/* notify main program */      mail_exists (stream,stream->nmsgs);				/* notify if empty */      if (!(stream->nmsgs || stream->silent)) mm_log ("Mailbox is empty",WARN);    }    else {			/* error in STAT */      mm_log (LOCAL->reply,ERROR);      pop3_close (stream,NIL);	/* too bad */    }  }  else {			/* connection failed */    if (LOCAL->reply) mm_log (LOCAL->reply,ERROR);    pop3_close (stream,NIL);	/* failed, clean up */  }  return LOCAL ? stream : NIL;	/* if stream is alive, return to caller */}/* POP3 capabilities * Accepts: stream *	    authenticator flags * Returns: T on success, NIL on failure */long pop3_capa (MAILSTREAM *stream,long flags){  unsigned long i;  char *s,*t,*r,*args;  if (LOCAL->cap.implementation)/* zap all old capabilities */    fs_give ((void **) &LOCAL->cap.implementation);  memset (&LOCAL->cap,0,sizeof (LOCAL->cap));				/* get server capabilities */  if (pop3_send (stream,"CAPA",NIL)) LOCAL->cap.capa = T;  else {    LOCAL->cap.user = T;	/* guess worst-case old server */    return NIL;			/* no CAPA on this server */  }  while ((t = net_getline (LOCAL->netstream)) && (t[1] || (*t != '.'))) {    if (stream->debug) mm_dlog (t);				/* get optional capability arguments */    if (args = strchr (t,' ')) *args++ = '\0';    if (!compare_cstring (t,"STLS")) LOCAL->cap.stls = T;    else if (!compare_cstring (t,"PIPELINING")) LOCAL->cap.pipelining = T;    else if (!compare_cstring (t,"RESP-CODES")) LOCAL->cap.respcodes = T;    else if (!compare_cstring (t,"TOP")) LOCAL->cap.top = T;    else if (!compare_cstring (t,"UIDL")) LOCAL->cap.uidl = T;    else if (!compare_cstring (t,"USER")) LOCAL->cap.user = T;    else if (!compare_cstring (t,"IMPLEMENTATION") && args)      LOCAL->cap.implementation = cpystr (args);    else if (!compare_cstring (t,"EXPIRE") && args) {      LOCAL->cap.expire = T;	/* note that it is present */      if (s = strchr(args,' ')){/* separate time from possible USER */	*s++ = '\0';				/* in case they add something after USER */	if ((strlen (s) > 4) && (s[4] == ' ')) s[4] = '\0';      }      LOCAL->cap.expire =	/* get expiration time */	(!compare_cstring (args,"NEVER")) ? 65535 :	  ((s && !compare_cstring (s,"USER")) ? -atoi (args) : atoi (args));    }    else if (!compare_cstring (t,"LOGIN-DELAY") && args) {      LOCAL->cap.logindelay = T;/* note that it is present */      if (s = strchr(args,' ')){/* separate time from possible USER */	*s++ = '\0';				/* in case they add something after USER */	if ((strlen (s) > 4) && (s[4] == ' ')) s[4] = '\0';      }				/* get delay time */      LOCAL->cap.delaysecs = (s && !compare_cstring (s,"USER")) ?	-atoi (args) : atoi (args);    }    else if (!compare_cstring (t,"SASL") && args)      for (args = strtok_r (args," ",&r); args; args = strtok_r (NIL," ",&r))	if ((i = mail_lookup_auth_name (args,flags)) &&	    (--i < MAXAUTHENTICATORS))	  LOCAL->cap.sasl |= (1 << i);    fs_give ((void **) &t);  }  if (t) {			/* flush end of text indicator */    if (stream->debug) mm_dlog (t);    fs_give ((void **) &t);  }  return LONGT;}/* POP3 authenticate * Accepts: stream to login *	    parsed network mailbox structure *	    scratch buffer of length MAILTMPLEN *	    place to return user name * Returns: T on success, NIL on failure */long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr){  unsigned long i,trial,auths = 0;  char *t;  AUTHENTICATOR *at;  long ret = NIL;  long flags = (stream->secure ? AU_SECURE : NIL) |    (mb->authuser[0] ? AU_AUTHUSER : NIL);  long capaok = pop3_capa (stream,flags);  NETDRIVER *ssld = (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL);  sslstart_t stls = (sslstart_t) mail_parameters (NIL,GET_SSLSTART,NIL);				/* server has TLS? */  if (stls && LOCAL->cap.stls && !mb->sslflag && !mb->notlsflag &&      pop3_send (stream,"STLS",NIL)) {    mb->tlsflag = T;		/* TLS OK, get into TLS at this end */    LOCAL->netstream->dtb = ssld;    if (!(LOCAL->netstream->stream =	  (*stls) (LOCAL->netstream->stream,mb->host,		   (mb->tlssslv23 ? NIL : NET_TLSCLIENT) |		   (mb->novalidate ? NET_NOVALIDATECERT : NIL)))) {				/* drat, drop this connection */      if (LOCAL->netstream) net_close (LOCAL->netstream);      LOCAL->netstream= NIL;      return NIL;		/* TLS negotiation failed */    }    pop3_capa (stream,flags);	/* get capabilities now that TLS in effect */  }  else if (mb->tlsflag) {	/* user specified /tls but can't do it */    mm_log ("Unable to negotiate TLS with this server",ERROR);    return NIL;  }  				/* get authenticators from capabilities */  if (capaok) auths = LOCAL->cap.sasl;				/* get list of authenticators */  else if (pop3_send (stream,"AUTH",NIL)) {    while ((t = net_getline (LOCAL->netstream)) && (t[1] || (*t != '.'))) {      if (stream->debug) mm_dlog (t);      if ((i = mail_lookup_auth_name (t,flags)) && (--i < MAXAUTHENTICATORS))	auths |= (1 << i);      fs_give ((void **) &t);    }    if (t) {			/* flush end of text indicator */      if (stream->debug) mm_dlog (t);      fs_give ((void **) &t);    }  }				/* disable LOGIN if PLAIN also advertised */  if ((i = mail_lookup_auth_name ("PLAIN",NIL)) && (--i < MAXAUTHENTICATORS) &&      (auths & (1 << i)) &&      (i = mail_lookup_auth_name ("LOGIN",NIL)) && (--i < MAXAUTHENTICATORS))    auths &= ~(1 << i);  if (auths) {			/* got any authenticators? */    if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) {				/* remote name for authentication */      strncpy (mb->host,(long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ?	       net_remotehost (LOCAL->netstream) : net_host (LOCAL->netstream),	       NETMAXHOST-1);      mb->host[NETMAXHOST-1] = '\0';    }    for (t = NIL, LOCAL->saslcancel = NIL; !ret && LOCAL->netstream && auths &&	 (at = mail_lookup_auth (find_rightmost_bit (&auths)+1)); ) {      if (t) {			/* previous authenticator failed? */	sprintf (pwd,"Retrying using %.80s authentication after %.80s",		 at->name,t);	mm_log (pwd,NIL);	fs_give ((void **) &t);      }      trial = 0;		/* initial trial count */      do {	if (t) {	  sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t);	  mm_log (pwd,WARN);	  fs_give ((void **) &t);	}	LOCAL->saslcancel = NIL;	if (pop3_send (stream,"AUTH",at->name)) {				/* hide client authentication responses */	  if (!(at->flags & AU_SECURE)) LOCAL->sensitive = T;	  if ((*at->client) (pop3_challenge,pop3_response,"pop",mb,stream,			     &trial,usr) && LOCAL->response) {	    if (*LOCAL->response == '+') ret = LONGT;				/* if main program requested cancellation */	    else if (!trial) mm_log ("POP3 Authentication cancelled",ERROR);	  }	  LOCAL->sensitive=NIL;	/* unhide */	}				/* remember response if error and no cancel */	if (!ret && trial) t = cpystr (LOCAL->reply);      } while (!ret && trial && (trial < pop3_maxlogintrials) &&	       LOCAL->netstream);    }    if (t) {			/* previous authenticator failed? */      if (!LOCAL->saslcancel) {	/* don't do this if a cancel */	sprintf (pwd,"Can not authenticate to POP3 server: %.80s",t);	mm_log (pwd,ERROR);      }      fs_give ((void **) &t);    }  }  else if (stream->secure)    mm_log ("Can't do secure authentication with this server",ERROR);  else if (mb->authuser[0])    mm_log ("Can't do /authuser with this server",ERROR);  else if (!LOCAL->cap.user) mm_log ("Can't login to this server",ERROR);  else {			/* traditional login */    trial = 0;			/* initial trial count */    do {      pwd[0] = 0;		/* prompt user for password */      mm_login (mb,usr,pwd,trial++);      if (pwd[0]) {		/* send login sequence if have password */	if (pop3_send (stream,"USER",usr)) {	  LOCAL->sensitive = T;	/* hide this command */	  if (pop3_send (stream,"PASS",pwd)) ret = LONGT;	  LOCAL->sensitive=NIL;	/* unhide */	}	if (!ret) {		/* failure */	  mm_log (LOCAL->reply,WARN);	  if (trial == pop3_maxlogintrials)	    mm_log ("Too many login failures",ERROR);	}      }				/* user refused to give password */      else mm_log ("Login aborted",ERROR);    } while (!ret && pwd[0] && (trial < pop3_maxlogintrials) &&	     LOCAL->netstream);  }  memset (pwd,0,MAILTMPLEN);	/* erase password */				/* get capabilities if logged in */  if (ret && capaok) pop3_capa (stream,flags);  return ret;}/* Get challenge to authenticator in binary * Accepts: stream *	    pointer to returned size * Returns: challenge or NIL if not challenge */void *pop3_challenge (void *s,unsigned long *len){  char tmp[MAILTMPLEN];  void *ret = NIL;  MAILSTREAM *stream = (MAILSTREAM *) s;  if (stream && LOCAL->response &&      (*LOCAL->response == '+') && (LOCAL->response[1] == ' ') &&      !(ret = rfc822_base64 ((unsigned char *) LOCAL->reply,			     strlen (LOCAL->reply),len))) {    sprintf (tmp,"POP3 SERVER BUG (invalid challenge): %.80s",LOCAL->reply);    mm_log (tmp,ERROR);  }  return ret;}/* Send authenticator response in BASE64 * Accepts: MAIL stream *	    string to send *	    length of string * Returns: T if successful, else NIL */long pop3_response (void *s,char *response,unsigned long size){  MAILSTREAM *stream = (MAILSTREAM *) s;  unsigned long i,j,ret;  char *t,*u;  if (response) {		/* make CRLFless BASE64 string */    if (size) {      for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;	   j < i; j++) if (t[j] > ' ') *u++ = t[j];      *u = '\0';		/* tie off string for mm_dlog() */      if (stream->debug) mail_dlog (t,LOCAL->sensitive);				/* append CRLF */      *u++ = '\015'; *u++ = '\012'; *u = '\0';      ret = net_sout (LOCAL->netstream,t,u - t);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -