--- lmtp2nntp.c 2001/07/25 15:02:57 1.5
+++ lmtp2nntp.c 2001/07/26 15:18:57 1.6
@@ -37,6 +37,7 @@
#define ERR_DELIVERY -2
#define MESSAGE_MAXLEN 8*1024*1024
+#define STDSTRLEN 128
extern void lmtp_debug_dumplmtp(lmtp_t *lmtp);
@@ -52,15 +53,16 @@
static lmtp_rc_t lmtp_cb_quit (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
typedef struct {
- int option_verbose;
- int option_tracing;
- int option_mode;
- char *azNewsgroups;
- size_t asNewsgroups;
- char *rfc822message;
- int saw_lhlo;
- char *azRcpt;
- size_t asRcpt;
+ int option_verbose;
+ int option_tracing;
+ int option_mode;
+ char *azNewsgroups;
+ size_t asNewsgroups;
+ char *rfc822message;
+ int lhlo_seen;
+ char *lhlo_domain;
+ char *azRcpt;
+ size_t asRcpt;
} lmtp2nntp_t;
enum {
@@ -128,7 +130,8 @@
ctx->azNewsgroups = NULL;
ctx->asNewsgroups = 0;
ctx->rfc822message = NULL;
- ctx->saw_lhlo = FALSE;
+ ctx->lhlo_seen = FALSE;
+ ctx->lhlo_domain = "";
ctx->azRcpt = NULL;
ctx->asRcpt = 0;
@@ -217,25 +220,109 @@
* and the receiver-SMTP are in the initial state, that is, there is no
* transaction in progress and all state tables and buffers are cleared.
*
+ * The first command in a session must be the HELO command. The HELO
+ * command may be used later in a session as well. If the HELO command
+ * argument is not acceptable a 501 failure reply must be returned and
+ * the receiver-SMTP must stay in the same state.
+ *
+ * If the transaction beginning command argument is not acceptable a 501
+ * failure reply must be returned and the receiver-SMTP must stay in the
+ * same state. If the commands in a transaction are out of order a 503
+ * failure reply must be returned and the receiver-SMTP must stay in the
+ * same state.
+ *
+ * HELO <SP> <domain> <CRLF>
*/
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
lmtp_rc_t rc = LMTP_OK;
lmtp_res_t res;
- lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+ char errorstring[STDSTRLEN];
+ char *cp;
+ int FIXME;
+
+ cp = NULL;
+ if (ctx->lhlo_seen == TRUE) {
+ res.statuscode = "503";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "Duplicate LHLO.";
+ } else {
+ if (!str_parse(req->msg,
+ "^.+ ("
- //FIXME use rset() not lmtp_cb_rset()
- ctx->saw_lhlo = TRUE;
+ /*
+ ##
+ ## The mega Perl regular expression below is generated
+ ## with the following Perl program. This is only possible
+ ## because the given grammar is Chomsky-3 (right or left
+ ## linear grammar, but noth both).
+ ##
+
+ # BNF grammar for <domain> according to RFC 821:
+ # <snum> ::= one, two, or three digits representing a decimal integer value in the range 0 through 255
+ # <a> ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
+ # <d> ::= any one of the ten digits 0 through 9
+ # <let-dig-hyp> ::= <a> | <d> | "-"
+ # <let-dig> ::= <a> | <d>
+ # <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+ # <dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>
+ # <number> ::= <d> | <d> <number>
+ # <name> ::= <a> <ldh-str> <let-dig>
+ # <element> ::= <name> | "#" <number> | "[" <dotnum> "]"
+ # <domain> ::= <element> | <element> "." <domain>
+
+ # corresponding Perl regular expression ($domain)
+ $snum = "(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])";
+ $d = "[0-9]";
+ $a = "[A-Za-z]";
+ $let_dig_hyp = "(?:$a|$d|-)";
+ $let_dig = "(?:$a|$d)";
+ $ldh_str = "${let_dig_hyp}+";
+ $dotnum = "$snum\\.$snum\\.$snum\\.$snum";
+ $number = "$d+";
+ $name = "$a$ldh_str$let_dig";
+ $element = "(?:$name|#$number|\\[$dotnum\\])";
+ $domain = "(?:$element\.)*$element";
+
+ # translate into C string block suitable for passing to the Perl
+ # Compatible Regular Expressions (PCRE) based string library Str.
+ my $cregex = $domain;
+ $cregex =~ s|\\|\\\\|sg;
+ $cregex =~ s|(.{70})|"$1"\n|sg;
+ $cregex =~ s|\n([^\n]+)$|\n"$1"|s;
+ print "$cregex\n";
+ */
+
+ "(?:(?:[A-Za-z](?:[A-Za-z]|[0-9]|-)+(?:[A-Za-z]|[0-9])|#[0-9]+|\\[(?:[0"
+ "-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0"
+ "-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0"
+ "-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5"
+ "])\\]).)*(?:[A-Za-z](?:[A-Za-z]|[0-9]|-)+(?:[A-Za-z]|[0-9])|#[0-9]+|\\"
+ "[(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]"
+ "{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{"
+ "2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|"
+ "25[0-5])\\])"
- res.statuscode = "250";
- res.dsncode = NULL; /* DSN not used for greeting */
- res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\nPIPELINING\n8BITMIME";
- res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\n8BITMIME";
- /*
- * RFC2034 = EHANCEDSTATUSCODES
- * RFC1894 = DSN
- * RFC1854 = PIPELINING
- * RFC1652 = 8BITMIME
- */
+ ")$", &cp, &ctx->lhlo_domain)) {
+ res.statuscode = "501";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "Please identify yourself. See <domain> BNF in RFC821.";
+ } else {
+ ctx->lhlo_seen = TRUE;
+ printf("DEBUG: cp=***%s***, v1=***%s***\n", cp, ctx->lhlo_domain);
+ str_format(errorstring, sizeof(errorstring), "Hello ***%s***", ctx->lhlo_domain);
+ res.statuscode = "250";
+ res.dsncode = NULL; /* DSN not used for greeting */
+ res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\nPIPELINING\n8BITMIME";
+ /*
+ * RFC2034 = EHANCEDSTATUSCODES
+ * RFC1894 = DSN
+ * RFC1854 = PIPELINING
+ * RFC1652 = 8BITMIME
+ */
+ }
+ }
lmtp_response(lmtp, &res);
+ if (cp) free(cp);
return rc;
}
@@ -245,7 +332,7 @@
lmtp_rc_t rc = LMTP_OK;
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
- if (ctx->saw_lhlo == TRUE) {
+ if (ctx->lhlo_seen == TRUE) {
res.statuscode = "250";
res.dsncode = "2.1.0";
res.statusmsg = "Sender ok FIXME";
@@ -281,7 +368,7 @@
lmtp_rc_t rc = LMTP_OK;
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
char *buf;
- char errorstring[128];
+ char errorstring[STDSTRLEN];
char *rcpt;
res.statuscode = "354";
@@ -349,7 +436,7 @@
lmtp_rc_t rc = LMTP_EOF;
res.statuscode = "221";
res.dsncode = "2.0.0";
- res.statusmsg = "Closing connection.";
+ res.statusmsg = "LMTP Service closing transmission channel.";
lmtp_response(lmtp, &res);
return rc;
}
|