static int parse_label(void) { int end; if ((end = str_findfirst(&linebuf, ' ')) <= 0) return 0; str_copyb(&label, linebuf.s, end); return end + 1; }
static const response* parse_addr_arg(void) { unsigned i; char term; int quoted; if (!str_truncate(&addr, 0)) return &resp_oom; if (!str_truncate(¶ms, 0)) return &resp_oom; addr.len = 0; if ((i = str_findfirst(&arg, LBRACE) + 1) != 0) term = RBRACE; else { term = SPACE; if ((i = str_findfirst(&arg, COLON) + 1) == 0) if ((i = str_findfirst(&arg, SPACE) + 1) == 0) return &resp_badaddr; while (i < arg.len && arg.s[i] == SPACE) ++i; } for (quoted = 0; i < arg.len && (quoted || arg.s[i] != term); ++i) { switch (arg.s[i]) { case QUOTE: quoted = !quoted; break; case ESCAPE: ++i; /* fall through */ default: if (!str_catc(&addr, arg.s[i])) return &resp_oom; } } ++i; if (i > arg.len) return &resp_badaddr; while (i < arg.len && arg.s[i] == SPACE) ++i; if (!str_copyb(¶ms, arg.s+i, arg.len-i)) return &resp_oom; str_subst(¶ms, ' ', 0); /* strip source routing */ if (addr.s[0] == AT && (i = str_findfirst(&addr, COLON) + 1) != 0) str_lcut(&addr, i); return 0; }
void make_username(const char* start, ssize_t len, const char* msgprefix) { str_copyb(&username, start, len); if (local_name && str_findfirst(&username, AT) < 0) { str_catc(&username, AT); str_cats(&username, local_name); } str_copy2s(&msgstr, msgprefix, username.s); log_line(msgstr.s, msgstr.len); }
/* actually do the log entry */ static void dosqlog(void) { str sql; str mq, mr, md; unsigned int i, ni; if(!sqlseq) return; /* nothing happened */ str_init(&sql); str_init(&mq); str_init(&mr); str_init(&mflags); addflag("greylist", "greylist", 1); addflag("sump", "sump", 0); addflag("dblhelo", "dblhelo", 0); addflag("dblfrom", "dblfrom", 1); addflag("badrcpt", "badrcpt", 1); addflag("badbatv", "badbatv", 1); addflag("rcptrule", "badabuse", 1); str_copys(&sql, "update mail set flags='"); str_cat(&sql, &mflags); sqlquote(&qsender, &mq); str_cats(&sql, "',mailfrom='"); str_cat(&sql, &mq); /* envelope domain */ i = str_findfirst(&qsender, '@'); if(i < qsender.len) { str_init(&md); str_copyb(&md, qsender.s+i+1, qsender.len-i-1); sqlquote(&md, &mq); str_cats(&sql, "',envdomain='"); str_cat(&sql, &mq); } str_cats(&sql, "' where serial="); str_cat(&sql, &sqlseqstr); sqlquery(&sql, 0); /* now add the recipients */ for(i = 0; i < qrecips.len ; i = ni+1) { ni = str_findnext(&qrecips, 0, i); str_copyb(&mr, qrecips.s+i, ni-i); sqlquote(&mr, &mq); str_copys(&sql,"insert into mailrcpt(serial,rcptto) values("); str_cat(&sql, &sqlseqstr); str_cats(&sql, ",'"); str_cat(&sql, &mq); str_cats(&sql, "')"); sqlquery(&sql, 0); } }
/* Mark a maildir filename with the named flag */ static int add_flag(str* fn, char flag) { int c; /* If the filename has no flags, append them */ if ((c = str_findfirst(fn, ':')) == -1) { if (!str_cats(fn, ":2,")) return 0; } else { /* If it has a colon (start of flags), see if they are a type we * recognize, and bail out if they aren't */ if (fn->s[c+1] != '2' || fn->s[c+2] != ',') return 1; /* Scan through the flag characters and return success * if the message is already marked with the flag */ if (strchr(fn->s+c+3, flag) != 0) return 1; } return str_catc(fn, flag); }
static int response1(struct sasl_state* ss, const str* response, str* challenge) { unsigned i; unsigned j; if (response->len == 0) return SASL_RESP_BAD; if ((i = str_findfirst(response, 0)) == (unsigned)-1) return SASL_RESP_BAD; ++i; if ((j = str_findnext(response, 0, i)) == (unsigned)-1) return SASL_RESP_BAD; ++j; if (!str_copyb(&ss->username, response->s + i, j - i - 1)) return SASL_TEMP_FAIL; return sasl_authenticate_plain(ss, response->s+i, response->s+j); (void)challenge; }
static void handle_auth_plain_response(str* line, ssize_t offset) { int start; int end; saw_auth_plain = 0; if (base64decode(line->s + offset, line->len - offset, &tmpstr)) { /* tmpstr should now contain "AUTHORIZATION\0AUTHENTICATION\0PASSWORD" */ if ((start = str_findfirst(&tmpstr, NUL)) >= 0 && (end = str_findnext(&tmpstr, NUL, ++start)) > start) { make_username(tmpstr.s + start, end - start, "AUTH PLAIN "); str_splice(&tmpstr, start, end - start, &username); line->len = offset; base64encode(tmpstr.s, tmpstr.len, line); str_catb(line, CRLF, 2); } } }
static void cmd_store(str* data) { int i; int fd; if ((i = str_findfirst(data, 0)) <= 0) respond("DStore command is missing data"); ++i; if ((fd = tempfile("tmp/spool")) == -1) respond("ZCould not create temporary file"); if (write(fd, data->s + i, data->len - i) != (long)(data->len - i) || (fd = fixup(fd)) == -1 || fchmod(fd, 0400) == -1 || close(fd) != 0) respond("ZCould not write temporary file"); if (rename(tempname.s, filename.s) != 0) respond("ZCould not rename temporary file"); trigger_pull(TRIGGER); respond("KCrontab successfully written"); }
static void handle_packet(struct connection* c) { str* packet; const char* id; const char* runas; const char* command; const char* envstart; long slot; unsigned int i; struct passwd* pw; packet = &c->packet; id = packet->s; if (*id == NUL) FAIL(id, "DInvalid ID"); if ((slot = pick_slot()) < 0) FAIL(id, "DCould not allocate a slot"); wrap_str(str_copys(&slots[slot].id, id)); if ((i = str_findfirst(packet, NUL) + 1) >= packet->len) FAIL(id, "DInvalid packet"); runas = packet->s + i; if (*runas == NUL || (pw = getpwnam(runas)) == 0) FAIL(id, "DInvalid username"); if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len) FAIL(id, "DInvalid packet"); command = packet->s + i; if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len) envstart = 0; else { envstart = packet->s + i; wrap_str(str_catc(packet, 0)); } if (!init_slot(slot, pw)) FAIL(id, "ZOut of memory"); start_slot(slot, command, envstart); }