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; }
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; }
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; }
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; }
// 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; }
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; }