Пример #1
0
/** The /who command: retrieves information from users. */
DLLFUNC int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aChannel *target_channel;
char *mask = parv[1];
char star[] = "*";
int i = 0;

	who_flags = 0;
	memset(&wfl, 0, sizeof(wfl));

	if (parc > 1)
	{
		i = parse_who_options(sptr, parc - 1, parv + 1);
		if (i < 0)
		{
			sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask);
			return 0;
		}
	}

	if (parc-i < 2 || strcmp(parv[1 + i], "0") == 0)
		mask = star;
	else
		mask = parv[1 + i];

	if (!i && parc > 2 && *parv[2] == 'o')
		who_flags |= WF_OPERONLY;

	collapse(mask);

	if (*mask == '\0')
	{
		/* no mask given */
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], "*");
		return 0;
	}

	if ((target_channel = find_channel(mask, NULL)) != NULL)
	{
		do_channel_who(sptr, target_channel, mask);
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask);
		return 0;
	}

	if (wfl.channel && wfl.want_channel == WHO_WANT && 
	    (target_channel = find_channel(wfl.channel, NULL)) != NULL)
	{
		do_channel_who(sptr, target_channel, mask);
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask);
		return 0;
	}
	else
	{
		do_other_who(sptr, mask);
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, parv[0], mask);
		return 0;
	}

	return 0;
}
Пример #2
0
/*
 *  login to remote system with given user name and password.
 */
void
clogin(char *cuser, char *cpassword)
{
	free(user);
	user = strdup(cuser);
	if (strcmp(user, "anonymous") != 0 &&
	    strcmp(user, "ftp") != 0)
		fatal("User must be 'anonymous' or 'ftp'");
	sendrequest("USER", user);
	switch(getreply(&ctlin, msg, sizeof(msg), 1)){
	case Success:
		return;
	case Incomplete:
		break;
	case TempFail:
	case PermFail:
		fatal("login failed");
	}
	if (cpassword == 0)
		fatal("password needed");
	sendrequest("PASS", cpassword);
	if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)
		fatal("password failed");
	if(strstr(msg, "Sess#"))
		defos = MVS;
	return;
}
Пример #3
0
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
/*
 *  login to remote system
 */
void
rlogin(char *rsys, char *keyspec)
{
	char *line;
	char pass[128];
	UserPasswd *up;

	up = nil;
	for(;;){
		if(up == nil && os != Plan9)
			up = auth_getuserpasswd(auth_getkey, "proto=pass server=%s service=ftp %s", rsys, keyspec);
		if(up != nil){
			sendrequest("USER", up->user);
		} else {
			print("User[default = %s]: ", user);
			line = Brdline(&stdin, '\n');
			if(line == 0)
				exits(0);
			line[Blinelen(&stdin)-1] = 0;
			if(*line){
				free(user);
				user = strdup(line);
			}
			sendrequest("USER", user);
		}
		switch(getreply(&ctlin, msg, sizeof(msg), 1)){
		case Success:
			goto out;
		case Incomplete:
			break;
		case TempFail:
		case PermFail:
			continue;
		}

		if(up != nil){
			sendrequest("PASS", up->passwd);
		} else {
			if(getpassword(pass, pass+sizeof(pass)) < 0)
				exits(0);
			sendrequest("PASS", pass);
		}
		if(getreply(&ctlin, msg, sizeof(msg), 1) == Success){
			if(strstr(msg, "Sess#"))
				defos = MVS;
			break;
		}
	}
out:
	if(up != nil){
		memset(up, 0, sizeof(*up));
		free(up);
	}
}
Пример #5
0
/*
 *  connect to remote server, default network is "tcp/ip"
 */
