Ejemplo n.º 1
0
INT64_T http_fetch_to_file(const char *url, const char *filename, time_t stoptime)
{
	FILE *file;
	INT64_T size;
	INT64_T actual;
	struct link *link;

	file = fopen(filename, "w");
	if(file) {
		link = http_query_size(url, "GET", &size, stoptime, 1);
		if(link) {
			actual = link_stream_to_file(link, file, size, stoptime);
			link_close(link);
			fclose(file);
			if(actual == size) {
				return actual;
			} else {
				unlink(filename);
				return -1;
			}
		} else {
			fclose(file);
			return -1;
		}
	} else {
		return -1;
	}

}
Ejemplo n.º 2
0
INT64_T chirp_client_getfile(struct chirp_client * c, const char *path, FILE * stream, time_t stoptime)
{
	INT64_T length;

	char safepath[CHIRP_LINE_MAX];
	url_encode(path, safepath, sizeof(safepath));

	length = simple_command(c, stoptime, "getfile %s\n", safepath);

	if(length >= 0) {
		if(link_stream_to_file(c->link, stream, length, stoptime) == length) {
			return length;
		} else {
			c->broken = 1;
			errno = ECONNRESET;
		}
	}

	return -1;
}
Ejemplo n.º 3
0
static int auth_ticket_assert(struct link *link, time_t stoptime)
{
	/* FIXME need to save errno ? */
	char line[AUTH_LINE_MAX];
	char **tickets = client_tickets;

	if(tickets) {
		char *ticket;
		char digest[DIGEST_LENGTH];

		for (ticket = *tickets; ticket; ticket = *(++tickets)) {
			if (access(ticket, R_OK) == -1) {
				debug(D_AUTH, "could not access ticket %s: %s", ticket, strerror(errno));
				continue;
			}

			/* load the digest */
			/* WARNING: openssl is *very* bad at giving sensible output. Use the last
			 * 32 non-space characters as the MD5 sum.
			 */
			char command[PATH_MAX * 2 + 4096];
			sprintf(command, "openssl rsa -in '%s' -pubout 2> /dev/null | openssl md5 2> /dev/null | tr -d '[:space:]' | tail -c 32", ticket);
			FILE *digestf = popen(command, "r");
			if(full_fread(digestf, digest, DIGEST_LENGTH) < DIGEST_LENGTH) {
				pclose(digestf);
				return 0;
			}
			pclose(digestf);
			debug(D_AUTH, "trying ticket %.*s", DIGEST_LENGTH, digest);
			if(link_putlstring(link, digest, DIGEST_LENGTH, stoptime) <= 0)
				return 0;
			if(link_putliteral(link, "\n", stoptime) <= 0)
				return 0;

			if(link_readline(link, line, sizeof(line), stoptime) <= 0)
				return 0;
			if(strcmp(line, "declined") == 0)
				continue;

			unsigned long length = strtoul(line, NULL, 10);
			if(errno == ERANGE || errno == EINVAL)
				return 0;	/* not a number? */
			debug(D_AUTH, "receiving challenge of %d bytes", length);

			FILE *in, *out;
			static const char command_template[] = "T1=`mktemp`\n"	/* signed challenge */
				"T2=`mktemp`\n"	/* private key without comments */
				"sed '/^\\s*#/d' < '%s' > \"$T2\"\n" "openssl rsautl -inkey \"$T2\" -sign > \"$T1\" 2> /dev/null\n" "R=\"$?\"\n" "if [ \"$R\" -ne 0 ]; then\n" "  rm -f \"$T1\" \"$T2\"\n" "  exit \"$R\"\n" "fi\n"
				"ls -l \"$T1\" | awk '{ print $5 }'\n" "cat \"$T1\"\n" "rm -f \"$T1\" \"$T2\"\n";
			sprintf(command, command_template, ticket);
			pid_t pid = dpopen(command, &in, &out);
			if(pid == 0)
				return 0;
			if(link_stream_to_file(link, in, length, stoptime) <= 0) {
				dpclose(in, out, pid);
				debug(D_AUTH, "openssl failed, your keysize may be too small");
				debug(D_AUTH, "please debug using \"dd if=/dev/urandom count=64 bs=1 | openssl rsautl -inkey <ticket file> -sign\"");
				return 0;
			}
			fclose(in);
			in = NULL;
			if(link_stream_from_file(link, out, 1 << 20, stoptime) <= 0) {
				dpclose(in, out, pid);
				debug(D_AUTH, "openssl failed, your keysize may be too small");
				debug(D_AUTH, "please debug using \"dd if=/dev/urandom count=64 bs=1 | openssl rsautl -inkey <ticket file> -sign\"");
				return 0;
			}
			dpclose(in, out, pid);

			if(link_readline(link, line, sizeof(line), stoptime) <= 0)
				return 0;
			if(strcmp(line, "success") == 0) {
				debug(D_AUTH, "succeeded challenge for %.*s\n", DIGEST_LENGTH, digest);
				return 1;
			} else if(strcmp(line, "failure") == 0) {
				debug(D_AUTH, "failed challenge for %.*s\n", DIGEST_LENGTH, digest);
				errno = EINVAL;
				return 0;
			} else {
				debug(D_AUTH, "received bad response: '%s'", line);
				errno = EINVAL;
				return 0;
			}
		}
	}
	link_putliteral(link, "==\n", stoptime);

	return 0;
}
Ejemplo n.º 4
0
static int auth_ticket_accept(struct link *link, char **subject, time_t stoptime)
{
	int serrno = errno;
	int status = 0;
	char line[AUTH_LINE_MAX];
	char ticket_subject[AUTH_LINE_MAX];
	char *ticket = NULL;

	errno = 0;

	debug(D_AUTH, "ticket: waiting for tickets");

	while(1) {
		if(link_readline(link, line, sizeof(line), stoptime) > 0) {
			if(strcmp(line, "==") == 0) {
				debug(D_AUTH, "ticket: exhausted all ticket challenges");
				break;
			} else if(strlen(line) == DIGEST_LENGTH) {
				char ticket_digest[DIGEST_LENGTH + 1];
				strcpy(ticket_digest, line);
				strcpy(ticket_subject, line);
				debug(D_AUTH, "ticket: read ticket digest: %s", ticket_digest);
				if(server_callback) {
					free(ticket); /* free previously allocated ticket string or NULL (noop) */
					ticket = server_callback(ticket_digest);
					if(ticket) {
						static const char command_template[] = "T1=`mktemp`\n"	/* The RSA Public Key */
							"T2=`mktemp`\n"	/* The Challenge */
							"T3=`mktemp`\n"	/* The Signed Challenge */
							"T4=`mktemp`\n"	/* The Decrypted (verified) Signed Challenge */
							"echo -n '%s' > \"$T1\"\n" "dd if=/dev/urandom of=\"$T2\" bs=%u count=1 > /dev/null 2> /dev/null\n" "cat \"$T2\"\n"	/* to stdout */
							"cat > \"$T3\"\n"	/* from stdin */
							"openssl rsautl -inkey \"$T1\" -pubin -verify < \"$T3\" > \"$T4\" 2> /dev/null\n" "cmp \"$T2\" \"$T4\" > /dev/null 2> /dev/null\n" "R=\"$?\"\n"
							"rm -f \"$T1\" \"$T2\" \"$T3\" \"$T4\" > /dev/null 2> /dev/null\n" "exit \"$R\"\n";

						char *command = xxmalloc(sizeof(command_template) + strlen(ticket) + 64);
						sprintf(command, command_template, ticket, CHALLENGE_LENGTH);

						FILE *in, *out;
						pid_t pid = dpopen(command, &in, &out);
						free(command);
						if(pid == 0)
							break;

						if(!link_putfstring(link, "%zu\n", stoptime, CHALLENGE_LENGTH))
							break;
						if(!link_stream_from_file(link, out, CHALLENGE_LENGTH, stoptime))
							break;

						if(link_readline(link, line, sizeof(line), stoptime) <= 0)
							break;
						unsigned long length = strtoul(line, NULL, 10);
						if(errno == ERANGE || errno == EINVAL)
							break;	/* not a number? */
						if(!link_stream_to_file(link, in, length, stoptime))
							break;

						int result = dpclose(in, out, pid);

						if(result == 0) {
							debug(D_AUTH, "succeeded challenge for %s\n", ticket_digest);
							link_putliteral(link, "success\n", stoptime);
							status = 1;
							break;
						} else {
							debug(D_AUTH, "failed challenge for %s\n", ticket_digest);
							link_putliteral(link, "failure\n", stoptime);
							break;
						}
					} else {
						debug(D_AUTH, "declining key %s", ticket_digest);
						link_putliteral(link, "declined\n", stoptime);
					}
				} else {
					debug(D_AUTH, "declining key %s", ticket_digest);
					link_putliteral(link, "declined\n", stoptime);
				}
			} else {
				debug(D_AUTH, "ticket: bad response");
				break;
			}
		} else {
			break;
		}
	}

	if(status) {
		*subject = xxmalloc(AUTH_LINE_MAX);
		strcpy(*subject, ticket_subject);
	}
	free(ticket); /* free previously allocated ticket string or NULL (noop) */
	errno = serrno;
	return status;
}