Example #1
0
/* set to NULL if not needed */
int urlinstStartTransfer(struct iurlinfo * ui, char * filename, 
                         char *extraHeaders) {
    char * buf;
    int fd, port;
    int family = -1;
    char * finalPrefix;
    struct in_addr addr;
    struct in6_addr addr6;
    char *hostname, *portstr;

    if (!strcmp(ui->prefix, "/"))
        finalPrefix = "";
    else
        finalPrefix = ui->prefix;

    buf = alloca(strlen(finalPrefix) + strlen(filename) + 20);
    if (*filename == '/')
        sprintf(buf, "%s%s", finalPrefix, filename);
    else
        sprintf(buf, "%s/%s", finalPrefix, filename);
    
    logMessage(INFO, "transferring %s://%s/%s to a fd",
               ui->protocol == URL_METHOD_FTP ? "ftp" : "http",
               ui->address, buf);

    splitHostname(ui->address, &hostname, &portstr);
    if (portstr == NULL)
        port = -1;
    else
        port = atoi(portstr);

    if (inet_pton(AF_INET, hostname, &addr) >= 1)
        family = AF_INET;
    else if (inet_pton(AF_INET6, hostname, &addr6) >= 1)
        family = AF_INET6;
    else {
        if (mygethostbyname(hostname, &addr, AF_INET) == 0) {
            family = AF_INET;
        } else if (mygethostbyname(hostname, &addr6, AF_INET6) == 0) {
            family = AF_INET6;
        } else {
            logMessage(ERROR, "cannot determine address family of %s",
                       hostname);
        }
    }

    if (ui->protocol == URL_METHOD_FTP) {
        ui->ftpPort = ftpOpen(hostname, family,
                              ui->login ? ui->login : "******", 
                              ui->password ? ui->password : "******", 
                              NULL, port);
        if (ui->ftpPort < 0)
            return -2;

        fd = ftpGetFileDesc(ui->ftpPort, addr6, family, buf);
        if (fd < 0) {
            close(ui->ftpPort);
            return -1;
        }
    } else {
#ifdef	ROCKS
	{
		/*
		 * try harder to start HTTP transfer
		 */
		int	tries = 1;
		int	rc;

		logMessage(INFO, "ROCKS:urlinstStartTransfer:http://%s/%s\n"
			"Headers:%s\n",
			ui->address, filename, extraHeaders);
		fd = -1;

		while ((fd < 0) && (tries < 10)) {
			fd = httpGetFileDesc(ui->address, -1, buf,
				extraHeaders);
			if (fd == FTPERR_FAILED_DATA_CONNECT) {
				/* Server busy, backoff */
				sleep(60);
				tries = 1;
				continue;
			}

			logMessage(INFO,
				"ROCKS:urlinstStartTransfer:attempt (%d)",
				tries);

			sleep(1);

			++tries;
		}

		if (fd < 0) {
			logMessage(ERROR, "ROCKS:urlinstStartTransfer:Failed");
			rc = newtWinChoice(_("GET File Error"), 
				_("Retry"), _("Cancel"), 
				_("Could not get file:\n\nhttp://%s/%s\n\n%s"), 
				ui->address, filename, 
				ftpStrerror(fd, URL_METHOD_HTTP));
			if (rc == 1)
				return urlinstStartTransfer(ui, filename,
					extraHeaders);
			else	
				return -1;
		}
	}
#else
        fd = httpGetFileDesc(hostname, port, buf, extraHeaders);
        if (fd < 0)
            return -1;
#endif /* ROCKS */
    }

    if (!FL_CMDLINE(flags))
        winStatus(70, 3, _("Retrieving"), "%s %s...", _("Retrieving"), 
                  filename);

    return fd;
}
Example #2
0
BIO *
httpsGetFileDesc(char * hostname, int port, char * remotename,
	char *extraHeaders, int *errorcode, char **returnedHeaders) 
{
	char *buf;
	char headers[4096];
	char *nextChar = headers;
	char *hstr;
	int sock;
	int rc;
	int checkedCode;
	int headerslen;

	int bufsize;
	int byteswritten;
	struct loaderData_s * loaderData;
	SSL_CTX *ssl_context;
	SSL *ssl;
	BIO *sbio = 0;
	X509 *server_cert;

	*errorcode = 0;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock < 0) {
		logMessage(ERROR,
			"ROCKS:httpsGetFileDesc:Could not get a socket");
		*errorcode = FTPERR_FAILED_CONNECT;
		return NULL;
	}

	/* OpenSSL_add_all_algorithms(); */
	SSLeay_add_ssl_algorithms();

	ssl_context = SSL_CTX_new(SSLv23_client_method());
	if (!ssl_context) {
		logMessage(ERROR, "Could not create SSLv2,3 context");
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	/* Pull in the Global Loader Data structure. */
	loaderData = rocks_global_loaderData;

	/* I have a Certificate */
	if (loaderData->cert_filename) {
		rc = SSL_CTX_use_certificate_file(ssl_context, 
			loaderData->cert_filename,
			SSL_FILETYPE_PEM);
		if (!rc) {
			logMessage(ERROR, "Could not read Cluster Certificate");
			*errorcode = FTPERR_CLIENT_SECURITY;
			goto error;
		}

		rc = SSL_CTX_use_PrivateKey_file(ssl_context, 
			loaderData->priv_filename,
			SSL_FILETYPE_PEM);
		if (!rc) {
			logMessage(ERROR,
				"Could not read Cluster cert private key");
			*errorcode = FTPERR_CLIENT_SECURITY;
			goto error;
		}

		/* Only connect to servers that have certs signed by
		 * our trusted CA. */
		if (loaderData->authParent) {
			rc = SSL_CTX_load_verify_locations(ssl_context,
				loaderData->ca_filename, 0);
			if (!rc) {
				logMessage(ERROR,
					"Could not read Server CA cert");
				*errorcode = FTPERR_CLIENT_SECURITY;
				goto error;
			}
			SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, 0);
			SSL_CTX_set_verify_depth(ssl_context, 1);
		}
	}

	sbio = BIO_new_ssl_connect(ssl_context);
	if (!sbio) {
		logMessage(ERROR, "Could not create SSL object");
		*errorcode = FTPERR_CLIENT_SECURITY;
		goto error;
	}

	BIO_get_ssl(sbio, &ssl);
	if (!ssl) {
		logMessage(ERROR, "Could not find ssl pointer.");
		*errorcode = FTPERR_CLIENT_SECURITY;
		goto error;
	}

	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

	BIO_set_conn_hostname(sbio, hostname);
	BIO_set_conn_port(sbio, "https");

	rc = BIO_do_connect(sbio);
	if (rc<=0) {
		rc = SSL_get_verify_result(ssl);
		if (rc) {
			logMessage(ERROR, "Could not verify %s's identity",
				hostname);	
			*errorcode = FTPERR_REFUSED;
			goto error;
		}
		logMessage(ERROR, "Could not connect to %s:https", hostname);
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	rc = BIO_do_handshake(sbio);
	if (rc<=0) {
		logMessage(ERROR,
			"Could not establish HTTPS connection with %s", 
			hostname);
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	server_cert = SSL_get_peer_certificate(ssl);

	/* Show credentials if appropriate. */
	/* Don't Show Credentials */
	if ( (0 == 1)  && !loaderData->cert_filename 
			&& !loaderData->ekv
			&& !loaderData->dropCert) {

		rc = show_cert(server_cert);
		if (rc != 1) {
			*errorcode = FTPERR_REFUSED;
			goto error;
		}
	}

	if (extraHeaders)
		hstr = extraHeaders;
	else
		hstr = "";

	bufsize = strlen(remotename) + strlen(hostname) + strlen(hstr) + 30;

	if ((buf = malloc(bufsize)) == NULL) {
			logMessage(ERROR,
				"ROCKS:httpsGetFileDesc:malloc failed");
			*errorcode = FTPERR_FAILED_CONNECT;
			goto error;
	}

	sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s\r\n", remotename, 
		hostname, hstr);

	byteswritten = BIO_puts(sbio, buf);

	logMessage(INFO,
		"ROCKS:httpsGetFileDesc:byteswritten(%d)", byteswritten);
	logMessage(INFO,
		"ROCKS:httpsGetFileDesc:bufsize(%d)", (int)strlen(buf));

	free(buf);

	/* This is fun; read the response a character at a time until we:
	1) Get our first \r\n; which lets us check the return code
	2) Get a \r\n\r\n, which means we're done */

	*nextChar = '\0';
	checkedCode = 0;
	headerslen = 0;
	while (!strstr(headers, "\r\n\r\n")) {

		if (BIO_read(sbio, nextChar, 1) != 1) {
			*errorcode = FTPERR_SERVER_SECURITY;
			goto error;
		}

		nextChar++;
		*nextChar = '\0';
		++headerslen;

		if (nextChar - headers == sizeof(headers)) {
			goto error;
		}

		if (!checkedCode && strstr(headers, "\r\n")) {
			char * start, * end;

			checkedCode = 1;
			start = headers;
			while (!isspace(*start) && *start) start++;
			if (!*start) {
				goto error;
			}

			while (isspace(*start) && *start) start++;

			end = start;
			while (!isspace(*end) && *end) end++;
			if (!*end) {
				goto error;
			}

			logMessage(INFO,
				"ROCKS:httpsGetFileDesc:status %s.", start);

			*end = '\0';
			if (!strcmp(start, "404"))
				goto error;
			else if (!strcmp(start, "403")) {
				*errorcode = FTPERR_SERVER_SECURITY;
				goto error;
			}
			else if (!strcmp(start, "503")) {
				/* A server nack - busy */
				logMessage(WARNING, "ROCKS:server busy");
				watchdog_reset();
				*errorcode = FTPERR_FAILED_DATA_CONNECT;
				goto error;
			}
			else if (strcmp(start, "200")) {
				*errorcode = FTPERR_BAD_SERVER_RESPONSE;
				goto error;
			}

			*end = ' ';
		}
	}

	if ((*returnedHeaders = (char *)malloc(headerslen + 1)) != NULL) {
		memcpy(*returnedHeaders, headers, headerslen + 1);
	}

	return sbio;

error:
	close(sock);
	if (sbio)
		BIO_free_all(sbio);
	if (!*errorcode)
		*errorcode = FTPERR_SERVER_IO_ERROR;
	logMessage(ERROR, "ROCKS:httpsGetFileDesc:Error %s", 
		ftpStrerror(*errorcode, URL_METHOD_HTTP));
	return NULL;
}
Example #3
0
/* Use SSL. Must be entirely different since the return
 * type is a pointer to an SSL structure.
 */
