]> andersk Git - moira.git/blob - update/get_file.c
#includes, prototypes, etc
[moira.git] / update / get_file.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5 /*  (c) Copyright 1988 by the Massachusetts Institute of Technology. */
6 /*  For copying and distribution information, please see the file */
7 /*  <mit-copyright.h>. */
8
9 #ifndef lint
10 static char *rcsid_get_file_c = "$Header$";
11 #endif
12
13 #include <mit-copyright.h>
14 #include <stdio.h>
15 #include <gdb.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <sys/param.h>
19 #include <sys/file.h>
20 #include <fcntl.h>
21 #include <des.h>
22 #include <krb.h>
23 #include <moira.h>
24 #include "update.h"
25
26 #ifndef MIN
27 #define MIN(a,b)    (((a) < (b))?(a):(b))
28 #endif /* MIN */
29
30 extern CONNECTION conn;
31 extern char buf[BUFSIZ];
32
33 extern int code, errno, uid;
34 extern char *whoami;
35
36 extern int have_authorization, have_file, done;
37 extern C_Block session;
38 static des_key_schedule sched;
39 static des_cblock ivec;
40
41 static int get_block();
42
43 /*
44  * get_file()
45  *
46  * arguments:
47  *      char *pathname
48  *              file to receive
49  *      int file_size
50  *              number of bytes
51  *      int checksum
52  *              linear checksum of bytes
53  *
54  * syntax:
55  * (initial protocol already done)
56  * <<< (int)code        (can we accept the file?)
57  * >>> (STRING)data
58  * <<< (int)code
59  * >>> (STRING)data
60  * <<< (int)code
61  * ...
62  * >>> (STRING)data     (last data block)
63  * <<< (int)code        (from read, write, checksum verify)
64  *
65  * returns:
66  *      int
67  *              0 for success, 1 for failure
68  *
69  * function:
70  *      perform initial preparations and receive file as
71  * a single string, storing it into <pathname>
72  *
73  */
74
75 int
76 get_file(pathname, file_size, checksum, mode, encrypt)
77     char *pathname;
78     int file_size;
79     int checksum;
80     int mode;
81     int encrypt;
82 {
83     int fd, n_written;
84     int found_checksum;
85     
86     if (!have_authorization) {
87         reject_call(MR_PERM);
88         return(1);
89     }
90     if (done)                   /* re-initialize data */
91         initialize();
92 #ifdef POSIX
93     if (setuid(uid) < 0) {
94 #else
95     if (setreuid(0, uid) < 0) {
96 #endif
97         com_err(whoami, errno, "Unable to setuid to %d\n", uid);
98         exit(1);
99     }
100     /* unlink old file */
101     if (!config_lookup("noclobber"))
102       (void) unlink(pathname);
103     /* open file descriptor */
104     fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode);
105     if (fd == -1) {
106         code = errno;
107         sprintf(buf, "%s: creating file %s (get_file)",
108                 error_message(code), pathname);
109         mr_log_error(buf);
110         report_error("reporting file creation error (get_file)");
111         if (setuid(0) < 0) {
112             com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
113             exit(1);
114         }
115         return(1);
116     }
117     /* check to see if we've got the disk space */
118     n_written = 0;
119     while (n_written < file_size) {
120         register int n_wrote;
121         n_wrote = write(fd, buf, sizeof(buf));
122         if (n_wrote == -1) {
123             code = errno;
124             sprintf(buf, "%s: verifying free disk space for %s (get_file)",
125                     error_message(code), pathname);
126             mr_log_error(buf);
127             /* do all we can to free the space */
128             (void) unlink(pathname);
129             (void) ftruncate(fd, 0);
130             (void) close(fd);
131             report_error("reporting test-write error (get_file)");
132             if (setuid(0) < 0) {
133                 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
134                 exit(1);
135             }
136             return(1);
137         }
138         n_written += n_wrote;
139     }
140     lseek(fd, 0, L_SET);
141     if (send_ok())
142         lose("sending okay for file transfer (get_file)");
143     if (encrypt) {
144 #ifdef DEBUG
145         com_err(whoami, 0, "Session %02x %02x %02x %02x  %02x %02x %02x %02x",
146                 session[0], session[1], session[2], session[3], 
147                 session[4], session[5], session[6], session[7]);
148 #endif /* DEBUG */
149         des_key_sched(session, sched);
150         memcpy(ivec, session, sizeof(ivec));
151     }
152     n_written = 0;
153     while (n_written < file_size && code == 0) {
154         int n_got = get_block(fd, file_size - n_written, encrypt);
155         if (n_got == -1) {
156             /* get_block has already printed a message */
157             unlink(pathname);
158             if (setuid(0) < 0) {
159                 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
160                 exit(1);
161             }
162             return(1);
163         }
164         n_written += n_got;
165         if (n_written != file_size)
166             if (send_ok())
167                 lose("receiving data");
168     }
169     if (code) {
170         code = connection_errno(conn);
171         report_error("reading file (get_file)");
172         if (setuid(0) < 0) {
173             com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
174             exit(1);
175         }
176         return(1);
177     }
178     fsync(fd);
179     ftruncate(fd, file_size);
180     fsync(fd);
181     close(fd);
182     if (setuid(0) < 0) {
183         com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
184         exit(1);
185     }
186     /* validate checksum */
187     found_checksum = checksum_file(pathname);
188     if (checksum != found_checksum) {
189         code = MR_MISSINGFILE;
190         com_err(whoami, code, ": expected = %d, found = %d",
191                 checksum, found_checksum);
192         report_error("checksum error");
193         return(1);
194     }
195     /* send ack or nack */
196     have_file = 1;
197     if (send_ok()) {
198         code = connection_errno(conn);
199         (void) unlink(pathname);
200         lose("sending ok after file transfer (get_file)");
201         return(1);
202     }
203     return(0);
204 }
205
206 static int
207 get_block(fd, max_size, encrypt)
208     int fd;
209     int max_size;
210     int encrypt;
211 {
212     STRING data;
213     unsigned char dst[UPDATE_BUFSIZ + 8], *src;
214     int n_read, n, i;
215
216     code = receive_object(conn, (char *)&data, STRING_T);
217     if (code) {
218         code = connection_errno(conn);
219         lose("receiving data file (get_file)");
220     }
221
222     if (encrypt) {
223         src = (unsigned char *)STRING_DATA(data);
224         n = MAX_STRING_SIZE(data);
225         des_pcbc_encrypt(src, dst, n, sched, ivec, 1);
226         for (i = 0; i < 8; i++)
227           ivec[i] = src[n - 8 + i] ^ dst[n - 8 + i];
228         memcpy(STRING_DATA(data), dst, n);
229     }
230
231     n_read = MIN(MAX_STRING_SIZE(data), max_size);
232     n = 0;
233     while (n < n_read) {
234         register int n_wrote;
235         n_wrote = write(fd, STRING_DATA(data)+n,
236                         n_read-n);
237         if (n_wrote == -1) {
238             code = errno;
239             sprintf(buf, "%s: writing file (get_file)", error_message(code));
240             mr_log_error(buf);
241             string_free(&data);
242             report_error("reporting write error (get_file)");
243             close(fd);
244             return(-1);
245         }
246         n += n_wrote;
247     }
248     string_free(&data);
249     return(n);
250 }
This page took 0.052201 seconds and 5 git commands to generate.