Example #1
0
/*
 * Establish a TCP connection to the specified port on the specified host.
 */
conn_t *
fetch_connect(struct url *url, int af, int verbose)
{
	conn_t *conn;
	char pbuf[10];
	const char *bindaddr;
	struct addrinfo hints, *res, *res0;
	int sd, error;

	if (verbose)
		fetch_info("looking up %s", url->host);

	/* look up host name and set up socket address structure */
	snprintf(pbuf, sizeof(pbuf), "%d", url->port);
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = af;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = 0;
	if ((error = getaddrinfo(url->host, pbuf, &hints, &res0)) != 0) {
		netdb_seterr(error);
		return (NULL);
	}
	bindaddr = getenv("FETCH_BIND_ADDRESS");

	if (verbose)
		fetch_info("connecting to %s:%d", url->host, url->port);

	/* try to connect */
	for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
		if ((sd = socket(res->ai_family, res->ai_socktype,
			 res->ai_protocol)) == -1)
			continue;
		if (bindaddr != NULL && *bindaddr != '\0' &&
		    fetch_bind(sd, res->ai_family, bindaddr) != 0) {
			fetch_info("failed to bind to '%s'", bindaddr);
			close(sd);
			continue;
		}
		if (connect(sd, res->ai_addr, res->ai_addrlen) == 0)
			break;
		close(sd);
	}
	freeaddrinfo(res0);
	if (sd == -1) {
		fetch_syserr();
		return (NULL);
	}

	if ((conn = fetch_reopen(sd)) == NULL) {
		fetch_syserr();
		close(sd);
		return (NULL);
	}
	conn->cache_url = fetchCopyURL(url);
	conn->cache_af = af;
	return (conn);
}
Example #2
0
 void InvalLoader::fetch_cluster_infos()
 {
   log_info("start loading groupnames.");
   //collect all group names
   const char* p_cluster_list = TBSYS_CONFIG.getString(INVALSERVER_SECTION, "cluster_list", NULL);
   if (p_cluster_list != NULL)
   {
     //get the cluster name list from the config file
     vector<std::string> cluster_name_list;
     parse_cluster_list(p_cluster_list, cluster_name_list);
     for (size_t i = 0; i < cluster_name_list.size(); ++i)
     {
       //fetch info for cluster
       fetch_info(cluster_name_list[i]);
     }
   }
 }
Example #3
0
/*
 * Get authentication data for a URL from .netrc
 */
int
fetch_netrc_auth(struct url *url)
{
	char fn[PATH_MAX];
	const char *word;
	char *p;
	FILE *f;

	if ((p = getenv("NETRC")) != NULL) {
		if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
			fetch_info("$NETRC specifies a file name "
			    "longer than PATH_MAX");
			return (-1);
		}
	} else {
		if ((p = getenv("HOME")) != NULL) {
			struct passwd *pwd;

			if ((pwd = getpwuid(getuid())) == NULL ||
			    (p = pwd->pw_dir) == NULL)
				return (-1);
		}
		if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn))
			return (-1);
	}

	if ((f = fopen(fn, "r")) == NULL)
		return (-1);
	while ((word = fetch_read_word(f)) != NULL) {
		if (strcmp(word, "default") == 0)
			break;
		if (strcmp(word, "machine") == 0 &&
		    (word = fetch_read_word(f)) != NULL &&
		    strcasecmp(word, url->host) == 0) {
			break;
		}
	}
	if (word == NULL)
		goto ferr;
	while ((word = fetch_read_word(f)) != NULL) {
		if (strcmp(word, "login") == 0) {
			if ((word = fetch_read_word(f)) == NULL)
				goto ferr;
			if (snprintf(url->user, sizeof(url->user),
				"%s", word) > (int)sizeof(url->user)) {
				fetch_info("login name in .netrc is too long");
				url->user[0] = '\0';
			}
		} else if (strcmp(word, "password") == 0) {
			if ((word = fetch_read_word(f)) == NULL)
				goto ferr;
			if (snprintf(url->pwd, sizeof(url->pwd),
				"%s", word) > (int)sizeof(url->pwd)) {
				fetch_info("password in .netrc is too long");
				url->pwd[0] = '\0';
			}
		} else if (strcmp(word, "account") == 0) {
			if ((word = fetch_read_word(f)) == NULL)
				goto ferr;
			/* XXX not supported! */
		} else {
			break;
		}
	}
	fclose(f);
	return (0);
 ferr:
	fclose(f);
	return (-1);
}
Example #4
0
/*
 * Transfer file
 */
