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

📄 srvrsmtp.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
# if SASL
		if (authenticating == SASL_PROC_AUTH)
		{
#  if 0
			if (*inp == '\0')
			{
				authenticating = SASL_NOT_AUTH;
				message("501 5.5.2 missing input");
				continue;
			}
#  endif /* 0 */
			if (*inp == '*' && *(inp + 1) == '\0')
			{
				authenticating = SASL_NOT_AUTH;

				/* rfc 2254 4. */
				message("501 5.0.0 AUTH aborted");
				continue;
			}

			/* could this be shorter? XXX */
			out = xalloc(strlen(inp));
			result = sasl_decode64(inp, strlen(inp), out, &outlen);
			if (result != SASL_OK)
			{
				authenticating = SASL_NOT_AUTH;

				/* rfc 2254 4. */
				message("501 5.5.4 cannot decode AUTH parameter %s",
					inp);
				continue;
			}

			result = sasl_server_step(conn,	out, outlen,
						  &out, &outlen, &errstr);

			/* get an OK if we're done */
			if (result == SASL_OK)
			{
  authenticated:
				message("235 2.0.0 OK Authenticated");
				authenticating = SASL_IS_AUTH;
				define(macid("{auth_type}", NULL),
				       newstr(auth_type), &BlankEnvelope);

				result = sasl_getprop(conn, SASL_USERNAME,
						      (void **)&user);
				if (result != SASL_OK)
				{
					user = "";
					define(macid("{auth_authen}", NULL),
					       NULL, &BlankEnvelope);
				}
				else
				{
					define(macid("{auth_authen}", NULL),
					       newstr(user), &BlankEnvelope);
				}

#  if 0
				/* get realm? */
				sasl_getprop(conn, SASL_REALM, (void **) &data);
#  endif /* 0 */


#  if SFIO
				/* get security strength (features) */
				result = sasl_getprop(conn, SASL_SSF,
						      (void **) &ssf);
				if (result != SASL_OK)
				{
					define(macid("{auth_ssf}", NULL),
					       "0", &BlankEnvelope);
					ssf = NULL;
				}
				else
				{
					char pbuf[8];

					snprintf(pbuf, sizeof pbuf, "%u", *ssf);
					define(macid("{auth_ssf}", NULL),
					       newstr(pbuf), &BlankEnvelope);
					if (tTd(95, 8))
						dprintf("SASL auth_ssf: %u\n",
							*ssf);
				}
				/*
				**  only switch to encrypted connection
				**  if a security layer has been negotiated
				*/
				if (ssf != NULL && *ssf > 0)
				{
					/*
					**  convert sfio stuff to use SASL
					**  check return values
					**  if the call fails,
					**  fall back to unencrypted version
					**  unless some cf option requires
					**  encryption then the connection must
					**  be aborted
					*/
					if (sfdcsasl(InChannel, OutChannel,
					    conn) == 0)
					{
						/* restart dialogue */
						gothello = FALSE;
						OneXact = TRUE;
						n_helo = 0;
					}
					else
						syserr("503 5.3.3 SASL TLS failed");
					if (LogLevel > 9)
						sm_syslog(LOG_INFO,
							  NOQID,
							  "SASL: connection from %.64s: mech=%.16s, id=%.64s, bits=%d",
							  CurSmtpClient,
							  auth_type, user,
							  *ssf);
				}
#  else /* SFIO */
				if (LogLevel > 9)
					sm_syslog(LOG_INFO, NOQID,
						  "SASL: connection from %.64s: mech=%.16s, id=%.64s",
						  CurSmtpClient, auth_type,
						  user);
#  endif /* SFIO */
			}
			else if (result == SASL_CONTINUE)
			{
				len = ENC64LEN(outlen);
				out2 = xalloc(len);
				result = sasl_encode64(out, outlen, out2, len,
						       (u_int *)&out2len);
				if (result != SASL_OK)
				{
					/* correct code? XXX */
					/* 454 Temp. authentication failure */
					message("454 4.5.4 Internal error: unable to encode64");
					if (LogLevel > 5)
						sm_syslog(LOG_WARNING, e->e_id,
							  "SASL encode64 error [%d for \"%s\"]",
							  result, out);
					/* start over? */
					authenticating = SASL_NOT_AUTH;
				}
				else
				{
					message("334 %s", out2);
					if (tTd(95, 2))
						dprintf("SASL continue: msg='%s' len=%d\n",
							out2, out2len);
				}
			}
			else
			{
				/* not SASL_OK or SASL_CONT */
				message("500 5.7.0 authentication failed");
				if (LogLevel > 9)
					sm_syslog(LOG_WARNING, e->e_id,
						  "AUTH failure (%s): %s (%d)",
						  auth_type,
						  sasl_errstring(result, NULL,
								 NULL),
						  result);
				authenticating = SASL_NOT_AUTH;
			}
		}
		else
		{
			/* don't want to do any of this if authenticating */
# endif /* SASL */

		/* echo command to transcript */
		if (e->e_xfp != NULL)
			fprintf(e->e_xfp, "<<< %s\n", inp);

		if (LogLevel >= 15)
			sm_syslog(LOG_INFO, e->e_id,
				  "<-- %s",
				  inp);

		if (e->e_id == NULL)
			sm_setproctitle(TRUE, e, "%s: %.80s",
					CurSmtpClient, inp);
		else
			sm_setproctitle(TRUE, e, "%s %s: %.80s",
					qid_printname(e),
					CurSmtpClient, inp);

		/* break off command */
		for (p = inp; isascii(*p) && isspace(*p); p++)
			continue;
		cmd = cmdbuf;
		while (*p != '\0' &&
		       !(isascii(*p) && isspace(*p)) &&
		       cmd < &cmdbuf[sizeof cmdbuf - 2])
			*cmd++ = *p++;
		*cmd = '\0';

		/* throw away leading whitespace */
		while (isascii(*p) && isspace(*p))
			p++;

		/* decode command */
		for (c = CmdTab; c->cmd_name != NULL; c++)
		{
			if (strcasecmp(c->cmd_name, cmdbuf) == 0)
				break;
		}

		/* reset errors */
		errno = 0;

		/*
		**  Process command.
		**
		**	If we are running as a null server, return 550
		**	to everything.
		*/

		if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
		{
			switch (c->cmd_code)
			{
			  case CMDQUIT:
			  case CMDHELO:
			  case CMDEHLO:
			  case CMDNOOP:
			  case CMDRSET:
				/* process normally */
				break;

			  case CMDETRN:
				if (bitnset(D_ETRNONLY, d_flags) &&
				    nullserver == NULL)
					break;
				continue;

			  default:
				if (++badcommands > MAXBADCOMMANDS)
				{
					delay *= 2;
					if (delay >= MAXTIMEOUT)
						delay = MAXTIMEOUT;
					(void) sleep(delay);
				}
				if (nullserver != NULL)
				{
					if (ISSMTPREPLY(nullserver))
						usrerr(nullserver);
					else
						usrerr("550 5.0.0 %s", nullserver);
				}
				else
					usrerr("452 4.4.5 Insufficient disk space; try again later");
				continue;
			}
		}

		/* non-null server */
		switch (c->cmd_code)
		{
		  case CMDMAIL:
		  case CMDEXPN:
		  case CMDVRFY:
		  case CMDETRN:
			lognullconnection = FALSE;
		}

		switch (c->cmd_code)
		{
# if SASL
		  case CMDAUTH: /* sasl */
			if (!sasl_ok)
			{
				message("503 5.3.3 AUTH not available");
				break;
			}
			if (authenticating == SASL_IS_AUTH)
			{
				message("503 5.5.0 Already Authenticated");
				break;
			}
			if (gotmail)
			{
				message("503 5.5.0 AUTH not permitted during a mail transaction");
				break;
			}
			if (tempfail)
			{
				if (LogLevel > 9)
					sm_syslog(LOG_INFO, e->e_id,
						  "SMTP AUTH command (%.100s) from %.100s tempfailed (due to previous checks)",
						  p, CurSmtpClient);
				usrerr("454 4.7.1 Please try again later");
				break;
			}

			ismore = FALSE;

			/* crude way to avoid crack attempts */
			(void) checksmtpattack(&n_auth, n_mechs + 1, TRUE,
					       "AUTH", e);

			/* make sure it's a valid string */
			for (q = p; *q != '\0' && isascii(*q); q++)
			{
				if (isspace(*q))
				{
					*q = '\0';
					while (*++q != '\0' &&
					       isascii(*q) && isspace(*q))
						continue;
					*(q - 1) = '\0';
					ismore = (*q != '\0');
					break;
				}
			}

			/* check whether mechanism is available */
			if (iteminlist(p, mechlist, " ") == NULL)
			{
				message("503 5.3.3 AUTH mechanism %s not available",
					p);
				break;
			}

			if (ismore)
			{
				/* could this be shorter? XXX */
				in = xalloc(strlen(q));
				result = sasl_decode64(q, strlen(q), in,
						       (u_int *)&inlen);
				if (result != SASL_OK)
				{
					message("501 5.5.4 cannot BASE64 decode '%s'",
						q);
					if (LogLevel > 5)
						sm_syslog(LOG_WARNING, e->e_id,
							  "SASL decode64 error [%d for \"%s\"]",
							  result, q);
					/* start over? */
					authenticating = SASL_NOT_AUTH;
					in = NULL;
					inlen = 0;
					break;
				}
#  if 0
				if (tTd(95, 99))
				{
					int i;

					dprintf("AUTH: more \"");
					for (i = 0; i < inlen; i++)
					{
						if (isascii(in[i]) &&
						    isprint(in[i]))
							dprintf("%c", in[i]);
						else
							dprintf("_");
					}
					dprintf("\"\n");
				}
#  endif /* 0 */
			}
			else
			{
				in = NULL;
				inlen = 0;
			}

			/* see if that auth type exists */
			result = sasl_server_start(conn, p, in, inlen,
						   &out, &outlen, &errstr);

			if (result != SASL_OK && result != SASL_CONTINUE)
			{
				message("500 5.7.0 authentication failed");
				if (LogLevel > 9)
					sm_syslog(LOG_ERR, e->e_id,
						  "AUTH failure (%s): %s (%d)",
						  p,
						  sasl_errstring(result, NULL,
								 NULL),
						  result);
				break;
			}
			auth_type = newstr(p);

			if (result == SASL_OK)
			{
				/* ugly, but same code */
				goto authenticated;
				/* authenticated by the initial response */
			}

			/* len is at least 2 */
			len = ENC64LEN(outlen);
			out2 = xalloc(len);
			result = sasl_encode64(out, outlen, out2, len,
					       (u_int *)&out2len);

			if (result != SASL_OK)
			{
				message("454 4.5.4 Temporary authentication failure");
				if (LogLevel > 5)
					sm_syslog(LOG_WARNING, e->e_id,
						  "SASL encode64 error [%d for \"%s\"]",
						  result, out);

				/* start over? */
				authenticating = SASL_NOT_AUTH;
			}
			else
			{
				message("334 %s", out2);
				authenticating = SASL_PROC_AUTH;
			}

			break;
# endif /* SASL */

# if STARTTLS
		  case CMDSTLS: /* starttls */
			if (*p != '\0')
			{
				message("501 5.5.2 Syntax error (no parameters allowed)");
				break;
			}
			if (!usetls)
			{
				message("503 5.5.0 TLS not available");
				break;
			}
			if (!tls_ok)
			{
				message("454 4.3.3 TLS not available after start");
				break;
			}
			if (gotmail)
			{
				message("503 5.5.0 TLS not permitted during a mail transaction");
				break;
			}
			if (tempfail)
			{
				if (LogLevel > 9)
					sm_syslog(LOG_INFO, e->e_id,
						  "SMTP STARTTLS command (%.100s) from %.100s tempfailed (due to previous checks)",
						  p, CurSmtpClient);
				usrerr("454 4.7.1 Please try again later");
				break;
			}
# if TLS_NO_RSA
			/*
			**  XXX do we need a temp key ?
			*/
# else /* TLS_NO_RSA */
			if (SSL_CTX_need_tmp_RSA(srv_ctx) &&
			   !SSL_CTX_set_tmp_rsa(srv_ctx,
				(rsa = RSA_generate_key(RSA_KEYLENGTH, RSA_F4,
							NULL, NULL)))
			  )
			{
				message("454 4.3.3 TLS not available: error generating RSA temp key");
				if (rsa != NULL)
					RSA_free(rsa);
				break;
			}
# endif /* TLS_NO_RSA */
			if (srv_ssl != NULL)
				SSL_clear(srv_ssl);
			else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
			{
				message("454 4.3.3 TLS not available: error generating SSL handle");
				break;
			}
			rfd = fileno(InChannel);
			wfd = fileno(OutChannel);
			if (rfd < 0 || wfd < 0 ||
			    SSL_set_rfd(srv_ssl, rfd) <= 0 ||
			    SSL_set_wfd(srv_ssl, wfd) <= 0)
			{
				message("454 4.3.3 TLS not available: error set fd");
				SSL_free(srv_ssl);
				srv_ssl = NULL;
				break;
			}
			message("220 2.0.0 Ready to start TLS");
			SSL_set_accept_state(srv_ssl);

#  define SSL_ACC(s)	SSL_accept(s)
			if ((r = SSL_ACC(srv_ssl)) <= 0)
			{
				int i;

				/* what to do in this case? */
				i = SSL_get_error(srv_ssl, r);
				if (LogLevel > 5)
				{
					sm_syslog(LOG_WARNING, e->e_id,
						  "TLS: error: accept failed=%d (%d)",
						  r, i);
					if (LogLevel > 9)
						tlslogerr();
				}
				tls_ok = FALSE;
				SSL_free(srv_ssl);
				srv_ssl = NULL;

				/*
				**  according to the next draft of
				**  RFC 2487 the connection should be dropped
				*/

				/* arrange to ignore any current send list */
				e->e_sendqueue = NULL;
				goto doquit;
			}

			/* ignore return code for now, it's in {verify} */
			(void) tls_get_info(srv_ssl, &BlankEnvelope, TRUE,
					    CurSmtpClient);

			/*
			**  call Stls_client to find out whether
			**  to accept the connection from the client
			*/

			saveQuickAbort = QuickAbort;
			saveSuprErrs = SuprErrs;
			SuprErrs = TRUE;
			QuickAbort = FALSE;
			if (rscheck("tls_client",

⌨️ 快捷键说明

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