BIO *
urlinstStartSSLTransfer(struct iurlinfo * ui, char * filename, 
                         char *extraHeaders, int silentErrors,
                         int flags, char *nextServer) {

	extern  void watchdog_reset();
	int	tries = 1;
	int	rc;
	int	errorcode = -1;
	int	sleepmin = KS_RETRY_MIN;
	char	*returnedHeaders;
	BIO	*sbio = 0;

	logMessage(INFO, "ROCKS:transferring https://%s/%s\nHeaders:%s\n",
	       ui->address, filename, extraHeaders);

	/* Add 'public' path element if we dont have a cert. */
	if (!haveCertificate())
		addPublic(&filename);

	while ((errorcode < 0) && (tries < 10)) {
		sbio = httpsGetFileDesc(ui->address, -1, filename,
			extraHeaders, &errorcode, &returnedHeaders);

		if (errorcode == 0) {
			char	*ptr;
			char	trackers[256];
			char	pkgservers[256];

			if ((ptr = strstr(returnedHeaders,
					"X-Avalanche-Trackers:")) != NULL) {
				sscanf(ptr, "X-Avalanche-Trackers: %256s",
					trackers);
			} else {
				if (nextServer != NULL) {
					snprintf(trackers, sizeof(trackers) - 1,
						"%s", nextServer);
				} else {
					strcpy(trackers, "127.0.0.1");
				}
			}

			if ((ptr = strstr(returnedHeaders,
					"X-Avalanche-Pkg-Servers:")) != NULL) {
				sscanf(ptr, "X-Avalanche-Pkg-Servers: %256s",
					pkgservers);
			} else {
				if (nextServer != NULL) {
					snprintf(pkgservers,
						sizeof(pkgservers) - 1, "%s",
						nextServer);
				} else {
					strcpy(pkgservers, "127.0.0.1");
				}
			}

			writeAvalancheInfo(trackers, pkgservers);

		} else if (errorcode == FTPERR_FAILED_DATA_CONNECT) {
			/*
			 * read the retry value from the return message
			 */
			char	*ptr;
			int	sleeptime = 0;

			if ((ptr = strstr(returnedHeaders, "Retry-After:"))
					!= NULL) {
				sscanf(ptr, "Retry-After: %d", &sleeptime);
			}

			if (sleeptime <= 0) {
				/*
				 * Backoff a random interval between
				 * KS_RETRY_MIN and KS_RETRY_MAX
				 */
				sleeptime = sleepmin +
					((KS_RETRY_MAX - sleepmin) *
					(rand()/(float)RAND_MAX));
			}

			winStatus(55, 3, _("Server Busy"), _("I will retry "
				"for a ks file after a %d sec sleep..."), 
				sleeptime, 0);

			/*
			 * this must be in a loop, as the alarm associated
			 * with the watchdog timer is sending a signal which
			 * interrupts the sleep().
			 */
			while ((sleeptime = sleep(sleeptime)) != 0) {
				;
			}

			newtPopWindow();

			tries = 1;
			/* Don't let the watchdog fire if the kickstart
			   server is reporting busy */
			watchdog_reset();
			continue;
		} else if (errorcode == FTPERR_REFUSED) {
			/*
			 * always accept the parent credentials
			 */
			forceParentAuth();
			continue;
		}

		logMessage(INFO, "ROCKS:urlinstStartSSLTransfer:attempt (%d)",
			tries);

		sleep(1);

		++tries;
	}

	if (errorcode < 0) {
		logMessage(ERROR, "ROCKS:urlinstStartSSLTransfer:Failed");
		rc = 0;

		/* Go through the public door automatically, but only
		 * if we have not tried it already. */
		if (errorcode == FTPERR_SERVER_SECURITY && !addPublic(&filename)) {
			rc = 1;
		}
		else {
			rc = newtWinChoice(_("GET File Error"), 
				_("Retry"), _("Cancel"), 
				_("Could not get file:\n\nhttps://%s/%s\n\n%s"),
				ui->address, filename, 
				ftpStrerror(errorcode, URL_METHOD_HTTP));
		}
		if (rc==1) 	/* Retry */
			return urlinstStartSSLTransfer(ui, filename,
				extraHeaders, silentErrors, flags, nextServer);
		else	/* Cancel */
			return NULL;
	}

	if (!FL_CMDLINE(flags))
		winStatus(70, 3, _("Retrieving"), "%s %.*s...", 
			_("Retrieving"), 60, filename);

	return sbio;
}
Example #4
0
/**
 * Check that all sources/patches/icons exist locally, fetching if necessary.
 */