void
hello(char *dest)
{
	char *p;
	char dir[Maxpath];
	TLSconn conn;

	Binit(&stdin, 0, OREAD);	/* init for later use */

	ctlfd = dial(netmkaddr(dest, "tcp", "ftp"), 0, dir, 0);
	if(ctlfd < 0){
		fprint(2, "can't dial %s: %r\n", dest);
		exits("dialing");
	}
		
	Binit(&ctlin, ctlfd, OREAD);

	/* remember network for the data connections */
	p = strrchr(dir+1, '/');
	if(p == 0)
		fatal("wrong dial(2) linked with ftp");
	*p = 0;
	safecpy(net, dir, sizeof(net));

	/* wait for hello from other side */
	if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)
		fatal("bad hello");
	if(strstr(msg, "Plan 9"))
		os = Plan9;

	if(usetls){
		sendrequest("AUTH", "TLS");
		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)
			fatal("bad auth tls");

		ctlfd = tlsClient(ctlfd, &conn);
		if(ctlfd < 0)
			fatal("starting tls: %r");
		free(conn.cert);

		Binit(&ctlin, ctlfd, OREAD);

		sendrequest("PBSZ", "0");
		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)
			fatal("bad pbsz 0");
		sendrequest("PROT", "P");
		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)
			fatal("bad prot p");
	}
}
Пример #6
0
static void send_who_reply(aClient *sptr, aClient *acptr, 
			   char *channel, char *status, char *xstat)
{
	char *stat;
	char *host;
	int flat = (FLAT_MAP && !IsAnOper(sptr)) ? 1 : 0;

	stat = malloc(strlen(status) + strlen(xstat) + 1);
	sprintf(stat, "%s%s", status, xstat);

	if (IsAnOper(sptr))
	{
		if (who_flags & WF_REALHOST)
			host = acptr->user->realhost;
		else if (who_flags & WF_IP)
			host = (acptr->user->ip_str ? acptr->user->ip_str : 
			        acptr->user->realhost);
		else
			host = GetHost(acptr);
	}
	else
		host = GetHost(acptr);
					

	if (IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES)
	        sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
        	     channel,       /* channel name */
	             acptr->user->username, /* user name */
        	     host,		    /* hostname */
	             "hidden",              /* let's hide the server from normal users if the server is a uline and HIDE_ULINES is on */
        	     acptr->name,           /* nick */
	             stat,                  /* status */
        	     0,                     /* hops (hidden) */
	             acptr->info            /* realname */
             	);

	else
		sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,      
		     channel,       /* channel name */
		     acptr->user->username,      /* user name */
		     host,		         /* hostname */
		     acptr->user->server,        /* server name */
		     acptr->name,                /* nick */
		     stat,                       /* status */
		     flat ? 0 : acptr->hopcount, /* hops */ 
		     acptr->info                 /* realname */
		     );
	free(stat);
}
Пример #7
0
/*
 *  tell remote that we're exiting and then do it
 */
void
quit(void)
{
	sendrequest("QUIT", nil);
	getreply(&ctlin, msg, sizeof(msg), 0);
	exits(0);
}
Пример #8
0
/*
 *  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;
}
Пример #9
0
void Connection::site(int argc, char *argv[])
{
	PROC(("site","%d [%s,%s,%s]",argc,(argc>=1)?argv[0]:"nil",(argc>=2)?argv[1]:"nil",(argc>=3)?argv[2]:"nil"));
	int  i;
	char buf[BUFSIZ];

	if(argc < 2)
	{
		code = -1;
		return;
	}

	strcpy(buf, Opt.cmdSite);
	strcat(buf, " ");
	strcat(buf, argv[1]);

	for(i = 2; i < argc; i++)
	{
		strcat(buf, " ");
		strcat(buf, argv[i]);
	}

	if(command(buf) == RPL_PRELIM)
		while(getreply(0) == RPL_PRELIM);
}
Пример #10
0
static int _ftp( struct ftp_info *info, unsigned long flags, const char *cmd )
{
struct opusftp_globals *ogp = info->fi_og;
int len;

	
// Valid?
if	(!info || !cmd)
	return 600;

// Socket used by non-owner task?
if	(info->fi_task != FindTask(0))
	return 600;

// Log outgoing commands if debugging is turned on
// NOOPs are never logged, passwords are hidden
if	(!info->fi_doing_noop && ogp->og_oc.oc_log_debug)
	logprintf("--> %s\n", strnicmp(cmd,"PASS ",5) ? cmd : "PASS ....." );


len = strlen(cmd);
send( info->fi_cs, (char *)cmd, len, 0 );

// Don't get reply if this is an asynchronous command, simply return 0
if	(flags & FTPFLAG_ASYNCH)
	return 0;


// Can TIMEOUT
return getreply( info );
}
Пример #11
0
/*
 *  used for keep alives
 */
void
nop(void)
{
	if(lastsend - time(0) < 15)
		return;
	sendrequest("PWD", nil);
	getreply(&ctlin, msg, sizeof(msg), 0);
}
Пример #12
0
static void
image(void)
{
	sendrequest("TYPE I", nil);
	switch(getreply(&ctlin, msg, sizeof(msg), 0)){
	case Success:
		break;
	default:
		fatal("can't set type to image/binary");
	}
}
Пример #13
0
static void
ascii(void)
{
	sendrequest("TYPE A", nil);
	switch(getreply(&ctlin, msg, sizeof(msg), 0)){
	case Success:
		break;
	default:
		fatal("can't set type to ascii");
	}
}
Пример #14
0
/*
 *  create a remote directory
 */
