X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/b29ec86e06ace733fb565f8b56d797914987a055..b227bf97b48044debde6ef0d192ae1611830ca42:/update/get_file.c diff --git a/update/get_file.c b/update/get_file.c index 79baacc7..be50013a 100644 --- a/update/get_file.c +++ b/update/get_file.c @@ -1,32 +1,35 @@ -/* - * $Source$ - * $Header$ +/* $Id$ + * + * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * . */ -/* (c) Copyright 1988 by the Massachusetts Institute of Technology. */ -/* For copying and distribution information, please see the file */ -/* . */ - -#ifndef lint -static char *rcsid_get_file_c = "$Header$"; -#endif lint #include -#include -#include -#include -#include -#include -#include +#include +#include "update_server.h" #include "update.h" -extern CONNECTION conn; -char buf[BUFSIZ]; +#include +#include +#include +#include +#include +#include + +#include + +RCSID("$Header$"); -extern int code, errno; +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif /* MIN */ -extern int have_authorization, have_file, done; +static des_key_schedule sched; +static des_cblock ivec; +extern des_cblock session; -int get_block(); +static int get_block(int conn, int fd, int max_size, int encrypt); /* * get_file() @@ -60,127 +63,168 @@ int get_block(); * */ -int -get_file(pathname, file_size, checksum) - char *pathname; - int file_size; - int checksum; +int get_file(int conn, char *pathname, int file_size, int checksum, + int mode, int encrypt) { - int fd, n_written; - int found_checksum; - - if (!have_authorization) { - reject_call(SMS_PERM); - return(1); + int fd, n_written, code; + int found_checksum; + char buf[BUFSIZ]; + + if (!have_authorization) + { + send_int(conn, MR_PERM); + return 1; } - if (done) /* re-initialize data */ - initialize(); - /* unlink old file */ - (void) unlink(pathname); - /* open file descriptor */ - fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, 0700); - if (fd == -1) { - code = errno; - sprintf(buf, "%s: creating file %s (get_file)", - error_message(code), pathname); - sms_log_error(buf); - report_error("reporting file creation error (get_file)"); - return(1); + if (setuid(uid) < 0) + { + com_err(whoami, errno, "Unable to setuid to %d\n", uid); + exit(1); } - /* check to see if we've got the disk space */ - n_written = 0; - while (n_written < file_size) { - register int n_wrote; - n_wrote = write(fd, buf, sizeof(buf)); - if (n_wrote == -1) { - code = errno; - sprintf(buf, "%s: verifying free disk space for %s (get_file)", - error_message(code), pathname); - sms_log_error(buf); - /* do all we can to free the space */ - (void) unlink(pathname); - (void) ftruncate(fd, 0); - (void) close(fd); - report_error("reporting test-write error (get_file)"); - return(1); + + /* unlink old file */ + if (!config_lookup("noclobber")) + unlink(pathname); + /* open file descriptor */ + fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode); + if (fd == -1) + { + code = errno; + com_err(whoami, errno, "creating file %s (get_file)", pathname); + send_int(conn, code); + if (setuid(0) < 0) + { + com_err(whoami, errno, "Unable to setuid back to %d\n", 0); + exit(1); } - n_written += n_wrote; + return 1; } - lseek(fd, 0, L_SET); - if (send_ok()) - lose("sending okay for file transfer (get_file)"); - n_written = 0; - while (n_written < file_size && code == 0) { - int n_got = get_block(fd, file_size - n_written); - if (n_got == -1) { - /* get_block has already printed a message */ - unlink(pathname); - return(1); + + /* check to see if we've got the disk space */ + n_written = 0; + while (n_written < file_size) + { + int n_wrote; + n_wrote = write(fd, buf, sizeof(buf)); + if (n_wrote == -1) + { + code = errno; + com_err(whoami, code, "verifying free disk space for %s (get_file)", + pathname); + send_int(conn, code); + + /* do all we can to free the space */ + unlink(pathname); + ftruncate(fd, 0); + close(fd); + + if (setuid(0) < 0) + { + com_err(whoami, errno, "Unable to setuid back to %d\n", 0); + exit(1); + } + return 1; } - n_written += n_got; - if (n_written != file_size) - if (send_ok()) - lose("receiving data"); + n_written += n_wrote; } - if (code) { - code = connection_errno(conn); - report_error("reading file (get_file)"); - return(1); + + lseek(fd, 0, SEEK_SET); + send_ok(conn); + + if (encrypt) + { + des_key_sched(session, sched); + memcpy(ivec, session, sizeof(ivec)); } - fsync(fd); - ftruncate(fd, file_size); - fsync(fd); - close(fd); - /* validate checksum */ - found_checksum = checksum_file(pathname); - if (checksum != found_checksum) { - code = SMS_MISSINGFILE; - com_err(whoami, code, ": expected = %d, found = %d", - checksum, found_checksum); - report_error("checksum error"); - return(1); + + n_written = 0; + while (n_written < file_size) + { + int n_got = get_block(conn, fd, file_size - n_written, encrypt); + + if (n_got == -1) + { + /* get_block has already printed a message */ + unlink(pathname); + if (setuid(0) < 0) + { + com_err(whoami, errno, "Unable to setuid back to %d\n", 0); + exit(1); + } + return 1; + } + n_written += n_got; + if (n_written != file_size) + send_ok(conn); } - /* send ack or nack */ - have_file = 1; - if (send_ok()) { - code = connection_errno(conn); - (void) unlink(pathname); - lose("sending ok after file transfer (get_file)"); - return(1); + + fsync(fd); + ftruncate(fd, file_size); + fsync(fd); + close(fd); + + if (setuid(0) < 0) + { + com_err(whoami, errno, "Unable to setuid back to %d\n", 0); + exit(1); + } + + /* validate checksum */ + found_checksum = checksum_file(pathname); + if (checksum != found_checksum) + { + code = MR_MISSINGFILE; + com_err(whoami, code, ": expected = %d, found = %d", + checksum, found_checksum); + send_int(conn, code); + return 1; } - return(0); + + send_ok(conn); + return 0; } -static int -get_block(fd, max_size) - int fd; - int max_size; +static int get_block(int conn, int fd, int max_size, int encrypt) { - STRING data; - int n_read, n; + char *data; + size_t len; + int n_read, n, i, code; + + recv_string(conn, &data, &len); + + if (encrypt) + { + char *unenc = malloc(len); - code = receive_object(conn, (char *)&data, STRING_T); - if (code) { - code = connection_errno(conn); - lose("receiving data file (get_file)"); + if (!unenc) + { + send_int(conn, ENOMEM); + return -1; + } + + des_pcbc_encrypt(data, unenc, len, sched, ivec, 1); + for (i = 0; i < 8; i++) + ivec[i] = data[len - 8 + i] ^ unenc[len - 8 + i]; + free(data); + data = unenc; } - n_read = MIN(MAX_STRING_SIZE(data), max_size); - n = 0; - while (n < n_read) { - register int n_wrote; - n_wrote = write(fd, STRING_DATA(data)+n, - n_read-n); - if (n_wrote == -1) { - code = errno; - sprintf(buf, "%s: writing file (get_file)", error_message(code)); - sms_log_error(buf); - string_free(&data); - report_error("reporting write error (get_file)"); - close(fd); - return(-1); + + n_read = MIN(len, max_size); + n = 0; + while (n < n_read) + { + int n_wrote; + n_wrote = write(fd, data + n, n_read - n); + if (n_wrote == -1) + { + code = errno; + com_err(whoami, errno, "writing file (get_file)"); + send_int(conn, code); + free(data); + close(fd); + return -1; } - n += n_wrote; + n += n_wrote; } - string_free(&data); - return(n); + free(data); + return n; }