static int prepFetch(Spec spec)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
{
#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    const char *Smacro;
#endif
    const char *Lmacro, *Lurlfn = NULL;
    const char *Rmacro, *Rurlfn = NULL;
    struct Source *sp;
    struct stat st;
    rpmRC rpmrc;
    int ec, rc;
    char *cp;

    /* XXX insure that %{_sourcedir} exists */
    rpmrc = RPMRC_OK;
    Lurlfn = rpmGenPath(NULL, "%{?_sourcedir}", NULL);
    if (Lurlfn != NULL && *Lurlfn != '\0')
	rpmrc = rpmMkdirPath(Lurlfn, "_sourcedir");
    Lurlfn = _free(Lurlfn);
    if (rpmrc != RPMRC_OK)
	return -1;

    /* XXX insure that %{_patchdir} exists */
    rpmrc = RPMRC_OK;
    Lurlfn = rpmGenPath(NULL, "%{?_patchdir}", NULL);
    if (Lurlfn != NULL && *Lurlfn != '\0')
	rpmrc = rpmMkdirPath(Lurlfn, "_patchdir");
    Lurlfn = _free(Lurlfn);
    if (rpmrc != RPMRC_OK)
	return -1;

    /* XXX insure that %{_icondir} exists */
    rpmrc = RPMRC_OK;
    Lurlfn = rpmGenPath(NULL, "%{?_icondir}", NULL);
    if (Lurlfn != NULL && *Lurlfn != '\0')
	rpmrc = rpmMkdirPath(Lurlfn, "_icondir");
    Lurlfn = _free(Lurlfn);
    if (rpmrc != RPMRC_OK)
	return -1;

    if (rpmIsVerbose() && !quietly && (rpmBTArgs.buildAmount & RPMBUILD_FETCHSOURCE))
        rpmlog(RPMLOG_NOTICE, "Checking source and patch file(s):\n");

    ec = 0;
    for (sp = spec->sources; sp != NULL; sp = sp->next) {

#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
	Smacro = "%{?_specdir}/";
#endif
#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    if (! (Lmacro = getSourceDir(sp->flags, sp->source)))
#else
    if (! (Lmacro = getSourceDir(sp->flags)))
#endif
        continue;
	if (sp->flags & RPMFILE_SOURCE) {
	    Rmacro = "%{?_Rsourcedir}/";
	} else
	if (sp->flags & RPMFILE_PATCH) {
	    Rmacro = "%{?_Rpatchdir}/";
	} else
	if (sp->flags & RPMFILE_ICON) {
	    Rmacro = "%{?_Ricondir}/";
	} else
	    continue;

#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
	/* support splitted source directories, i.e., source files which
	   are alternatively placed into the .spec directory and picked
	   up from there, too. */
	Lurlfn = rpmGenPath(NULL, Smacro, sp->source);
	rc = Lstat(Lurlfn, &st);
	if (rc == 0) {
            prepFetchVerbose(sp, &st);
	    goto bottom;
        }
#endif
	Lurlfn = rpmGenPath(NULL, Lmacro, sp->source);
	rc = Lstat(Lurlfn, &st);
	if (rc == 0) {
/*@-noeffect@*/
            prepFetchVerbose(sp, &st);
/*@=noeffect@*/
	    goto bottom;
        }
/*@-noeffect@*/
        prepFetchVerbose(sp, NULL);
/*@=noeffect@*/
	if (errno != ENOENT) {
	    ec++;
	    rpmlog(RPMLOG_ERR, _("Missing %s%d %s: %s\n"),
		((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
		sp->num, sp->source, strerror(ENOENT));
	    goto bottom;
	}

        /* try to fetch via macro-controlled remote locations */
        cp = rpmExpand(Rmacro, NULL);
        if (cp != NULL && strcmp(cp, "/") != 0) {
            cp = _free(cp);
            Rurlfn = rpmGenPath(NULL, Rmacro, sp->source);
            if (!(Rurlfn == NULL || Rurlfn[0] == '\0' || !strcmp(Rurlfn, "/") || !strcmp(Lurlfn, Rurlfn))) {
                rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
                       (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, Rurlfn);
                rc = urlGetFile(Rurlfn, Lurlfn);
                if (rc == 0)
                    goto bottom;
                else {
                    rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
                           (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
                    ec++;
                }
            }
        }
        cp = _free(cp);

        /* try to fetch from original location */
        rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
               (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, sp->fullSource);
        rc = urlGetFile(sp->fullSource, Lurlfn);
        if (rc == 0)
            goto bottom;
        else {
            rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
                   (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
            ec++;
        }

        rpmlog(RPMLOG_ERR, _("Missing %s%d: %s: %s\n"),
            ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
            sp->num, sp->source, strerror(ENOENT));
        ec++;

bottom:
	Lurlfn = _free(Lurlfn);
	Rurlfn = _free(Rurlfn);
    }

    return ec;
}