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