int
createdir(Node *node)
{
	if(changedir(node->parent) < 0)
		return -1;
	
	sendrequest("MKD", node->d->name);
	if(getreply(&ctlin, msg, sizeof(msg), 0) != Success)
		return -1;
	return 0;
}
Пример #15
0
/*
 *  remove a remote directory
 */
int
removedir(Node *node)
{
	if(changedir(node->parent) < 0)
		return -1;
	
	sendrequest("RMD", s_to_c(node->remname));
	if(getreply(&ctlin, msg, sizeof(msg), 0) != Success)
		return -1;
	return 0;
}
Пример #16
0
/*
 *  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);
}
Пример #17
0
/*
 *  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));
}
Пример #18
0
/*
 *  Announce on a local port and tell its address to the the remote side
 */
static int
port(void)
{
	char buf[256];
	int n, fd;
	char *ptr;
	uchar ipaddr[IPaddrlen];
	int port;

	/* get a channel to listen on, let kernel pick the port number */
	sprint(buf, "%s!*!0", net);
	listenfd = announce(buf, netdir);
	if(listenfd < 0)
		return seterr("can't announce");

	/* get the local address and port number */
	sprint(buf, "%s/local", netdir);
	fd = open(buf, OREAD);
	if(fd < 0)
		return seterr("opening %s: %r", buf);
	n = read(fd, buf, sizeof(buf)-1);
	close(fd);
	if(n <= 0)
		return seterr("opening %s/local: %r", netdir);
	buf[n] = 0;
	ptr = strchr(buf, ' ');
	if(ptr)
		*ptr = 0;
	ptr = strchr(buf, '!')+1;
	port = atoi(ptr);

	memset(ipaddr, 0, IPaddrlen);
	if (*net){
		strcpy(buf, net);
		ptr = strchr(buf +1, '/');
		if (ptr)
			*ptr = 0;
		myipaddr(ipaddr, buf);
	}

	/* tell remote side */
	sprint(buf, "PORT %d,%d,%d,%d,%d,%d", ipaddr[IPv4off+0], ipaddr[IPv4off+1],
		ipaddr[IPv4off+2], ipaddr[IPv4off+3], port>>8, port&0xff);
	sendrequest(buf, nil);
	if(getreply(&ctlin, msg, sizeof(msg), 0) != Success)
		return seterr(msg);
	return 0;
}
Пример #19
0
/*
 *  read a remote file
 */
int
readfile1(Node *node)
{
	Biobuf *bp;
	char buf[4*1024];
	long off;
	int n;
	int tries;

	if(changedir(node->parent) < 0)
		return -1;

	for(tries = 0; tries < 4; tries++){
		switch(data(OREAD, &bp, "RETR", s_to_c(node->remname))){
		case Extra:
			break;
		case TempFail:
			continue;
		default:
			return seterr(nosuchfile);
		}
		off = 0;
		while((n = read(Bfildes(bp), buf, sizeof buf)) > 0){
			if(filewrite(node, buf, off, n) != n){
				off = -1;
				break;
			}
			off += n;
		}
		if(off < 0)
			return -1;

		/* make sure a file gets created even for a zero length file */
		if(off == 0)
			filewrite(node, buf, 0, 0);

		close(Bfildes(bp));
		switch(getreply(&ctlin, msg, sizeof(msg), 0)){
		case Success:
			return off;
		case TempFail:
			continue;
		default:
			return seterr(nosuchfile);
		}
	}
	return seterr(nosuchfile);
}
Пример #20
0
/*
 *  have server call back for a data connection
 */