static fetchIO *
ftp_transfer(conn_t *conn, const char *oper, const char *file, const char *op_arg,
    int mode, off_t offset, const char *flags)
{
	union anonymous {
		struct sockaddr_storage ss;
		struct sockaddr sa;
		struct sockaddr_in6 sin6;
		struct sockaddr_in sin4;
	} u;
	const char *bindaddr;
	const char *filename;
	int filenamelen, type;
	int pasv, verbose;
	int e, sd = -1;
	socklen_t l;
	char *s;
	fetchIO *df;

	/* check flags */
	pasv = !CHECK_FLAG('a');
	verbose = CHECK_FLAG('v');

	/* passive mode */
	if (!pasv)
		pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
		    strncasecmp(s, "no", 2) != 0);

	/* isolate filename */
	filename = ftp_filename(file, &filenamelen, &type, op_arg != NULL);

	/* set transfer mode and data type */
	if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK)
		goto ouch;

	/* find our own address, bind, and listen */
	l = sizeof(u.ss);
	if (getsockname(conn->sd, &u.sa, &l) == -1)
		goto sysouch;
	if (u.ss.ss_family == AF_INET6)
		unmappedaddr(&u.sin6, &l);

retry_mode:

	/* open data socket */
	if ((sd = socket(u.ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
		fetch_syserr();
		return (NULL);
	}

	if (pasv) {
		unsigned char addr[64];
		char *ln, *p;
		unsigned int i;
		int port;

		/* send PASV command */
		if (verbose)
			fetch_info("setting passive mode");
		switch (u.ss.ss_family) {
		case AF_INET:
			if ((e = ftp_cmd(conn, "PASV\r\n")) != FTP_PASSIVE_MODE)
				goto ouch;
			break;
		case AF_INET6:
			if ((e = ftp_cmd(conn, "EPSV\r\n")) != FTP_EPASSIVE_MODE) {
				if (e == -1)
					goto ouch;
				if ((e = ftp_cmd(conn, "LPSV\r\n")) !=
				    FTP_LPASSIVE_MODE)
					goto ouch;
			}
			break;
		default:
			e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */
			goto ouch;
		}

		/*
		 * Find address and port number. The reply to the PASV command
		 * is IMHO the one and only weak point in the FTP protocol.
		 */
		ln = conn->buf;
		switch (e) {
		case FTP_PASSIVE_MODE:
		case FTP_LPASSIVE_MODE:
			for (p = ln + 3; *p && !isdigit((unsigned char)*p); p++)
				/* nothing */ ;
			if (!*p) {
				e = FTP_PROTOCOL_ERROR;
				goto ouch;
			}
			l = (e == FTP_PASSIVE_MODE ? 6 : 21);
			for (i = 0; *p && i < l; i++, p++)
				addr[i] = strtol(p, &p, 10);
			if (i < l) {
				e = FTP_PROTOCOL_ERROR;
				goto ouch;
			}
			break;
		case FTP_EPASSIVE_MODE:
			for (p = ln + 3; *p && *p != '('; p++)
				/* nothing */ ;
			if (!*p) {
				e = FTP_PROTOCOL_ERROR;
				goto ouch;
			}
			++p;
			if (sscanf(p, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2],
				&port, &addr[3]) != 5 ||
			    addr[0] != addr[1] ||
			    addr[0] != addr[2] || addr[0] != addr[3]) {
				e = FTP_PROTOCOL_ERROR;
				goto ouch;
			}
			break;
		case FTP_SYNTAX_ERROR:
			if (verbose)
				fetch_info("passive mode failed");
			/* Close socket and retry with passive mode. */
			pasv = 0;
			close(sd);
			sd = -1;
			goto retry_mode;
		}

		/* seek to required offset */
		if (offset)
			if (ftp_cmd(conn, "REST %lu\r\n", (unsigned long)offset) != FTP_FILE_OK)
				goto sysouch;

		/* construct sockaddr for data socket */
		l = sizeof(u.ss);
		if (getpeername(conn->sd, &u.sa, &l) == -1)
			goto sysouch;
		if (u.ss.ss_family == AF_INET6)
			unmappedaddr(&u.sin6, &l);
		switch (u.ss.ss_family) {
		case AF_INET6:
			if (e == FTP_EPASSIVE_MODE)
				u.sin6.sin6_port = htons(port);
			else {
				memcpy(&u.sin6.sin6_addr, addr + 2, 16);
				memcpy(&u.sin6.sin6_port, addr + 19, 2);
			}
			break;
		case AF_INET:
			if (e == FTP_EPASSIVE_MODE)
				u.sin4.sin_port = htons(port);
			else {
				memcpy(&u.sin4.sin_addr, addr, 4);
				memcpy(&u.sin4.sin_port, addr + 4, 2);
			}
			break;
		default:
			e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */
			break;
		}

		/* connect to data port */
		if (verbose)
			fetch_info("opening data connection");
		bindaddr = getenv("FETCH_BIND_ADDRESS");
		if (bindaddr != NULL && *bindaddr != '\0' &&
		    fetch_bind(sd, u.ss.ss_family, bindaddr) != 0)
			goto sysouch;
		if (connect(sd, &u.sa, l) == -1)
			goto sysouch;

		/* make the server initiate the transfer */
		if (verbose)
			fetch_info("initiating transfer");
		if (op_arg)
			e = ftp_cmd(conn, "%s%s%s\r\n", oper, *op_arg ? " " : "", op_arg);
		else
			e = ftp_cmd(conn, "%s %.*s\r\n", oper,
			    (int)filenamelen, filename);
		if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
			goto ouch;

	} else {
		uint32_t a;
		uint16_t p;
#if defined(IPV6_PORTRANGE) || defined(IP_PORTRANGE)
		int arg;
		int low = CHECK_FLAG('l');
#endif
		int d;
		char hname[INET6_ADDRSTRLEN];

		switch (u.ss.ss_family) {
		case AF_INET6:
			u.sin6.sin6_port = 0;
#ifdef IPV6_PORTRANGE
			arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
			if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
				(char *)&arg, sizeof(arg)) == -1)
				goto sysouch;
#endif
			break;
		case AF_INET:
			u.sin4.sin_port = 0;
#ifdef IP_PORTRANGE
			arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
			if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
				(char *)&arg, sizeof(arg)) == -1)
				goto sysouch;
