void
sender(String *path)
{
String *s;
static char *lastsender;
if(rejectcheck())
return;
if (authenticate && !authenticated) {
rejectcount++;
reply("530 5.7.0 Authentication required\r\n");
return;
}
if(him == 0 || *him == 0){
rejectcount++;
reply("503 Start by saying HELO, please.\r\n", s_to_c(path));
return;
}
/* don't add the domain onto black holes or we will loop */
if(strchr(s_to_c(path), '!') == 0 && strcmp(s_to_c(path), "/dev/null") != 0){
s = s_new();
s_append(s, him);
s_append(s, "!");
s_append(s, s_to_c(path));
s_terminate(s);
s_free(path);
path = s;
}
if(shellchars(s_to_c(path))){
rejectcount++;
reply("501 5.1.3 Bad character in sender address %s.\r\n",
s_to_c(path));
return;
}
/*
* if the last sender address resulted in a rejection because the sending
* domain didn't exist and this sender has the same domain, reject
* immediately.
*/
if(lastsender){
if (strncmp(lastsender, s_to_c(path), strlen(lastsender)) == 0){
filterstate = REFUSED;
rejectcount++;
reply("554 5.1.8 Sender domain must exist: %s\r\n",
s_to_c(path));
return;
}
free(lastsender); /* different sender domain */
lastsender = 0;
}
/*
* see if this ip address, domain name, user name or account is blocked
*/
logged = 0;
filterstate = blocked(path);
/*
* permanently reject what we can before trying smtp ping, which
* often leads to merely temporary rejections.
*/
switch (filterstate){
case DENIED:
syslog(0, "smtpd", "Denied %s (%s/%s)",
s_to_c(path), him, nci->rsys);
rejectcount++;
logged++;
reply("554-5.7.1 We don't accept mail from %s.\r\n",
s_to_c(path));
reply("554 5.7.1 Contact [email protected]%s for more information.\r\n",
dom);
return;
case REFUSED:
syslog(0, "smtpd", "Refused %s (%s/%s)",
s_to_c(path), him, nci->rsys);
rejectcount++;
logged++;
reply("554 5.7.1 Sender domain must exist: %s\r\n",
s_to_c(path));
return;
}
listadd(&senders, path);
reply("250 2.0.0 sender is %s\r\n", s_to_c(path));
}
开发者ID:CoryXie,项目名称:nix-os,代码行数:86,代码来源:smtpd.c
示例8: startcmd
String*
startcmd(void)
{
int n;
char *filename;
char **av;
Link *l;
String *cmd;
/*
* ignore the filterstate if the all the receivers prefer it.
*/
filterstate = optoutall(filterstate);
switch (filterstate){
case BLOCKED:
case DELAY:
rejectcount++;
logmsg("Blocked");
filename = dumpfile(s_to_c(senders.last->p));
cmd = s_new();
s_append(cmd, "cat > ");
s_append(cmd, filename);
pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 0, 0);
break;
case DIALUP:
logmsg("Dialup");
rejectcount++;
reply("554 5.7.1 We don't accept mail from dial-up ports.\r\n");
/*
* we could exit here, because we're never going to accept mail
* from this ip address, but it's unclear that RFC821 allows
* that. Instead we set the hardreject flag and go stupid.
*/
hardreject = 1;
return 0;
case DENIED:
logmsg("Denied");
rejectcount++;
reply("554-5.7.1 We don't accept mail from %s.\r\n",
s_to_c(senders.last->p));
reply("554 5.7.1 Contact [email protected]%s for more information.\r\n",
dom);
return 0;
case REFUSED:
logmsg("Refused");
rejectcount++;
reply("554 5.7.1 Sender domain must exist: %s\r\n",
s_to_c(senders.last->p));
return 0;
default:
case NONE:
logmsg("Confused");
rejectcount++;
reply("554-5.7.0 We have had an internal mailer error "
"classifying your message.\r\n");
reply("554-5.7.0 Filterstate is %d\r\n", filterstate);
reply("554 5.7.0 Contact [email protected]%s for more information.\r\n",
dom);
return 0;
case ACCEPT:
/*
* now that all other filters have been passed,
* do grey-list processing.
*/
if(gflag)
vfysenderhostok();
/* fall through */
case TRUSTED:
/*
* set up mail command
*/
cmd = s_clone(mailer);
n = 3;
for(l = rcvers.first; l; l = l->next)
n++;
av = malloc(n * sizeof(char*));
if(av == nil){
reply("450 4.3.2 We're busy right now, try later\r\n");
s_free(cmd);
return 0;
}
n = 0;
av[n++] = s_to_c(cmd);
av[n++] = "-r";
for(l = rcvers.first; l; l = l->next)
av[n++] = s_to_c(l->p);
av[n] = 0;
/*
* start mail process
*/
pp = noshell_proc_start(av, instream(), outstream(),
outstream(), 0, 0);
free(av);
break;
}
if(pp == 0) {
reply("450 4.3.2 We're busy right now, try later\r\n");
//.........这里部分代码省略.........
void
hello(String *himp, int extended)
{
char **mynames;
char *ldot, *rdot;
him = s_to_c(himp);
syslog(0, "smtpd", "%s from %s as %s", extended? "ehlo": "helo",
nci->rsys, him);
if(rejectcheck())
return;
if (strchr(him, '.') && nci && !trusted && fflag &&
strcmp(nci->rsys, nci->lsys) != 0){
/*
* We don't care if he lies about who he is, but it is
* not okay to pretend to be us. Many viruses do this,
* just parroting back what we say in the greeting.
*/
if(strcmp(him, dom) == 0)
goto Liarliar;
for(mynames = sysnames_read(); mynames && *mynames; mynames++){
if(cistrcmp(*mynames, him) == 0){
Liarliar:
syslog(0, "smtpd",
"Hung up on %s; claimed to be %s",
nci->rsys, him);
if(Dflag)
sleep(delaysecs()*1000);
reply("554 5.7.0 Liar!\r\n");
exits("client pretended to be us");
return;
}
}
}
/*
* it is unacceptable to claim any string that doesn't look like
* a domain name (e.g., has at least one dot in it), but
* Microsoft mail client software gets this wrong, so let trusted
* (local) clients omit the dot.
*/
rdot = strrchr(him, '.');
if (rdot && rdot[1] == '\0') {
*rdot = '\0'; /* clobber trailing dot */
rdot = strrchr(him, '.'); /* try again */
}
if (!trusted && rdot == nil)
goto Liarliar;
/*
* Reject obviously bogus domains and those reserved by RFC 2606.
*/
if (rdot == nil)
rdot = him;
else
rdot++;
if (!trusted && (cistrcmp(rdot, "localdomain") == 0 ||
cistrcmp(rdot, "localhost") == 0 ||
cistrcmp(rdot, "example") == 0 ||
cistrcmp(rdot, "invalid") == 0 ||
cistrcmp(rdot, "test") == 0))
goto Liarliar; /* bad top-level domain */
/* check second-level RFC 2606 domains: example\.(com|net|org) */
if (rdot != him)
*--rdot = '\0';
ldot = strrchr(him, '.');
if (rdot != him)
*rdot = '.';
if (ldot == nil)
ldot = him;
else
ldot++;
if (cistrcmp(ldot, "example.com") == 0 ||
cistrcmp(ldot, "example.net") == 0 ||
cistrcmp(ldot, "example.org") == 0)
goto Liarliar;
/*
* similarly, if the claimed domain is not an address-literal,
* require at least one letter, which there will be in
* at least the last component (e.g., .com, .net) if it's real.
* this rejects non-address-literal IP addresses,
* among other bogosities.
*/
if (!trusted && him[0] != '[') {
char *p;
for (p = him; *p != '\0'; p++)
if (isascii(*p) && isalpha(*p))
break;
if (*p == '\0')
goto Liarliar;
}
if(strchr(him, '.') == 0 && nci != nil && strchr(nci->rsys, '.') != nil)
him = nci->rsys;
if(Dflag)
sleep(delaysecs()*1000);
reply("250%c%s you are %s\r\n", extended ? '-' : ' ', dom, him);
if (extended) {
//.........这里部分代码省略.........
开发者ID:CoryXie,项目名称:nix-os,代码行数:101,代码来源:smtpd.c
示例11: auth
void
auth(String *mech, String *resp)
{
char *user, *pass, *scratch = nil;
AuthInfo *ai = nil;
Chalstate *chs = nil;
String *s_resp1_64 = nil, *s_resp2_64 = nil, *s_resp1 = nil;
String *s_resp2 = nil;
if (rejectcheck())
goto bomb_out;
syslog(0, "smtpd", "auth(%s, %s) from %s", s_to_c(mech),
"(protected)", him);
if (authenticated) {
bad_sequence:
rejectcount++;
reply("503 5.5.2 Bad sequence of commands\r\n");
goto bomb_out;
}
if (cistrcmp(s_to_c(mech), "plain") == 0) {
if (!passwordinclear) {
rejectcount++;
reply("538 5.7.1 Encryption required for requested "
"authentication mechanism\r\n");
goto bomb_out;
}
s_resp1_64 = resp;
if (s_resp1_64 == nil) {
reply("334 \r\n");
s_resp1_64 = s_new();
if (getcrnl(s_resp1_64, &bin) <= 0)
goto bad_sequence;
}
s_resp1 = s_dec64(s_resp1_64);
if (s_resp1 == nil) {
rejectcount++;
reply("501 5.5.4 Cannot decode base64\r\n");
goto bomb_out;
}
memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
user = s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1;
pass = user + strlen(user) + 1;
ai = auth_userpasswd(user, pass);
authenticated = ai != nil;
memset(pass, 'X', strlen(pass));
goto windup;
}
else if (cistrcmp(s_to_c(mech), "login") == 0) {
if (!passwordinclear) {
rejectcount++;
reply("538 5.7.1 Encryption required for requested "
"authentication mechanism\r\n");
goto bomb_out;
}
if (resp == nil) {
reply("334 VXNlcm5hbWU6\r\n");
s_resp1_64 = s_new();
if (getcrnl(s_resp1_64, &bin) <= 0)
goto bad_sequence;
}
reply("334 UGFzc3dvcmQ6\r\n");
s_resp2_64 = s_new();
if (getcrnl(s_resp2_64, &bin) <= 0)
goto bad_sequence;
s_resp1 = s_dec64(s_resp1_64);
s_resp2 = s_dec64(s_resp2_64);
memset(s_to_c(s_resp2_64), 'X', s_len(s_resp2_64));
if (s_resp1 == nil || s_resp2 == nil) {
rejectcount++;
reply("501 5.5.4 Cannot decode base64\r\n");
goto bomb_out;
}
ai = auth_userpasswd(s_to_c(s_resp1), s_to_c(s_resp2));
authenticated = ai != nil;
memset(s_to_c(s_resp2), 'X', s_len(s_resp2));
windup:
if (authenticated) {
/* if you authenticated, we trust you despite your IP */
trusted = 1;
reply("235 2.0.0 Authentication successful\r\n");
} else {
rejectcount++;
reply("535 5.7.1 Authentication failed\r\n");
syslog(0, "smtpd", "authentication failed: %r");
}
goto bomb_out;
}
else if (cistrcmp(s_to_c(mech), "cram-md5") == 0) {
int chal64n;
char *resp, *t;
chs = auth_challenge("proto=cram role=server");
if (chs == nil) {
rejectcount++;
reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n");
goto bomb_out;
}
scratch = malloc(chs->nchal * 2 + 1);
//.........这里部分代码省略.........
开发者ID:CoryXie,项目名称:nix-os,代码行数:101,代码来源:smtpd.c
示例12: data
void
data(void)
{
int status, nbytes;
char *cp, *ep;
char errx[ERRMAX];
Link *l;
String *cmd, *err;
if(rejectcheck())
return;
if(senders.last == 0){
reply("503 2.5.2 Data without MAIL FROM:\r\n");
rejectcount++;
return;
}
if(rcvers.last == 0){
reply("503 2.5.2 Data without RCPT TO:\r\n");
rejectcount++;
return;
}
if(!trusted && sendermxcheck()){
rerrstr(errx, sizeof errx);
if(strncmp(errx, "rejected:", 9) == 0)
reply("554 5.7.1 %s\r\n", errx);
else
reply("450 4.7.0 %s\r\n", errx);
for(l=rcvers.first; l; l=l->next)
syslog(0, "smtpd", "[%s/%s] %s -> %s sendercheck: %s",
him, nci->rsys, s_to_c(senders.first->p),
s_to_c(l->p), errx);
rejectcount++;
return;
}
cmd = startcmd();
if(cmd == 0)
return;
reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
if(debug){
seek(2, 0, 2);
stamp();
fprint(2, "# sent 354; accepting DATA %s\n", thedate());
}
/*
* allow 145 more minutes to move the data
*/
alarm(145*60*1000);
status = pipemsg(&nbytes);
/*
* read any error messages
*/
err = s_new();
if (debug) {
stamp();
fprint(2, "waiting for upas/send to close stderr\n");
}
while(s_read_line(pp->std[2]->fp, err))
;
alarm(0);
atnotify(catchalarm, 0);
if (debug) {
stamp();
fprint(2, "waiting for upas/send to exit\n");
}
status |= proc_wait(pp);
if(debug){
seek(2, 0, 2);
stamp();
fprint(2, "# %d upas/send status %#ux at %s\n",
getpid(), status, thedate());
if(*s_to_c(err))
fprint(2, "# %d error %s\n", getpid(), s_to_c(err));
}
/*
* if process terminated abnormally, send back error message
*/
if(status){
int code;
char *ecode;
if(strstr(s_to_c(err), "mail refused")){
syslog(0, "smtpd", "++[%s/%s] %s %s refused: %s",
him, nci->rsys, s_to_c(senders.first->p),
s_to_c(cmd), firstline(s_to_c(err)));
code = 554;
ecode = "5.0.0";
} else {
syslog(0, "smtpd", "++[%s/%s] %s %s %s%s%sreturned %#q %s",
him, nci->rsys,
s_to_c(senders.first->p), s_to_c(cmd),
piperror? "error during pipemsg: ": "",
//.........这里部分代码省略.........
/*! \brief Message handling function for all messages sent to the app_server
\param code ID of the message sent
\param buffer Attachment buffer for the message.
*/
void
AppServer::_DispatchMessage(int32 code, BPrivate::LinkReceiver& msg)
{
switch (code) {
case AS_GET_DESKTOP:
{
Desktop* desktop = NULL;
port_id replyPort;
msg.Read<port_id>(&replyPort);
int32 userID;
msg.Read<int32>(&userID);
char* targetScreen = NULL;
msg.ReadString(&targetScreen);
if (targetScreen != NULL && strlen(targetScreen) == 0) {
free(targetScreen);
targetScreen = NULL;
}
int32 version;
if (msg.Read<int32>(&version) < B_OK
|| version != AS_PROTOCOL_VERSION) {
syslog(LOG_ERR, "Application for user %" B_PRId32 " with port "
"%" B_PRId32 " does not support the current server "
"protocol.\n", userID, replyPort);
} else {
desktop = _FindDesktop(userID, targetScreen);
if (desktop == NULL) {
// we need to create a new desktop object for this user
// TODO: test if the user exists on the system
// TODO: maybe have a separate AS_START_DESKTOP_SESSION for
// authorizing the user
desktop = _CreateDesktop(userID, targetScreen);
}
}
free(targetScreen);
BPrivate::LinkSender reply(replyPort);
if (desktop != NULL) {
reply.StartMessage(B_OK);
reply.Attach<port_id>(desktop->MessagePort());
} else
reply.StartMessage(B_ERROR);
reply.Flush();
break;
}
#if TEST_MODE
case B_QUIT_REQUESTED:
{
// We've been asked to quit, so (for now) broadcast to all
// desktops to quit. This situation will occur only when the server
// is compiled as a regular Be application.
fQuitting = true;
while (fDesktops.CountItems() > 0) {
Desktop *desktop = fDesktops.RemoveItemAt(0);
thread_id thread = desktop->Thread();
desktop->PostMessage(B_QUIT_REQUESTED);
// we just wait for the desktop to kill itself
status_t status;
wait_for_thread(thread, &status);
}
delete this;
// we are now clear to exit
exit(0);
break;
}
#endif
default:
STRACE(("Server::MainLoop received unexpected code %" B_PRId32 " "
"(offset %" B_PRId32 ")\n", code, code - SERVER_TRUE));
break;
}
}
请发表评论