]> andersk Git - moira.git/blame - update/get_file.c
Build without krb4 if it's unavailable.
[moira.git] / update / get_file.c
CommitLineData
7ac48069 1/* $Id$
2 *
3 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
5 * <mit-copyright.h>.
de56407f 6 */
de56407f 7
546bc43b 8#include <mit-copyright.h>
2ad0a777 9#include <moira.h>
7ac48069 10#include "update_server.h"
de56407f 11#include "update.h"
de56407f 12
7ac48069 13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
85330553 16#include <stdlib.h>
eedd0489 17#include <string.h>
7ac48069 18#include <unistd.h>
19
cb974713 20#ifdef HAVE_KRB4
7ac48069 21#include <des.h>
cb974713 22#endif
7ac48069 23
24RCSID("$Header$");
25
7b18e95b 26#ifndef MIN
5eaef520 27#define MIN(a, b) (((a) < (b)) ? (a) : (b))
7b18e95b 28#endif /* MIN */
29
cb974713 30#ifdef HAVE_KRB4
d599d457 31static des_key_schedule sched;
32static des_cblock ivec;
85330553 33extern des_cblock session;
cb974713 34#endif
de56407f 35
85330553 36static int get_block(int conn, int fd, int max_size, int encrypt);
de56407f 37
38/*
39 * get_file()
40 *
41 * arguments:
42 * char *pathname
43 * file to receive
44 * int file_size
45 * number of bytes
46 * int checksum
47 * linear checksum of bytes
48 *
49 * syntax:
50 * (initial protocol already done)
51 * <<< (int)code (can we accept the file?)
52 * >>> (STRING)data
53 * <<< (int)code
54 * >>> (STRING)data
55 * <<< (int)code
56 * ...
57 * >>> (STRING)data (last data block)
58 * <<< (int)code (from read, write, checksum verify)
59 *
60 * returns:
61 * int
62 * 0 for success, 1 for failure
63 *
64 * function:
65 * perform initial preparations and receive file as
66 * a single string, storing it into <pathname>
67 *
68 */
69
85330553 70int get_file(int conn, char *pathname, int file_size, int checksum,
5eaef520 71 int mode, int encrypt)
de56407f 72{
85330553 73 int fd, n_written, code;
5eaef520 74 int found_checksum;
85330553 75 char buf[BUFSIZ];
5eaef520 76
0a01a5a4 77 memset(buf, '\0', sizeof(buf));
78
5eaef520 79 if (!have_authorization)
80 {
85330553 81 send_int(conn, MR_PERM);
5eaef520 82 return 1;
de56407f 83 }
5eaef520 84 if (setuid(uid) < 0)
85 {
86 com_err(whoami, errno, "Unable to setuid to %d\n", uid);
87 exit(1);
35fd45e2 88 }
85330553 89
5eaef520 90 /* unlink old file */
91 if (!config_lookup("noclobber"))
92 unlink(pathname);
93 /* open file descriptor */
94 fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode);
95 if (fd == -1)
96 {
97 code = errno;
85330553 98 com_err(whoami, errno, "creating file %s (get_file)", pathname);
99 send_int(conn, code);
5eaef520 100 return 1;
de56407f 101 }
85330553 102
5eaef520 103 /* check to see if we've got the disk space */
104 n_written = 0;
105 while (n_written < file_size)
106 {
44d12d58 107 int n_wrote;
5eaef520 108 n_wrote = write(fd, buf, sizeof(buf));
109 if (n_wrote == -1)
110 {
111 code = errno;
85330553 112 com_err(whoami, code, "verifying free disk space for %s (get_file)",
113 pathname);
114 send_int(conn, code);
115
5eaef520 116 /* do all we can to free the space */
117 unlink(pathname);
118 ftruncate(fd, 0);
119 close(fd);
5eaef520 120 return 1;
de56407f 121 }
5eaef520 122 n_written += n_wrote;
de56407f 123 }
85330553 124
7ac48069 125 lseek(fd, 0, SEEK_SET);
85330553 126 send_ok(conn);
127
5eaef520 128 if (encrypt)
129 {
cb974713 130#ifdef HAVE_KRB4
5eaef520 131 des_key_sched(session, sched);
132 memcpy(ivec, session, sizeof(ivec));
cb974713 133#else
134 /* The session key only gets stored if auth happens in krb4 to
135 begin with. If you don't have krb4, you can't possibly be
136 coming up with a valid session key. */
137 return MR_NO_KRB4;
138#endif
d599d457 139 }
85330553 140
5eaef520 141 n_written = 0;
85330553 142 while (n_written < file_size)
5eaef520 143 {
85330553 144 int n_got = get_block(conn, fd, file_size - n_written, encrypt);
145
5eaef520 146 if (n_got == -1)
147 {
148 /* get_block has already printed a message */
149 unlink(pathname);
5eaef520 150 return 1;
151 }
152 n_written += n_got;
153 if (n_written != file_size)
85330553 154 send_ok(conn);
de56407f 155 }
85330553 156
5eaef520 157 fsync(fd);
158 ftruncate(fd, file_size);
159 fsync(fd);
160 close(fd);
85330553 161
5eaef520 162 /* validate checksum */
163 found_checksum = checksum_file(pathname);
164 if (checksum != found_checksum)
165 {
166 code = MR_MISSINGFILE;
167 com_err(whoami, code, ": expected = %d, found = %d",
168 checksum, found_checksum);
85330553 169 send_int(conn, code);
5eaef520 170 return 1;
de56407f 171 }
85330553 172
173 send_ok(conn);
5eaef520 174 return 0;
de56407f 175}
176
85330553 177static int get_block(int conn, int fd, int max_size, int encrypt)
de56407f 178{
85330553 179 char *data;
180 size_t len;
181 int n_read, n, i, code;
de56407f 182
85330553 183 recv_string(conn, &data, &len);
32df7737 184
5eaef520 185 if (encrypt)
186 {
cb974713 187#ifdef HAVE_KRB4
85330553 188 char *unenc = malloc(len);
189
190 if (!unenc)
191 {
192 send_int(conn, ENOMEM);
193 return -1;
194 }
195
196 des_pcbc_encrypt(data, unenc, len, sched, ivec, 1);
5eaef520 197 for (i = 0; i < 8; i++)
85330553 198 ivec[i] = data[len - 8 + i] ^ unenc[len - 8 + i];
199 free(data);
200 data = unenc;
cb974713 201#endif
32df7737 202 }
203
85330553 204 n_read = MIN(len, max_size);
5eaef520 205 n = 0;
206 while (n < n_read)
207 {
44d12d58 208 int n_wrote;
85330553 209 n_wrote = write(fd, data + n, n_read - n);
5eaef520 210 if (n_wrote == -1)
211 {
212 code = errno;
85330553 213 com_err(whoami, errno, "writing file (get_file)");
214 send_int(conn, code);
215 free(data);
5eaef520 216 close(fd);
217 return -1;
de56407f 218 }
5eaef520 219 n += n_wrote;
de56407f 220 }
85330553 221 free(data);
5eaef520 222 return n;
de56407f 223}
This page took 0.67365 seconds and 5 git commands to generate.