#endif
			break;
		}
		if (verbose)
			fetch_info("binding data socket");
		if (bind(sd, &u.sa, l) == -1)
			goto sysouch;
		if (listen(sd, 1) == -1)
			goto sysouch;

		/* find what port we're on and tell the server */
		if (getsockname(sd, &u.sa, &l) == -1)
			goto sysouch;
		switch (u.ss.ss_family) {
		case AF_INET:
			a = ntohl(u.sin4.sin_addr.s_addr);
			p = ntohs(u.sin4.sin_port);
			e = ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d\r\n",
			    (a >> 24) & 0xff, (a >> 16) & 0xff,
			    (a >> 8) & 0xff, a & 0xff,
			    (p >> 8) & 0xff, p & 0xff);
			break;
		case AF_INET6:
			e = -1;
			u.sin6.sin6_scope_id = 0;
			if (getnameinfo(&u.sa, l,
				hname, sizeof(hname),
				NULL, 0, NI_NUMERICHOST) == 0) {
				e = ftp_cmd(conn, "EPRT |%d|%s|%d|\r\n", 2, hname,
				    htons(u.sin6.sin6_port));
				if (e == -1)
					goto ouch;
			}
			if (e != FTP_OK) {
				unsigned char *ap = (void *)&u.sin6.sin6_addr.s6_addr;
				uint16_t port = ntohs(u.sin6.sin6_port);
				e = ftp_cmd(conn,
				    "LPRT %d,%d,%u,%u,%u,%u,%u,%u,%u,%u,"
				    "%u,%u,%u,%u,%u,%u,%u,%u,%d,%d,%d\r\n",
				    6, 16,
				    (unsigned)ap[0], (unsigned)ap[1],
				    (unsigned)ap[2], (unsigned)ap[3],
				    (unsigned)ap[4], (unsigned)ap[5],
				    (unsigned)ap[6], (unsigned)ap[7],
				    (unsigned)ap[8], (unsigned)ap[9],
				    (unsigned)ap[10], (unsigned)ap[11],
				    (unsigned)ap[12], (unsigned)ap[13],
				    (unsigned)ap[14], (unsigned)ap[15],
				    2, port >> 8, port & 0xff);
			}
			break;
		default:
			e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */
			goto ouch;
		}
		if (e != FTP_OK)
			goto ouch;

		/* seek to required offset */
		if (offset)
			if (ftp_cmd(conn, "REST %llu\r\n", (unsigned long long)offset) != FTP_FILE_OK)
				goto sysouch;

		/* make the server initiate the transfer */
		if (verbose)
			fetch_info("initiating transfer");
		if (op_arg)
			e = ftp_cmd(conn, "%s%s%s\r\n", oper, *op_arg ? " " : "", op_arg);
		else
			e = ftp_cmd(conn, "%s %.*s\r\n", oper,
			    (int)filenamelen, filename);
		if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
			goto ouch;

		/* accept the incoming connection and go to town */
		if ((d = accept(sd, NULL, NULL)) == -1)
			goto sysouch;
		close(sd);
		sd = d;
	}