예제 #1
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  report a recipient to remote
 */
char *
rcptto(char *to)
{
	String *s;

	s = unescapespecial(bangtoat(to));
	if(toline == 0)
		toline = s_new();
	else
		s_append(toline, ", ");
	s_append(toline, s_to_c(s));
	if(strchr(s_to_c(s), '@'))
		dBprint("RCPT TO:<%s>\r\n", s_to_c(s));
	else {
		s_append(toline, "@");
		s_append(toline, ddomain);
		dBprint("RCPT TO:<%s@%s>\r\n", s_to_c(s), ddomain);
	}
	alarm(10*alarmscale);
	switch(getreply()){
	case 2:
		break;
	case 5:
		return Giveup;
	default:
		return Retry;
	}
	return 0;
}
예제 #2
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  print out a parsed date
 */
int
printdate(Node *p)
{
	int n, sep = 0;

	n = dBprint("Date: %s,", s_to_c(p->s));
	for(p = p->next; p; p = p->next){
		if(p->s){
			if(sep == 0) {
				dBputc(' ');
				n++;
			}
			if (p->next)
				n += dBprint("%s", s_to_c(p->s));
			else
				n += dBprint("%s", rewritezone(s_to_c(p->s)));
			sep = 0;
		} else {
			dBputc(p->c);
			n++;
			sep = 1;
		}
	}
	n += dBprint("\r\n");
	return n;
}
예제 #3
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
static char *
doauth(char *methods)
{
	char *buf, *err;
	UserPasswd *p;
	int n;
	DS ds;

	dial_string_parse(ddomain, &ds);

	if(user != nil)
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q user=%q", ds.host, user);
	else
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q", ds.host);
	if (p == nil)
		return Giveup;

	err = Retry;
	if (strstr(methods, "LOGIN")){
		dBprint("AUTH LOGIN\r\n");
		if (getreply() != 3)
			goto out;

		dBprint("%.*[\r\n", strlen(p->user), p->user);
		if (getreply() != 3)
			goto out;

		dBprint("%.*[\r\n", strlen(p->passwd), p->passwd);
		if (getreply() != 2)
			goto out;

		err = nil;
	}
	else
	if (strstr(methods, "PLAIN")){
		n = strlen(p->user) + strlen(p->passwd) + 2;
		buf = malloc(n+1);
		if (buf == nil) {
			free(buf);
			goto out;	/* Out of memory */
		}
		snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd);
		dBprint("AUTH PLAIN %.*[\r\n", n, buf);
		memset(buf, 0, n);
		free(buf);
		if (getreply() != 2)
			goto out;
		err = nil;
	} else
		err = "No supported AUTH method";
out:
	memset(p->user, 0, strlen(p->user));
	memset(p->passwd, 0, strlen(p->passwd));
	free(p);
	return err;
}
예제 #4
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  print out the parsed header
 */
int
printheader(void)
{
	int n, len;
	Field *f;
	Node *p;
	char *cp;
	char c[1];

	n = 0;
	for(f = firstfield; f; f = f->next){
		for(p = f->node; p; p = p->next){
			if(p->s)
				n += dBprint("%s", s_to_c(p->s));
			else {
				c[0] = p->c;
				putcrnl(c, 1);
				n++;
			}
			if(p->white){
				cp = s_to_c(p->white);
				len = strlen(cp);
				putcrnl(cp, len);
				n += len;
			}
			uneaten = p->end;
		}
		putcrnl("\n", 1);
		n++;
		uneaten++;		/* skip newline */
	}
	return n;
}
예제 #5
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  report sender to remote
 */
char *
mailfrom(char *from)
{
	if(!returnable(from))
		dBprint("MAIL FROM:<>\r\n");
	else
	if(strchr(from, '@'))
		dBprint("MAIL FROM:<%s>\r\n", from);
	else
		dBprint("MAIL FROM:<%s@%s>\r\n", from, hostdomain);
	switch(getreply()){
	case 2:
		break;
	case 5:
		return Giveup;
	default:
		return Retry;
	}
	return 0;
}
예제 #6
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  we're leaving
 */
void
quit(char *rv)
{
		/* 60 minutes to quit */
	quitting = 1;
	quitrv = rv;
	alarm(60*alarmscale);
	dBprint("QUIT\r\n");
	getreply();
	Bterm(&bout);
	Bterm(&bfile);
}
예제 #7
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  exchange names with remote host, attempt to
 *  enable encryption and optionally authenticate.
 *  not fatal if we can't.
 */
