]>
Commit | Line | Data |
---|---|---|
de56407f | 1 | /* |
2 | * $Source$ | |
3 | * $Header$ | |
4 | */ | |
546bc43b | 5 | /* (c) Copyright 1988 by the Massachusetts Institute of Technology. */ |
6 | /* For copying and distribution information, please see the file */ | |
7 | /* <mit-copyright.h>. */ | |
de56407f | 8 | |
9 | #ifndef lint | |
10 | static char *rcsid_get_file_c = "$Header$"; | |
11 | #endif lint | |
12 | ||
546bc43b | 13 | #include <mit-copyright.h> |
de56407f | 14 | #include <stdio.h> |
ea579254 | 15 | #include <gdb.h> |
de56407f | 16 | #include <ctype.h> |
17 | #include <sys/param.h> | |
18 | #include <sys/file.h> | |
32df7737 | 19 | #include <des.h> |
20 | #include <krb.h> | |
2ad0a777 | 21 | #include <moira.h> |
de56407f | 22 | #include "update.h" |
de56407f | 23 | |
7b18e95b | 24 | #ifndef MIN |
25 | #define MIN(a,b) (((a) < (b))?(a):(b)) | |
26 | #endif /* MIN */ | |
27 | ||
de56407f | 28 | extern CONNECTION conn; |
29 | char buf[BUFSIZ]; | |
30 | ||
35fd45e2 | 31 | extern int code, errno, uid; |
de56407f | 32 | |
33 | extern int have_authorization, have_file, done; | |
32df7737 | 34 | extern C_Block session; |
de56407f | 35 | |
36 | int get_block(); | |
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 | ||
70 | int | |
32df7737 | 71 | get_file(pathname, file_size, checksum, mode, encrypt) |
de56407f | 72 | char *pathname; |
73 | int file_size; | |
74 | int checksum; | |
35fd45e2 | 75 | int mode; |
32df7737 | 76 | int encrypt; |
de56407f | 77 | { |
78 | int fd, n_written; | |
79 | int found_checksum; | |
80 | ||
81 | if (!have_authorization) { | |
2ad0a777 | 82 | reject_call(MR_PERM); |
de56407f | 83 | return(1); |
84 | } | |
85 | if (done) /* re-initialize data */ | |
86 | initialize(); | |
35fd45e2 | 87 | if (setreuid(0, uid) < 0) { |
88 | com_err(whoami, errno, "Unable to setuid to %d\n", uid); | |
89 | exit(1); | |
90 | } | |
de56407f | 91 | /* unlink old file */ |
35fd45e2 | 92 | if (!config_lookup("noclobber")) |
93 | (void) unlink(pathname); | |
de56407f | 94 | /* open file descriptor */ |
35fd45e2 | 95 | fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode); |
de56407f | 96 | if (fd == -1) { |
97 | code = errno; | |
98 | sprintf(buf, "%s: creating file %s (get_file)", | |
99 | error_message(code), pathname); | |
2ad0a777 | 100 | mr_log_error(buf); |
de56407f | 101 | report_error("reporting file creation error (get_file)"); |
35fd45e2 | 102 | if (setuid(0) < 0) { |
103 | com_err(whoami, errno, "Unable to setuid back to %d\n", 0); | |
104 | exit(1); | |
105 | } | |
de56407f | 106 | return(1); |
107 | } | |
108 | /* check to see if we've got the disk space */ | |
109 | n_written = 0; | |
110 | while (n_written < file_size) { | |
111 | register int n_wrote; | |
112 | n_wrote = write(fd, buf, sizeof(buf)); | |
113 | if (n_wrote == -1) { | |
114 | code = errno; | |
115 | sprintf(buf, "%s: verifying free disk space for %s (get_file)", | |
116 | error_message(code), pathname); | |
2ad0a777 | 117 | mr_log_error(buf); |
de56407f | 118 | /* do all we can to free the space */ |
119 | (void) unlink(pathname); | |
120 | (void) ftruncate(fd, 0); | |
121 | (void) close(fd); | |
122 | report_error("reporting test-write error (get_file)"); | |
35fd45e2 | 123 | if (setuid(0) < 0) { |
124 | com_err(whoami, errno, "Unable to setuid back to %d\n", 0); | |
125 | exit(1); | |
126 | } | |
de56407f | 127 | return(1); |
128 | } | |
129 | n_written += n_wrote; | |
130 | } | |
131 | lseek(fd, 0, L_SET); | |
132 | if (send_ok()) | |
133 | lose("sending okay for file transfer (get_file)"); | |
134 | n_written = 0; | |
135 | while (n_written < file_size && code == 0) { | |
32df7737 | 136 | int n_got = get_block(fd, file_size - n_written, encrypt); |
de56407f | 137 | if (n_got == -1) { |
138 | /* get_block has already printed a message */ | |
139 | unlink(pathname); | |
35fd45e2 | 140 | if (setuid(0) < 0) { |
141 | com_err(whoami, errno, "Unable to setuid back to %d\n", 0); | |
142 | exit(1); | |
143 | } | |
de56407f | 144 | return(1); |
145 | } | |
146 | n_written += n_got; | |
147 | if (n_written != file_size) | |
148 | if (send_ok()) | |
149 | lose("receiving data"); | |
150 | } | |
151 | if (code) { | |
152 | code = connection_errno(conn); | |
153 | report_error("reading file (get_file)"); | |
35fd45e2 | 154 | if (setuid(0) < 0) { |
155 | com_err(whoami, errno, "Unable to setuid back to %d\n", 0); | |
156 | exit(1); | |
157 | } | |
de56407f | 158 | return(1); |
159 | } | |
160 | fsync(fd); | |
161 | ftruncate(fd, file_size); | |
162 | fsync(fd); | |
163 | close(fd); | |
35fd45e2 | 164 | if (setuid(0) < 0) { |
165 | com_err(whoami, errno, "Unable to setuid back to %d\n", 0); | |
166 | exit(1); | |
167 | } | |
de56407f | 168 | /* validate checksum */ |
ea579254 | 169 | found_checksum = checksum_file(pathname); |
de56407f | 170 | if (checksum != found_checksum) { |
2ad0a777 | 171 | code = MR_MISSINGFILE; |
de56407f | 172 | com_err(whoami, code, ": expected = %d, found = %d", |
173 | checksum, found_checksum); | |
174 | report_error("checksum error"); | |
175 | return(1); | |
176 | } | |
de56407f | 177 | /* send ack or nack */ |
178 | have_file = 1; | |
179 | if (send_ok()) { | |
180 | code = connection_errno(conn); | |
181 | (void) unlink(pathname); | |
182 | lose("sending ok after file transfer (get_file)"); | |
183 | return(1); | |
184 | } | |
185 | return(0); | |
186 | } | |
187 | ||
188 | static int | |
32df7737 | 189 | get_block(fd, max_size, encrypt) |
de56407f | 190 | int fd; |
191 | int max_size; | |
32df7737 | 192 | int encrypt; |
de56407f | 193 | { |
194 | STRING data; | |
195 | int n_read, n; | |
196 | ||
197 | code = receive_object(conn, (char *)&data, STRING_T); | |
198 | if (code) { | |
199 | code = connection_errno(conn); | |
200 | lose("receiving data file (get_file)"); | |
201 | } | |
202 | n_read = MIN(MAX_STRING_SIZE(data), max_size); | |
32df7737 | 203 | if (encrypt) { |
204 | des_key_schedule sched; | |
205 | des_cblock ivec; | |
206 | STRING newdata; | |
207 | ||
208 | des_key_sched(session, sched); | |
209 | bzero(ivec, sizeof(ivec)); | |
210 | STRING_DATA(newdata) = (char *) malloc(n_read+9); | |
211 | des_pcbc_encrypt(STRING_DATA(data), STRING_DATA(newdata), | |
212 | n_read, sched, &ivec, 1); | |
213 | string_free(&data); | |
214 | data.ptr = newdata.ptr; | |
215 | } | |
216 | ||
de56407f | 217 | n = 0; |
218 | while (n < n_read) { | |
219 | register int n_wrote; | |
220 | n_wrote = write(fd, STRING_DATA(data)+n, | |
221 | n_read-n); | |
222 | if (n_wrote == -1) { | |
223 | code = errno; | |
224 | sprintf(buf, "%s: writing file (get_file)", error_message(code)); | |
2ad0a777 | 225 | mr_log_error(buf); |
de56407f | 226 | string_free(&data); |
227 | report_error("reporting write error (get_file)"); | |
228 | close(fd); | |
229 | return(-1); | |
230 | } | |
231 | n += n_wrote; | |
232 | } | |
233 | string_free(&data); | |
234 | return(n); | |
235 | } |