int64_t copy_stream_to_fd(FILE *input, int fd) { int64_t total = 0; while(1) { char buffer[COPY_BUFFER_SIZE]; int64_t actual_read = full_fread(input, buffer, COPY_BUFFER_SIZE); if(actual_read <= 0) { if (total == 0) return -1; else break; } int64_t actual_write = full_write(fd, buffer, actual_read); if(actual_write == -1) { if (total == 0) return -1; else break; } total += actual_write; } return total; }
INT64_T link_stream_from_file(struct link * link, FILE * file, INT64_T length, time_t stoptime) { char buffer[65536]; INT64_T total = 0; INT64_T ractual, wactual; while(1) { INT64_T chunk = MIN(sizeof(buffer), length); ractual = full_fread(file, buffer, chunk); if(ractual <= 0) break; wactual = link_write(link, buffer, ractual, stoptime); if(wactual != ractual) { total = -1; break; } total += ractual; length -= ractual; } return total; }
int64_t copy_stream_to_buffer(FILE *input, char **buffer, size_t *len) { size_t _len; if (len == NULL) len = &_len; int64_t total = 0; buffer_t B; buffer_init(&B); while(1) { char buffer[COPY_BUFFER_SIZE]; int64_t actual_read = full_fread(input, buffer, COPY_BUFFER_SIZE); if(actual_read <= 0) { if (total == 0) return -1; else break; } if (buffer_putlstring(&B, buffer, actual_read) == -1) { buffer_free(&B); return -1; } total += actual_read; } buffer_dupl(&B, buffer, len); buffer_free(&B); return total; }
INT64_T chirp_client_ticket_create(struct chirp_client * c, char name[CHIRP_PATH_MAX], unsigned bits, time_t stoptime) { static const char command[] = "T=`mktemp`\n" "P=`mktemp`\n" "MD5=`mktemp`\n" "echo \"# Chirp Ticket\" > \"$T\"\n" "echo \"# `date`: Ticket Created.\" >> \"$T\"\n" "openssl genrsa \"$CHIRP_BITS\" >> \"$T\" 2> /dev/null\n" "sed '/^\\s*#/d' < \"$T\" | openssl rsa -pubout > \"$P\" 2> /dev/null\n" /* WARNING: openssl is *very* bad at giving sensible output. Use the last * 32 non-space characters as the MD5 sum. */ "openssl md5 < \"$P\" 2> /dev/null | tr -d '[:space:]' | tail -c 32 > \"$MD5\"\n" "if [ -z \"$CHIRP_TICKET\" ]; then\n" " CHIRP_TICKET=\"ticket.`cat $MD5`\"\n" "fi\n" "cat > \"$CHIRP_TICKET\" < \"$T\"\n" "rm -f \"$T\" \"$P\" \"$MD5\"\n" "echo \"Generated ticket $CHIRP_TICKET.\" 1>&2\n" "echo -n \"$CHIRP_TICKET\"\n"; int result = 0; if(strlen(name) == 0) unsetenv("CHIRP_TICKET"); else result = setenv("CHIRP_TICKET", name, 1); if(result == -1) return -1; char bits_s[32]; sprintf(bits_s, "%u", bits); result = setenv("CHIRP_BITS", bits_s, 1); if(result == -1) return -1; memset(name, 0, CHIRP_PATH_MAX); FILE *shell = popen(command, "r"); if(shell == NULL) return -1; ssize_t read; char *buffer = name; while((read = full_fread(shell, buffer, sizeof(name) - 1 - (name - buffer))) > 0) buffer += read; pclose(shell); if((buffer - name) <= 0) { errno = EINVAL; return -1; } return 0; }
char * load_one_file( const char *filename, int *length ) { FILE *file = fopen(filename,"r"); if(!file) { fprintf(stderr,"%s: couldn't open %s: %s\n",progname,filename,strerror(errno)); exit(1); } fseek(file,0,SEEK_END); *length = ftell(file); fseek(file,0,SEEK_SET); char *data = malloc(*length); if(!data) { fprintf(stderr,"%s: out of memory!\n",progname); exit(1); } full_fread(file,data,*length); fclose(file); return data; }
struct cseq * cseq_read( FILE *file ) { char line[SEQUENCE_FILE_LINE_MAX]; char metadata[SEQUENCE_FILE_LINE_MAX]; char name[SEQUENCE_FILE_LINE_MAX]; int nbases, nbytes; if(!fgets(line,sizeof(line),file)) return 0; // special case: two arrows indicates the end of a list, // but not the end of a file. if(line[0] == '>' && line[1] == '>') return 0; metadata[0] = 0; int n = sscanf(line, ">%s %d %d %[^\n]",name,&nbases,&nbytes,metadata); if(n<3) fatal("syntax error near %s\n",line); // allocate memory, rounding up to the next word size int malloc_bytes = get_malloc_bytes(nbases); short *data = malloc(malloc_bytes); // set the last full word to zero, to avoid uninitialized data. data[(malloc_bytes/sizeof(short))-1] = 0; n = full_fread(file,data,nbytes); if(n!=nbytes) fatal("sequence file is corrupted."); fgetc(file); struct cseq *c = cseq_create(name,nbases,data,metadata); free(data); return c; }
int64_t link_stream_from_file(struct link * link, FILE * file, int64_t length, time_t stoptime) { int64_t total = 0; while(1) { char buffer[1<<16]; size_t chunk = MIN(sizeof(buffer), (size_t)length); ssize_t ractual = full_fread(file, buffer, chunk); if(ractual <= 0) break; ssize_t wactual = link_write(link, buffer, ractual, stoptime); if(wactual != ractual) { total = -1; break; } total += ractual; length -= ractual; } return total; }
int main(int argc, char *argv[]) { int did_explicit_auth = 0; int follow_mode = 0; int whole_file_mode = 1; const char *hostname, *source_file, *target_file; time_t stoptime; FILE *file; int c; char *tickets = NULL; debug_config(argv[0]); static struct option long_options[] = { {"auth", required_argument, 0, 'a'}, {"block-size", required_argument, 0, 'b'}, {"debug", required_argument, 0, 'd'}, {"follow", no_argument, 0, 'f'}, {"tickets", required_argument, 0, 'i'}, {"timeout", required_argument, 0, 't'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; while((c = getopt_long(argc, argv, "a:b:d:fi:t:vh", long_options, NULL)) > -1) { switch (c) { case 'a': auth_register_byname(optarg); did_explicit_auth = 1; break; case 'b': buffer_size = (size_t)strtoul(optarg, NULL, 0); break; case 'd': debug_flags_set(optarg); break; case 'f': follow_mode = 1; break; case 'i': tickets = strdup(optarg); break; case 't': timeout = string_time_parse(optarg); break; case 'v': cctools_version_print(stdout, argv[0]); exit(0); break; case 'h': show_help(argv[0]); exit(0); break; } } cctools_version_debug(D_DEBUG, argv[0]); if(!did_explicit_auth) auth_register_all(); if(tickets) { auth_ticket_load(tickets); free(tickets); } else if(getenv(CHIRP_CLIENT_TICKETS)) { auth_ticket_load(getenv(CHIRP_CLIENT_TICKETS)); } else { auth_ticket_load(NULL); } if((argc - optind) < 3) { show_help(argv[0]); exit(0); } source_file = argv[optind]; hostname = argv[optind + 1]; target_file = argv[optind + 2]; stoptime = time(0) + timeout; if(!strcmp(source_file, "-")) { file = stdin; source_file = "/dev/stdin"; } else { file = fopen(source_file, "r"); if(!file) { fprintf(stderr, "chirp_put: couldn't open %s: %s\n", source_file, strerror(errno)); return 1; } } if(follow_mode) whole_file_mode = 0; if(whole_file_mode) { INT64_T result = chirp_recursive_put(hostname, source_file, target_file, stoptime); if(result < 0) { fprintf(stderr, "chirp_put: couldn't put %s to host %s: %s\n", source_file, hostname, strerror(errno)); return 1; } else { return 0; } } else { struct chirp_stream *stream; char *buffer = xxmalloc(buffer_size); INT64_T ractual, wactual; stream = chirp_stream_open(hostname, target_file, CHIRP_STREAM_WRITE, stoptime); if(!stream) { fprintf(stderr, "chirp_put: couldn't open %s for writing: %s\n", target_file, strerror(errno)); return 1; } while(1) { ractual = full_fread(file, buffer, buffer_size); if(ractual == 0) { if(follow_mode) { debug(D_DEBUG, "waiting for more data..."); sleep(1); continue; } else { break; } } wactual = chirp_stream_write(stream, buffer, (int)ractual, stoptime); if(wactual != ractual) { fprintf(stderr, "chirp_put: couldn't write to %s: %s\n", target_file, strerror(errno)); return 1; } } chirp_stream_close(stream, stoptime); 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; }