static char *
dotls(char *me)
{
	char *err;

	dBprint("STARTTLS\r\n");
	if (getreply() != 2)
		return Giveup;

	err = wraptls();
	if (err != nil)
		return err;

	return(hello(me, 1));
}
예제 #8
0
파일: smtp.c 프로젝트: Earnestly/plan9
/*
 *  exchange names with remote host, attempt to
 *  enable encryption and optionally authenticate.
 *  not fatal if we can't.
 */
static char *
dotls(char *me)
{
	TLSconn *c;
	char *err;
	int fd;

	c = mallocz(sizeof(*c), 1);	/* Note: not freed on success */
	if (c == nil)
		return Giveup;

	dBprint("STARTTLS\r\n");
	if (getreply() != 2)
		return Giveup;

	fd = tlsClient(Bfildes(&bout), c);
	if (fd < 0) {
		syslog(0, "smtp", "tlsClient to %q: %r", ddomain);
		return Giveup;
	}

	err = ckthumbs(c);
	if (err && !okunksecure) {
		free(c);
		close(fd);
		return err;		/* how to recover? TLS is started */
	}

	Bterm(&bin);
	Bterm(&bout);

	/*
	 * set up bin & bout to use the TLS fd, i/o upon which generates
	 * i/o on the original, underlying fd.
	 */
	Binit(&bin, fd, OREAD);
	fd = dup(fd, -1);
	Binit(&bout, fd, OWRITE);

	syslog(0, "smtp", "started TLS to %q", ddomain);
	return(hello(me, 1));
}
예제 #9
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
/*
 *  send the damn thing
 */
