Exemple #1
0
static int auth_unix_assert(struct link *link, time_t stoptime)
{
	int success = 0;
	FILE *file;
	char line[AUTH_LINE_MAX];

	debug(D_AUTH, "unix: waiting for challenge");
	if(link_readline(link, line, sizeof(line), stoptime)) {
		debug(D_AUTH, "unix: challenge is %s", line);
		file = fopen(line, "w");
		if(file) {
			fsync(fileno(file));
			fclose(file);
			debug(D_AUTH, "unix: issued response");
			if(auth_barrier(link, "yes\n", stoptime)) {
				debug(D_AUTH, "unix: response accepted");
				success = 1;
			} else {
				debug(D_AUTH, "unix: response rejected");
			}
		} else {
			debug(D_AUTH, "unix: could not meet challenge: %s", strerror(errno));
			link_putliteral(link, "no\n", stoptime);
		}
		unlink(line);
	} else {
		debug(D_AUTH, "unix: couldn't read challenge");
	}

	return success;
}
Exemple #2
0
INT64_T chirp_alloc_putstream(const char *path, struct link * l, time_t stoptime)
{
	INT64_T fd, result, actual, total = 0;
	int buffer_size = 65536;
	char *buffer;

	fd = chirp_alloc_open(path, O_CREAT | O_TRUNC | O_WRONLY, 0700);
	if(fd < 0)
		return fd;

	link_putliteral(l, "0\n", stoptime);

	buffer = malloc(buffer_size);

	while(1) {
		result = link_read(l, buffer, buffer_size, stoptime);
		if(result <= 0)
			break;

		actual = chirp_alloc_pwrite(fd, buffer, result, total);
		if(actual != result)
			break;

		total += actual;
	}

	free(buffer);

	chirp_alloc_close(fd);

	return total;
}
Exemple #3
0
static int auth_address_accept(struct link *link, char **subject, time_t stoptime)
{
	char addr[LINK_ADDRESS_MAX];
	int port;

	if(!link_address_remote(link, addr, &port)) {
		debug(D_AUTH, "address: couldn't get address of link");
		goto reject;
	}

	*subject = strdup(addr);
	if(!*subject) {
		debug(D_AUTH, "address: out of memory");
		goto reject;
	}

	link_putliteral(link, "yes\n", stoptime);
	return 1;

      reject:
	link_putliteral(link, "no\n", stoptime);
	return 0;
}
INT64_T cfs_basic_putfile(const char *path, struct link * link, INT64_T length, INT64_T mode, time_t stoptime)
{
	int fd;
	INT64_T result;

	mode = 0600 | (mode & 0100);

	fd = cfs->open(path, O_WRONLY | O_CREAT | O_TRUNC, (int) mode);
	if(fd >= 0) {
		char buffer[65536];
		INT64_T total = 0;

		link_putliteral(link, "0\n", stoptime);

		while(length > 0) {
			INT64_T ractual, wactual;
			INT64_T chunk = MIN((int) sizeof(buffer), length);

			ractual = link_read(link, buffer, chunk, stoptime);
			if(ractual <= 0)
				break;

			wactual = cfs->pwrite(fd, buffer, ractual, total);
			if(wactual != ractual) {
				total = -1;
				break;
			}

			total += ractual;
			length -= ractual;
		}

		result = total;

		if(length != 0) {
			if(result >= 0)
				link_soak(link, length - result, stoptime);
			result = -1;
		}
		cfs->close(fd);
	} else {
		result = -1;
	}
	return result;
}
Exemple #5
0
int get_results(struct link *mpi_link, struct itable *active_list, struct list *complete_list, int timeout)
{
	char line[MPI_QUEUE_LINE_MAX];
	int num_results, n = 0;
	int stoptime = time(0) + timeout;

	debug(D_MPI, "Getting any results\n");
	link_putliteral(mpi_link, "get results\n", stoptime);
	if(link_readline(mpi_link, line, sizeof(line), stoptime)) {
		debug(D_MPI, "received: %s\n", line);
		sscanf(line, "num results %d", &num_results);
	} else {
		return 0;
	}
	debug(D_MPI, "%d results available\n", num_results);

	while(n++ < num_results && link_readline(mpi_link, line, sizeof(line), stoptime)) {
		struct mpi_queue_task *t;
		int taskid, status, result, result_length;
		
		sscanf(line, "result %d %d %d %d", &taskid, &status, &result, &result_length);
		t = itable_remove(active_list, taskid);
		if(!t) {
			debug(D_NOTICE, "Invalid taskid (%d) returned\n", taskid);
			return -1;
		}
		if(result_length) {
			t->output = malloc(result_length+1);
			link_read(mpi_link, t->output, result_length, time(0) + timeout);
			t->output[result_length] = 0;
		}
		t->status = MPI_QUEUE_TASK_STATUS_COMPLETE;
		t->return_status = result;
		t->result = status;
		list_push_tail(complete_list, t);
	}
	return num_results;
}
Exemple #6
0
// NOT IMPLEMENTED YET
int s3_setacl(char* bucketname, char *filename, const char* owner, struct hash_table* acls, const char* access_key_id, const char* access_key) {
	struct s3_message mesg;
	struct link* server;
	time_t stoptime = time(0)+s3_timeout;
	char path[HEADER_LINE_MAX];
	char response[HEADER_LINE_MAX];
	//char * text;
	//int length;
	char *id;
	struct s3_acl_object *acl;
 
	if(!s3_endpoint) return -1;
	if(filename) sprintf(path, "%s?acl", filename);
	else
	sprintf(path, "/?acl");
 

	mesg.content_length = 39 + 32 + strlen(owner) + 32;
	hash_table_firstkey(acls);
	while(hash_table_nextkey(acls, &id, (void**)&acl)) {
		int glength;

		switch(acl->acl_type) {
			case S3_ACL_URI:
				glength = 140+strlen(id);
				break;
			case S3_ACL_EMAIL:
				glength = 135+strlen(id);
				break;
			default:
				glength = 107+strlen(id);
		}

		if(acl->perm & S3_ACL_FULL_CONTROL)	mesg.content_length += 40 + glength + 12;
		if(acl->perm & S3_ACL_READ)		mesg.content_length += 40 + glength + 4;
		if(acl->perm & S3_ACL_WRITE)		mesg.content_length += 40 + glength + 5;
		if(acl->perm & S3_ACL_READ_ACP)		mesg.content_length += 40 + glength + 8;
		if(acl->perm & S3_ACL_WRITE_ACP)	mesg.content_length += 40 + glength + 9;
	}
	mesg.content_length += 43;

	mesg.type = S3_MESG_PUT;
	mesg.path = path;
	mesg.bucket = bucketname;
	mesg.content_type = NULL;
	mesg.content_md5 = NULL;
	mesg.date = time(0);
	mesg.expect = 0;
	mesg.amz_headers = NULL;

	//server = link_connect(s3_address, 80, stoptime);

	sign_message(&mesg, access_key_id, access_key);
	server = s3_send_message(&mesg, NULL, stoptime);
	if(!server)
		return -1;

	//length = s3_message_to_string(&mesg, &text);

	//fprintf(stderr, "Message:\n%s\n", text);
	//link_putlstring(server, text, length, stoptime);
	//free(text);

	link_putliteral(server, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", stoptime);
	link_putliteral(server, "<AccessControlPolicy><Owner><ID>", stoptime);
	link_putstring(server, owner, stoptime);
	link_putliteral(server, "</ID></Owner><AccessControlList>", stoptime);

	hash_table_firstkey(acls);
	while(hash_table_nextkey(acls, &id, (void**)&acl)) {
		char grantee[HEADER_LINE_MAX];

		switch(acl->acl_type) {
			case S3_ACL_URI:
				sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/%s</URI></Grantee>", id);
				break;
			case S3_ACL_EMAIL:
				sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"AmazonCustomerByEmail\"><EmailAddress>%s</EmailAddress></Grantee>", id);
				break;
			default:
				sprintf(grantee, "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>%s</ID></Grantee>", id);
		}

		if(acl->perm & S3_ACL_FULL_CONTROL) {
			link_putfstring(server, "<Grant>%s<Permission>FULL_CONTROL</Permission></Grant>", stoptime, grantee);
		}
		if(acl->perm & S3_ACL_READ) {
			link_putfstring(server, "<Grant>%s<Permission>READ</Permission></Grant>", stoptime, grantee);
		}
		if(acl->perm & S3_ACL_WRITE) {
			link_putfstring(server, "<Grant>%s<Permission>WRITE</Permission></Grant>", stoptime, grantee);
		}
		if(acl->perm & S3_ACL_READ_ACP) {
			link_putfstring(server, "<Grant>%s<Permission>READ_ACP</Permission></Grant>", stoptime, grantee);
		}
		if(acl->perm & S3_ACL_WRITE_ACP) {
			link_putfstring(server, "<Grant>%s<Permission>WRITE_ACP</Permission></Grant>", stoptime, grantee);
		}
	}

	link_putliteral(server, "</AccessControlList></AccessControlPolicy>\n", stoptime);

	link_readline(server, response, HEADER_LINE_MAX, stoptime);
	if(strcmp(response, "HTTP/1.1 200 OK")) {
		// Error: transfer failed; close connection and return failure
		fprintf(stderr, "Error: send file failed\nResponse: %s\n", response);
		link_close(server);
		return -1;
	}

//	fprintf(stderr, "Response:\n");
	do {
//		fprintf(stderr, "\t%s\n", response);
		if(!strcmp(response, "Server: AmazonS3")) break;
	} while(link_readline(server, response, HEADER_LINE_MAX, stoptime));

	link_close(server);

	return 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;
}
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;
}
Exemple #9
0
static int auth_unix_accept(struct link *link, char **subject, time_t stoptime)
{
	char path[AUTH_LINE_MAX];
	char line[AUTH_LINE_MAX];
	int success = 0;
	struct stat buf;
	struct passwd *p;

	debug(D_AUTH, "unix: generating challenge");
	make_challenge_path(path);
	link_putfstring(link, "%s\n", stoptime, path);

	debug(D_AUTH, "unix: waiting for response");
	if(link_readline(link, line, sizeof(line), stoptime)) {
		if(!strcmp(line, "yes")) {
			int file_exists = 0;
			int i=0;

			for(i=0;i<challenge_timeout;i++) {
				/*
				This is an odd hack, but invoking ls -la appears to help to force
				some NFS clients to refresh cached metadata.
				*/

				DIR *d = opendir(challenge_dir);
				if(d) {
					closedir(d);
				}

				if(stat(path,&buf)==0) {
					file_exists = 1;
					break;
				} else {
					debug(D_AUTH,"unix: client claims success, but I don't see it yet...");
					sleep(1);
				}
			}

			if(file_exists) {
				debug(D_AUTH, "unix: got response");
				debug(D_AUTH, "unix: client is uid %d", buf.st_uid);
				p = auth_get_passwd_from_uid(buf.st_uid);
				if(p) {
					debug(D_AUTH, "unix: client is subject %s", p->pw_name);
					link_putliteral(link, "yes\n", stoptime);
					*subject = xxstrdup(p->pw_name);
					success = 1;
				} else {
					debug(D_AUTH, "unix: there is no user corresponding to uid %d", buf.st_uid);
					link_putliteral(link, "no\n", stoptime);
				}
			} else {
				debug(D_AUTH, "unix: client failed the challenge: %s", strerror(errno));
				link_putliteral(link, "no\n", stoptime);
			}
		} else {
			debug(D_AUTH, "unix: client declined the challenge");
		}
	}

	unlink(path);

	return success;
}