static int
active(int mode, Biobuf **bpp, char *cmda, char *cmdb)
{
	int cfd, dfd, rv;
	char newdir[Maxpath];
	char datafile[Maxpath + 6];
	TLSconn conn;

	if(port() < 0)
		return TempFail;

	sendrequest(cmda, cmdb);

	rv = getreply(&ctlin, msg, sizeof(msg), 0);
	if(rv != Extra){
		close(listenfd);
		return rv;
	}

	/* wait for a new call */
	cfd = listen(netdir, newdir);
	if(cfd < 0)
		fatal("waiting for data connection");
	close(listenfd);

	/* open it's data connection and close the control connection */
	sprint(datafile, "%s/data", newdir);
	dfd = open(datafile, ORDWR);
	close(cfd);
	if(dfd < 0)
		fatal("opening data connection");

	if(usetls){
		memset(&conn, 0, sizeof(conn));
		dfd = tlsClient(dfd, &conn);
		if(dfd < 0)
			fatal("starting tls: %r");
		free(conn.cert);
	}

	Binit(&dbuf, dfd, mode);
	*bpp = &dbuf;
	return Extra;
}
Пример #21
0
/*
 *  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));
}
Пример #22
0
/*VARARGS1*/
int command(const char *fmt, ...)
{
	va_list ap;
	int r;
	void (*oldintr)(int);

	abrtflag = 0;
	if (debug) {
		printf("---> ");
		va_start(ap, fmt);
		vfprintf(stdout, fmt, ap);
		va_end(ap);
		printf("\n");
		(void) fflush(stdout);
	}
	if (cout == 0) {
		perror ("No control connection for command");
		code = -1;
		return (0);
	}
	oldintr = signal(SIGINT,cmdabort);
	{
		char buffer[1024];

		va_start(ap, fmt);
		vsprintf(buffer, fmt, ap);
		va_end(ap);
//DLJ: to work through  firewalls - send the command as a single message
		strcat(buffer,"\r\n");
		fprintfSocket(cout, buffer);
	}
//DLJ: the following two lines are replaced by the strcat above - seems to
// make it work through firewalls.
//	fprintfSocket(cout, "\r\n");
//	(void) fflush(cout);
	cpend = 1;
	r = getreply(!strcmp(fmt, "QUIT"));
	if (abrtflag && oldintr != SIG_IGN)
		(*oldintr)(SIGINT);
//	(void) signal(SIGINT, oldintr);
	return(r);
}
Пример #23
0
/*
 *  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;
}
Пример #24
0
int
command(const char *fmt, ...)
{
	va_list ap;
	int r;
	void (*oldintr)(int);

	abrtflag = 0;
	if (debug) {
		printf("---> ");
		va_start(ap, fmt);
		if (strncmp("PASS ", fmt, 5) == 0)
			printf("PASS XXXX");
		else 
			vfprintf(stdout, fmt, ap);
		va_end(ap);
		printf("\n");
		(void) fflush(stdout);
	}
	if (cout == NULL) {
		perror ("No control connection for command");
		code = -1;
		return (0);
	}
	oldintr = signal(SIGINT, cmdabort);
	va_start(ap, fmt);
	vfprintf(cout, fmt, ap);
	va_end(ap);
	fprintf(cout, "\r\n");
	(void) fflush(cout);
	cpend = 1;
	r = getreply(!strcmp(fmt, "QUIT"));
	if (abrtflag && oldintr != SIG_IGN)
		(*oldintr)(SIGINT);
	(void) signal(SIGINT, oldintr);
	return(r);
}
Пример #25
0
/*
 *  write back a file
 */
int
createfile1(Node *node)
{
	Biobuf *bp;
	char buf[4*1024];
	long off;
	int n;

	if(changedir(node->parent) < 0)
		return -1;

	if(data(OWRITE, &bp, "STOR", s_to_c(node->remname)) != Extra)
		return -1;
	for(off = 0; ; off += n){
		n = fileread(node, buf, off, sizeof(buf));
		if(n <= 0)
			break;
		write(Bfildes(bp), buf, n);
	}
	close(Bfildes(bp));
	if(getreply(&ctlin, msg, sizeof(msg), 0) != Success)
		return -1;
	return off;
}
Пример #26
0
/*
 *  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;
}
Пример #27
0
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;
}
Пример #28
0
void
recvrequest(const char *cmd, 
	    char *volatile local, char *remote, 
	    const char *lmode, int printnames)
{
	FILE *volatile fout, *volatile din = 0;
	int (*volatile closefunc)(FILE *);
	void (*volatile oldintp)(int);
	void (*volatile oldintr)(int);
	volatile int is_retr, tcrflag, bare_lfs = 0;
	static unsigned bufsize;
	static char *buf;
	volatile long bytes = 0, hashbytes = HASHBYTES;
	register int c, d;
	struct timeval start, stop;
	struct stat st;

#if 0
	printf("%s(%d): recvrequest(cmd=%s,local=%s,remote=%s)\n", __FILE__, __LINE__, cmd, local, remote);
#endif
	is_retr = strcmp(cmd, "RETR") == 0;
	if (is_retr && ftpverbose && printnames) {
		if (local && *local != '-')
			printf("local: %s ", local);
		if (remote)
			printf("remote: %s\n", remote);
	}
#if 0
	if (proxy && is_retr) {
		proxtrans(cmd, local, remote);
		return;
	}
#endif
	closefunc = NULL;
	oldintr = NULL;
	oldintp = NULL;
	tcrflag = !crflag && is_retr;
	if (sigsetjmp(recvabort, 1)) {
		while (cpend) {
			(void) getreply(0);
		}
		if (data >= 0) {
			(void) close(data);
			data = -1;
		}
		if (oldintr)
			(void) signal(SIGINT, oldintr);
		code = -1;
		return;
	}
	oldintr = signal(SIGINT, abortrecv);
#if 0
	if (strcmp(local, "-") && *local != '|') {
		if (access(local, W_OK) < 0) {
			char *dir = rindex(local, '/');

			if (errno != ENOENT && errno != EACCES) {
				fprintf(stderr, "local: %s: %s\n", local,
					strerror(errno));
				(void) signal(SIGINT, oldintr);
				code = -1;
				return;
			}
			if (dir != NULL)
				*dir = 0;
			d = access(dir ? local : ".", W_OK);
			if (dir != NULL)
				*dir = '/';
			if (d < 0) {
				fprintf(stderr, "local: %s: %s\n", local,
					strerror(errno));
				(void) signal(SIGINT, oldintr);
				code = -1;
				return;
			}
			if (!runique && errno == EACCES &&
			    chmod(local, 0600) < 0) {
				fprintf(stderr, "local: %s: %s\n", local,
					strerror(errno));
				/*
				 * Believe it or not, this was actually
				 * repeated in the original source.
				 */
				(void) signal(SIGINT, oldintr);
				/*(void) signal(SIGINT, oldintr);*/
				code = -1;
				return;
			}
			if (runique && errno == EACCES &&
			   (local = gunique(local)) == NULL) {
				(void) signal(SIGINT, oldintr);
				code = -1;
				return;
			}
		}
		else if (runique && (local = gunique(local)) == NULL) {
			(void) signal(SIGINT, oldintr);
			code = -1;
			return;
		}
	}