char *
data(String *from, Biobuf *b)
{
	char *buf, *cp;
	int i, n, nbytes, bufsize, eof, r;
	String *fromline;
	char errmsg[Errlen];
	char id[40];

	/*
	 *  input the header.
	 */

	buf = malloc(1);
	if(buf == 0){
		s_append(s_restart(reply), "out of memory");
		return Retry;
	}
	n = 0;
	eof = 0;
	for(;;){
		cp = Brdline(b, '\n');
		if(cp == nil){
			eof = 1;
			break;
		}
		nbytes = Blinelen(b);
		buf = realloc(buf, n+nbytes+1);
		if(buf == 0){
			s_append(s_restart(reply), "out of memory");
			return Retry;
		}
		strncpy(buf+n, cp, nbytes);
		n += nbytes;
		if(nbytes == 1)		/* end of header */
			break;
	}
	buf[n] = 0;
	bufsize = n;

	/*
	 *  parse the header, turn all addresses into @ format
	 */
	yyinit(buf, n);
	yyparse();

	/*
	 *  print message observing '.' escapes and using \r\n for \n
	 */
	alarm(20*alarmscale);
	if(!filter){
		dBprint("DATA\r\n");
		switch(getreply()){
		case 3:
			break;
		case 5:
			free(buf);
			return Giveup;
		default:
			free(buf);
			return Retry;
		}
	}
	/*
	 *  send header.  add a message-id, a sender, and a date if there
	 *  isn't one
	 */
	nbytes = 0;
	fromline = convertheader(from);
	uneaten = buf;

	srand(truerand());
	if(messageid == 0){
		for(i=0; i<16; i++){
			r = rand()&0xFF;
			id[2*i] = hex[r&0xF];
			id[2*i+1] = hex[(r>>4)&0xF];
		}
		id[2*i] = '\0';
		nbytes += Bprint(&bout, "Message-ID: <%s@%s>\r\n", id, hostdomain);
		if(debug)
			Bprint(&berr, "Message-ID: <%s@%s>\r\n", id, hostdomain);
	}

	if(originator==0){
		nbytes += Bprint(&bout, "From: %s\r\n", s_to_c(fromline));
		if(debug)
			Bprint(&berr, "From: %s\r\n", s_to_c(fromline));
	}
	s_free(fromline);

	if(destination == 0 && toline)
		if(*s_to_c(toline) == '@'){	/* route addr */
			nbytes += Bprint(&bout, "To: <%s>\r\n", s_to_c(toline));
			if(debug)
				Bprint(&berr, "To: <%s>\r\n", s_to_c(toline));
		} else {
			nbytes += Bprint(&bout, "To: %s\r\n", s_to_c(toline));
			if(debug)
				Bprint(&berr, "To: %s\r\n", s_to_c(toline));
		}

	if(date==0 && udate)
		nbytes += printdate(udate);
	if (usys)
		uneaten = usys->end + 1;
	nbytes += printheader();
	if (*uneaten != '\n')
		putcrnl("\n", 1);

	/*
	 *  send body
	 */

	putcrnl(uneaten, buf+n - uneaten);
	nbytes += buf+n - uneaten;
	if(eof == 0){
		for(;;){
			n = Bread(b, buf, bufsize);
			if(n < 0){
				rerrstr(errmsg, sizeof(errmsg));
				s_append(s_restart(reply), errmsg);
				free(buf);
				return Retry;
			}
			if(n == 0)
				break;
			alarm(10*alarmscale);
			putcrnl(buf, n);
			nbytes += n;
		}
	}
	free(buf);
	if(!filter){
		if(last != '\n')
			dBprint("\r\n.\r\n");
		else
			dBprint(".\r\n");
		alarm(10*alarmscale);
		switch(getreply()){
		case 2:
			break;
		case 5:
			return Giveup;
		default:
			return Retry;
		}
		syslog(0, "smtp", "%s sent %d bytes to %s", s_to_c(from),
				nbytes, s_to_c(toline));/**/
	}
	return 0;
}
예제 #10
0
파일: smtp.c 프로젝트: grobe0ba/plan9front
char *
hello(char *me, int encrypted)
{
	int ehlo;
	String *r;
	char *ret, *s, *t;

	if (!encrypted) {
		if(trysecure > 1){
			if((ret = wraptls()) != nil)
				return ret;
			encrypted = 1;
		}

		/*
		 * Verizon fails to print the smtp greeting banner when it
		 * answers a call.  Send a no-op in the hope of making it
		 * talk.
		 */
		if (autistic) {
			dBprint("NOOP\r\n");
			getreply();	/* consume the smtp greeting */
			/* next reply will be response to noop */
		}
		switch(getreply()){
		case 2:
			break;
		case 5:
			return Giveup;
		default:
			return Retry;
		}
	}

	ehlo = 1;
  Again:
	if(ehlo)
		dBprint("EHLO %s\r\n", me);
	else
		dBprint("HELO %s\r\n", me);
	switch (getreply()) {
	case 2:
		break;
	case 5:
		if(ehlo){
			ehlo = 0;
			goto Again;
		}
		return Giveup;
	default:
		return Retry;
	}
	r = s_clone(reply);
	if(r == nil)
		return Retry;	/* Out of memory or couldn't get string */

	/* Invariant: every line has a newline, a result of getcrlf() */
	for(s = s_to_c(r); (t = strchr(s, '\n')) != nil; s = t + 1){
		*t = '\0';
		for (t = s; *t != '\0'; t++)
			*t = toupper(*t);
		if(!encrypted && trysecure &&
		    (strcmp(s, "250-STARTTLS") == 0 ||
		     strcmp(s, "250 STARTTLS") == 0)){
			s_free(r);
			return dotls(me);
		}
		if(tryauth && (encrypted || insecure) &&
		    (strncmp(s, "250 AUTH", strlen("250 AUTH")) == 0 ||
		     strncmp(s, "250-AUTH", strlen("250 AUTH")) == 0)){
			ret = doauth(s + strlen("250 AUTH "));
			s_free(r);
			return ret;
		}
	}
	s_free(r);
	return 0;
}
예제 #11
0
파일: smtp.c 프로젝트: Earnestly/plan9
static char *
doauth(char *methods)
{
	char *buf, *base64;
	int n;
	DS ds;
	UserPasswd *p;

	dial_string_parse(ddomain, &ds);

	if(user != nil)
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q user=%q", ds.host, user);
	else
		p = auth_getuserpasswd(nil,
	  	  "proto=pass service=smtp server=%q", ds.host);
	if (p == nil)
		return Giveup;

	if (strstr(methods, "LOGIN")){
		dBprint("AUTH LOGIN\r\n");
		if (getreply() != 3)
			return Retry;

		n = strlen(p->user);
		base64 = malloc(2*n);
		if (base64 == nil)
			return Retry;	/* Out of memory */
		enc64(base64, 2*n, (uchar *)p->user, n);
		dBprint("%s\r\n", base64);
		if (getreply() != 3)
			return Retry;

		n = strlen(p->passwd);
		base64 = malloc(2*n);
		if (base64 == nil)
			return Retry;	/* Out of memory */
		enc64(base64, 2*n, (uchar *)p->passwd, n);
		dBprint("%s\r\n", base64);
		if (getreply() != 2)
			return Retry;

		free(base64);
	}
	else
	if (strstr(methods, "PLAIN")){
		n = strlen(p->user) + strlen(p->passwd) + 3;
		buf = malloc(n);
		base64 = malloc(2 * n);
		if (buf == nil || base64 == nil) {
			free(buf);
			return Retry;	/* Out of memory */
		}
		snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd);
		enc64(base64, 2 * n, (uchar *)buf, n - 1);
		free(buf);
		dBprint("AUTH PLAIN %s\r\n", base64);
		free(base64);
		if (getreply() != 2)
			return Retry;
	}
	else
		return "No supported AUTH method";
	return(0);
}