#endif
	if (!is_retr) {
		if (curtype != TYPE_A)
			changetype(TYPE_A, 0);
	} 
	else if (curtype != type) {
		changetype(type, 0);
	}
	if (initconn()) {
		(void) signal(SIGINT, oldintr);
		code = -1;
		return;
	}
	if (sigsetjmp(recvabort, 1))
		goto abort;
	if (is_retr && restart_point &&
	    command("REST %ld", (long) restart_point) != CONTINUE)
		return;
	if (remote) {
		if (command("%s %s", cmd, remote) != PRELIM) {
			(void) signal(SIGINT, oldintr);
			return;
		}
	} 
	else {
		if (command("%s", cmd) != PRELIM) {
			(void) signal(SIGINT, oldintr);
			return;
		}
	}
	din = dataconn("r");
	if (din == NULL)
		goto abort;
	if (strcmp(local, "-") == 0)
		fout = stdout;
	else if (*local == '|') {
		oldintp = signal(SIGPIPE, SIG_IGN);
		fout = popen(local + 1, "w");
		if (fout == NULL) {
			perror(local+1);
			goto abort;
		}
		closefunc = pclose;
	} 
	else {
		extern int local_fclose();
		fout = local_fopen(local, lmode);
		if (fout == NULL) {
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
			goto abort;
		}
		closefunc = local_fclose;
	}
	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
		st.st_blksize = BUFSIZ;
	if (st.st_blksize > bufsize) {
		if (buf)
			(void) free(buf);
		buf = malloc((unsigned)st.st_blksize);
		if (buf == NULL) {
			perror("malloc");
			bufsize = 0;
			goto abort;
		}
		bufsize = st.st_blksize;
	}
	(void) gettimeofday(&start, (struct timezone *)0);
	switch (curtype) {

	case TYPE_I:
	case TYPE_L:
		if (restart_point &&
		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
			if (closefunc != NULL)
				(*closefunc)(fout);
			return;
		}
		errno = d = 0;
		while ((c = read(fileno(din), buf, bufsize)) > 0) {
			if ((d = local_write(fileno(fout), buf, c)) != c)
				break;
			bytes += c;
			if (hash && is_retr) {
				while (bytes >= hashbytes) {
					(void) putchar('#');
					hashbytes += HASHBYTES;
				}
				(void) fflush(stdout);
			}
			if (tick && (bytes >= hashbytes) && is_retr) {
				(void) printf("\rBytes transferred: %ld",
					bytes);
				(void) fflush(stdout);
				while (bytes >= hashbytes)
					hashbytes += TICKBYTES;
			}
		}
		if (hash && bytes > 0) {
			if (bytes < HASHBYTES)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (tick && is_retr) {
			(void) printf("\rBytes transferred: %ld\n", bytes);
			(void) fflush(stdout);
		}
		if (c < 0) {
			if (errno != EPIPE)
				perror("netin");
			bytes = -1;
		}
		if (d < c) {
			if (d < 0)
				fprintf(stderr, "local: %s: %s\n", local,
					strerror(errno));
			else
				fprintf(stderr, "%s: short write\n", local);
		}
		break;

	case TYPE_A:
#if 0 /* ascii mode not supported for netflash */
		if (restart_point) {
			register int i, n, ch;

			if (fseek(fout, 0L, L_SET) < 0)
				goto done;
			n = restart_point;
			for (i = 0; i++ < n;) {
				if ((ch = getc(fout)) == EOF)
					goto done;
				if (ch == '\n')
					i++;
			}
			if (fseek(fout, 0L, L_INCR) < 0) {
done:
				fprintf(stderr, "local: %s: %s\n", local,
					strerror(errno));
				if (closefunc != NULL)
					(*closefunc)(fout);
				return;
			}
		}
		while ((c = getc(din)) != EOF) {
			if (c == '\n')
				bare_lfs++;
			while (c == '\r') {
				while (hash && (bytes >= hashbytes)
					&& is_retr) {
					(void) putchar('#');
					(void) fflush(stdout);
					hashbytes += HASHBYTES;
				}
				if (tick && (bytes >= hashbytes) && is_retr) {
					printf("\rBytes transferred: %ld",
						bytes);
					fflush(stdout);
					while (bytes >= hashbytes)
						hashbytes += TICKBYTES;
				}
				bytes++;
				if ((c = getc(din)) != '\n' || tcrflag) {
					if (ferror(fout))
						goto break2;
					(void) putc('\r', fout);
					if (c == '\0') {
						bytes++;
						goto contin2;
					}
					if (c == EOF)
						goto contin2;
				}
			}
			(void) putc(c, fout);
			bytes++;
	contin2:	;
		}
break2:
		if (hash && is_retr) {
			if (bytes < hashbytes)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (tick && is_retr) {
			(void) printf("\rBytes transferred: %ld\n", bytes);
			(void) fflush(stdout);
		}
		if (bare_lfs) {
			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
			printf("File may not have transferred correctly.\n");
		}
		if (ferror(din)) {
			if (errno != EPIPE)
				perror("netin");
			bytes = -1;
		}
		if (ferror(fout))
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
#else
		printf("Netflash does not support ASCII downloads!\n");
		bytes = -1;
#endif 0 /* ascii mode not supported for netflash */
		break;
	}
	if (closefunc != NULL)
		(*closefunc)(fout);
	(void) signal(SIGINT, oldintr);
	if (oldintp)
		(void) signal(SIGPIPE, oldintp);
	(void) gettimeofday(&stop, (struct timezone *)0);
	(void) fclose(din);
	/* closes data as well, so discard it */
	data = -1;
	(void) getreply(0);
	if (bytes > 0 && is_retr)
		ptransfer("received", bytes, &start, &stop);
	return;
abort:

/* abort using RFC959 recommended IP,SYNC sequence  */

	(void) gettimeofday(&stop, (struct timezone *)0);
	if (oldintp)
		(void) signal(SIGPIPE, oldintp);
	(void) signal(SIGINT, SIG_IGN);
	if (!cpend) {
		code = -1;
		(void) signal(SIGINT, oldintr);
		return;
	}

	abort_remote(din);
	code = -1;
	if (closefunc != NULL && fout != NULL)
		(*closefunc)(fout);
	if (din) {
		(void) fclose(din);
	}
	if (data >= 0) {
		/* if it just got closed with din, again won't hurt */
		(void) close(data);
		data = -1;
	}
	if (bytes > 0)
		ptransfer("received", bytes, &start, &stop);
	(void) signal(SIGINT, oldintr);
}
Пример #29
0
void
sendrequest(const char *cmd, char *local, char *remote, int printnames)
{
	struct stat st;
	struct timeval start, stop;
	register int c, d;
	FILE *volatile fin, *volatile dout = 0;
	int (*volatile closefunc)(FILE *);
	void (*volatile oldintr)(int);
	void (*volatile oldintp)(int);
	volatile long bytes = 0, hashbytes = HASHBYTES;
	char buf[BUFSIZ], *bufp;
	const char *volatile lmode;

#if 1
	printf("%s(%d): sendrequest(cmd=%s,local=%s,remote=%s)\n", __FILE__, __LINE__, cmd, local, remote);
#endif
	if (ftpverbose && printnames) {
		if (local && *local != '-')
			printf("local: %s ", local);
		if (remote)
			printf("remote: %s\n", remote);
	}
#if 0
	if (proxy) {
		proxtrans(cmd, local, remote);
		return;
	}
#endif
	if (curtype != type)
		changetype(type, 0);
	closefunc = NULL;
	oldintr = NULL;
	oldintp = NULL;
	lmode = "w";
	if (sigsetjmp(sendabort, 1)) {
		while (cpend) {
			(void) getreply(0);
		}
		if (data >= 0) {
			(void) close(data);
			data = -1;
		}
		if (oldintr)
			(void) signal(SIGINT,oldintr);
		if (oldintp)
			(void) signal(SIGPIPE,oldintp);
		code = -1;
		return;
	}
	oldintr = signal(SIGINT, abortsend);
	if (strcmp(local, "-") == 0)
		fin = stdin;
	else if (*local == '|') {
		oldintp = signal(SIGPIPE,SIG_IGN);
		fin = popen(local + 1, "r");
		if (fin == NULL) {
			perror(local + 1);
			(void) signal(SIGINT, oldintr);
			(void) signal(SIGPIPE, oldintp);
			code = -1;
			return;
		}
		closefunc = pclose;
	} else {
		fin = fopen(local, "r");
		if (fin == NULL) {
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
			(void) signal(SIGINT, oldintr);
			code = -1;
			return;
		}
		closefunc = fclose;
		if (fstat(fileno(fin), &st) < 0 ||
		    (st.st_mode&S_IFMT) != S_IFREG) {
			fprintf(stdout, "%s: not a plain file.\n", local);
			(void) signal(SIGINT, oldintr);
			fclose(fin);
			code = -1;
			return;
		}
	}
	if (initconn()) {
		(void) signal(SIGINT, oldintr);
		if (oldintp)
			(void) signal(SIGPIPE, oldintp);
		code = -1;
		if (closefunc != NULL)
			(*closefunc)(fin);
		return;
	}
	if (sigsetjmp(sendabort, 1))
		goto abort;

	if (restart_point &&
	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
		if (fseek(fin, (long) restart_point, 0) < 0) {
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
			restart_point = 0;
			if (closefunc != NULL)
				(*closefunc)(fin);
			return;
		}
		if (command("REST %ld", (long) restart_point)
			!= CONTINUE) {
			restart_point = 0;
			if (closefunc != NULL)
				(*closefunc)(fin);
			return;
		}
		restart_point = 0;
		lmode = "r+w";
	}
	if (remote) {
		if (command("%s %s", cmd, remote) != PRELIM) {
			(void) signal(SIGINT, oldintr);
			if (oldintp)
				(void) signal(SIGPIPE, oldintp);
			if (closefunc != NULL)
				(*closefunc)(fin);
			return;
		}
	} else
		if (command("%s", cmd) != PRELIM) {
			(void) signal(SIGINT, oldintr);
			if (oldintp)
				(void) signal(SIGPIPE, oldintp);
			if (closefunc != NULL)
				(*closefunc)(fin);
			return;
		}
	dout = dataconn(lmode);
	if (dout == NULL)
		goto abort;
	(void) gettimeofday(&start, (struct timezone *)0);
	oldintp = signal(SIGPIPE, SIG_IGN);
	switch (curtype) {

	case TYPE_I:
	case TYPE_L:
		errno = d = 0;
		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
			bytes += c;
			for (bufp = buf; c > 0; c -= d, bufp += d)
				if ((d = local_write(fileno(dout), bufp, c)) <= 0)
					break;
			if (hash) {
				while (bytes >= hashbytes) {
					(void) putchar('#');
					hashbytes += HASHBYTES;
				}
				(void) fflush(stdout);
			}
			if (tick && (bytes >= hashbytes)) {
				printf("\rBytes transferred: %ld", bytes);
				(void) fflush(stdout);
				while (bytes >= hashbytes)
					hashbytes += TICKBYTES;
			}
		}
		if (hash && (bytes > 0)) {
			if (bytes < HASHBYTES)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (tick) {
			(void) printf("\rBytes transferred: %ld\n", bytes);
			(void) fflush(stdout);
		}
		if (c < 0)
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
		if (d < 0) {
			if (errno != EPIPE) 
				perror("netout");
			bytes = -1;
		}
		break;

	case TYPE_A:
		while ((c = getc(fin)) != EOF) {
			if (c == '\n') {
				while (hash && (bytes >= hashbytes)) {
					(void) putchar('#');
					(void) fflush(stdout);
					hashbytes += HASHBYTES;
				}
				if (tick && (bytes >= hashbytes)) {
					(void) printf("\rBytes transferred: %ld",
						bytes);
					(void) fflush(stdout);
					while (bytes >= hashbytes)
						hashbytes += TICKBYTES;
				}
				if (ferror(dout))
					break;
				(void) putc('\r', dout);
				bytes++;
			}
			(void) putc(c, dout);
			bytes++;
	/*		if (c == '\r') {			  	*/
	/*		(void)	putc('\0', dout);  (* this violates rfc */
	/*			bytes++;				*/
	/*		}                          			*/     
		}
		if (hash) {
			if (bytes < hashbytes)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (tick) {
			(void) printf("\rBytes transferred: %ld\n", bytes);
			(void) fflush(stdout);
		}
		if (ferror(fin))
			fprintf(stderr, "local: %s: %s\n", local,
				strerror(errno));
		if (ferror(dout)) {
			if (errno != EPIPE)
				perror("netout");
			bytes = -1;
		}
		break;
	}
	(void) gettimeofday(&stop, (struct timezone *)0);
	if (closefunc != NULL)
		(*closefunc)(fin);
	(void) fclose(dout);
	/* closes data as well, so discard it */
	data = -1;
	(void) getreply(0);
	(void) signal(SIGINT, oldintr);
	if (oldintp)
		(void) signal(SIGPIPE, oldintp);
	if (bytes > 0)
		ptransfer("sent", bytes, &start, &stop);
	return;
abort:
	(void) gettimeofday(&stop, (struct timezone *)0);
	(void) signal(SIGINT, oldintr);
	if (oldintp)
		(void) signal(SIGPIPE, oldintp);
	if (!cpend) {
		code = -1;
		return;
	}
	if (dout) {
		(void) fclose(dout);
	}
	if (data >= 0) {
		/* if it just got closed with dout, again won't hurt */
		(void) close(data);
		data = -1;
	}
	(void) getreply(0);
	code = -1;
	if (closefunc != NULL && fin != NULL)
		(*closefunc)(fin);
	if (bytes > 0)
		ptransfer("sent", bytes, &start, &stop);
}
Пример #30
0
char *
hookup(char *host, int port)
{
	register struct hostent *hp = 0;
	int s, tos;
	socklen_t len;
	static char hostnamebuf[256];

	memset(&hisctladdr, 0, sizeof(hisctladdr));
	if (inet_aton(host, &hisctladdr.sin_addr)) {
		hisctladdr.sin_family = AF_INET;
		strncpy(hostnamebuf, host, sizeof(hostnamebuf));
		hostnamebuf[sizeof(hostnamebuf)-1]=0;
	} 
	else {
		hp = gethostbyname(host);
		if (hp == NULL) {
			fprintf(stderr, "ftp: %s: ", host);
#ifndef EMBED
			herror((char *)NULL);
#endif
			code = -1;
			return((char *) 0);
		}
		hisctladdr.sin_family = hp->h_addrtype;
		if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) {
			hp->h_length = sizeof(hisctladdr.sin_addr);
		}
		memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length);
		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
		hostnamebuf[sizeof(hostnamebuf)-1] = 0;
	}
	hostname = hostnamebuf;
	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
	if (s < 0) {
		perror("ftp: socket");
		code = -1;
		return (0);
	}
	hisctladdr.sin_port = port;
	while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
		if (hp && hp->h_addr_list[1]) {
			int oerrno = errno;

			fprintf(stderr, "ftp: connect to address %s: ",
				inet_ntoa(hisctladdr.sin_addr));
			errno = oerrno;
			perror((char *) 0);
			hp->h_addr_list++;
			memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], 
			       hp->h_length);
			fprintf(stdout, "Trying %s...\n",
				inet_ntoa(hisctladdr.sin_addr));
			(void) close(s);
			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
			if (s < 0) {
				perror("ftp: socket");
				code = -1;
				return (0);
			}
			continue;
		}
		perror("ftp: connect");
		code = -1;
		goto bad;
	}
	len = sizeof (myctladdr);
	if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
		perror("ftp: getsockname");
		code = -1;
		goto bad;
	}
#ifdef IP_TOS
	tos = IPTOS_LOWDELAY;
	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
		perror("ftp: setsockopt TOS (ignored)");
#endif
	cin = fdopen(s, "r");
	cout = fdopen(s, "w");
	if (cin == NULL || cout == NULL) {
		fprintf(stderr, "ftp: fdopen failed.\n");
		if (cin)
			(void) fclose(cin);
		if (cout)
			(void) fclose(cout);
		code = -1;
		goto bad;
	}
	if (ftpverbose)
		printf("Connected to %s.\n", hostname);
	if (getreply(0) > 2) { 	/* read startup message from server */
		if (cin)
			(void) fclose(cin);
		if (cout)
			(void) fclose(cout);
		code = -1;
		goto bad;
	}
#ifdef SO_OOBINLINE
	{
	int on = 1;

	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
		< 0 && debug) {
			perror("ftp: setsockopt");
		}
	}
#endif /* SO_OOBINLINE */

	return (hostname);
bad:
	(void) close(s);
	return ((char *)0);
}