"Fossies" - the Fresh Open Source Software Archive 
Member "radmind-1.15.3/radmind-/retr.c" (30 Nov 2020, 14299 Bytes) of package /linux/privat/radmind-1.15.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * Copyright (c) 2003 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
4 */
5
6 #include "config.h"
7
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/param.h>
11 #include <sys/time.h>
12 #ifdef __APPLE__
13 #include <sys/attr.h>
14 #include <sys/paths.h>
15 #endif /* __APPLE__ */
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <openssl/ssl.h>
24 #include <openssl/err.h>
25
26 #include <openssl/evp.h>
27
28 #ifdef HAVE_ZLIB
29 #include <zlib.h>
30 #endif /* HAVE_ZLIB */
31
32 #include <snet.h>
33
34 #include "openssl_compat.h" // Compatibility shims for OpenSSL < 1.1.0
35 #include "applefile.h"
36 #include "connect.h"
37 #include "cksum.h"
38 #include "base64.h"
39 #include "code.h"
40 #include "largefile.h"
41 #include "progress.h"
42 #include "mkprefix.h"
43
44 extern void (*logger)( char * );
45 extern struct timeval timeout;
46 extern int linenum;
47 extern int verbose;
48 extern int showprogress;
49 extern int dodots;
50 extern int cksum;
51 extern int errno;
52 extern int create_prefix;
53 extern SSL_CTX *ctx;
54
55 /*
56 * Download requests path from sn and writes it to disk. The path to
57 * this new file is returned via temppath which must be 2 * MAXPATHLEN.
58 *
59 * Return Value:
60 * -1 - error, do not call closesn
61 * 0 - OKAY
62 * 1 - error, call closesn
63 */
64
65 int
66 retr( SNET *sn, char *pathdesc, char *path, char *temppath, mode_t tempmode,
67 off_t transize, char *trancksum )
68 {
69 struct timeval tv;
70 char *line;
71 int fd;
72 unsigned int md_len;
73 int returnval = -1;
74 off_t size = 0;
75 char buf[ 8192 ];
76 ssize_t rr;
77 extern EVP_MD *md;
78 EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
79 unsigned char md_value[ SZ_BASE64_D( SZ_BASE64_E( EVP_MAX_MD_SIZE ) ) ];
80 char cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ];
81
82 if ( cksum ) {
83 if ( strcmp( trancksum, "-" ) == 0 ) {
84 fprintf( stderr, "line %d: No checksum\n", linenum);
85 fprintf( stderr, "%s\n", pathdesc );
86 return( 1 );
87 }
88 EVP_DigestInit( mdctx, md );
89 }
90
91 if ( verbose ) printf( ">>> RETR %s\n", pathdesc );
92 if ( snet_writef( sn, "RETR %s\n", pathdesc ) < 0 ) {
93 fprintf( stderr, "retrieve %s failed: 1-%s\n", pathdesc,
94 strerror( errno ));
95 return( -1 );
96 }
97
98 tv = timeout;
99 if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) {
100 fprintf( stderr, "retrieve %s failed: 2-%s\n", pathdesc,
101 strerror( errno ));
102 return( -1 );
103 }
104
105 if ( *line != '2' ) {
106 fprintf( stderr, "%s\n", line );
107 return( 1 );
108 }
109
110 /* Get file size from server */
111 tv = timeout;
112 if (( line = snet_getline( sn, &tv )) == NULL ) {
113 fprintf( stderr, "retrieve %s failed: 3-%s\n", pathdesc,
114 strerror( errno ));
115 return( -1 );
116 }
117 size = strtoofft( line, NULL, 10 );
118 if ( verbose ) printf( "<<< %" PRIofft "d\n", size );
119 if ( transize >= 0 && size != transize ) {
120 fprintf( stderr, "line %d: size in transcript does not match size "
121 "from server\n", linenum );
122 fprintf( stderr, "%s\n", pathdesc );
123 return( -1 );
124 }
125
126 /*Create temp file name*/
127 if ( snprintf( temppath, MAXPATHLEN, "%s.radmind.%i",
128 path, getpid()) >= MAXPATHLEN ) {
129 fprintf( stderr, "%s.radmind.%i: too long", path,
130 (int)getpid());
131 return( -1 );
132 }
133 /* Open file */
134 if (( fd = open( temppath, O_WRONLY | O_CREAT, tempmode )) < 0 ) {
135 if ( create_prefix && errno == ENOENT ) {
136 errno = 0;
137 if ( mkprefix( temppath ) != 0 ) {
138 perror( temppath );
139 return( -1 );
140 }
141 if (( fd = open( temppath, O_WRONLY | O_CREAT, tempmode )) < 0 ) {
142 perror( temppath );
143 return( -1 );
144 }
145 } else {
146 perror( temppath );
147 return( -1 );
148 }
149 }
150
151 if ( verbose ) printf( "<<< " );
152
153 /* Get file from server */
154 while ( size > 0 ) {
155 tv = timeout;
156 if (( rr = snet_read( sn, buf, MIN( sizeof( buf ), size ),
157 &tv )) <= 0 ) {
158 fprintf( stderr, "retrieve %s failed: 4-%s\n", pathdesc,
159 strerror( errno ));
160 returnval = -1;
161 goto error2;
162 }
163 if ( write( fd, buf, (size_t)rr ) != rr ) {
164 perror( temppath );
165 returnval = -1;
166 goto error2;
167 }
168 if ( cksum ) {
169 EVP_DigestUpdate( mdctx, buf, (unsigned int)rr );
170 }
171 if ( dodots ) { putc( '.', stdout ); fflush( stdout ); }
172 size -= rr;
173 if ( showprogress ) {
174 progressupdate( rr, path );
175 }
176 }
177 if ( close( fd ) != 0 ) {
178 perror( path );
179 returnval = -1;
180 goto error1;
181 }
182 if ( verbose ) printf( "\n" );
183
184 tv = timeout;
185 if (( line = snet_getline( sn, &tv )) == NULL ) {
186 fprintf( stderr, "retrieve %s failed: 5-%s\n", pathdesc,
187 strerror( errno ));
188 returnval = -1;
189 goto error1;
190 }
191 if ( strcmp( line, "." ) != 0 ) {
192 fprintf( stderr, "%s", line );
193 fprintf( stderr, "%s\n", pathdesc );
194 returnval = -1;
195 goto error1;
196 }
197 if ( verbose ) printf( "<<< .\n" );
198
199 /* cksum file */
200 if ( cksum ) {
201 EVP_DigestFinal( mdctx, md_value, &md_len );
202 base64_e( md_value, md_len, cksum_b64 );
203 EVP_MD_CTX_free(mdctx);
204 if ( strcmp( trancksum, cksum_b64 ) != 0 ) {
205 fprintf( stderr, "line %d: checksum in transcript does not match "
206 "checksum from server\n", linenum );
207 fprintf( stderr, "%s\n", pathdesc );
208 returnval = 1;
209 goto error1;
210 }
211 }
212
213 return( 0 );
214
215 error2:
216 close( fd );
217 error1:
218 unlink( temppath );
219 return( returnval );
220 }
221
222 #ifdef __APPLE__
223
224 /*
225 * Return Value:
226 * -1 - error, do not call closesn
227 * 0 - OKAY
228 * 1 - error, call closesn
229 */
230
231 int
232 retr_applefile( SNET *sn, char *pathdesc, char *path, char *temppath,
233 mode_t tempmode, off_t transize, char *trancksum )
234 {
235 int dfd, rfd;
236 unsigned int md_len;
237 int returnval = -1;
238 off_t size;
239 size_t rsize;
240 ssize_t rc;
241 char finfo[ FINFOLEN ];
242 char buf[ 8192 ];
243 char rsrc_path[ MAXPATHLEN ];
244 char *line;
245 struct as_header ah;
246 extern struct as_header as_header;
247 extern struct attrlist setalist;
248 struct as_entry ae_ents[ 3 ];
249 struct timeval tv;
250 extern EVP_MD *md;
251 EVP_MD_CTX *mdctx;
252 unsigned char md_value[ SZ_BASE64_D( SZ_BASE64_E( EVP_MAX_MD_SIZE ) ) ];
253 char cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ];
254
255 if ( cksum ) {
256 if ( strcmp( trancksum, "-" ) == 0 ) {
257 fprintf( stderr, "line %d: No checksum\n", linenum);
258 fprintf( stderr, "%s\n", pathdesc );
259 return( 1 );
260 }
261 EVP_DigestInit( mdctx, md );
262 }
263
264 if ( verbose ) printf( ">>> RETR %s\n", pathdesc );
265 if ( snet_writef( sn, "RETR %s\n", pathdesc ) < 0 ) {
266 fprintf( stderr, "retrieve applefile %s failed: 1-%s\n", pathdesc,
267 strerror( errno ));
268 return( -1 );
269 }
270
271 tv = timeout;
272 if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) {
273 fprintf( stderr, "retrieve applefile %s failed: 2-%s\n", pathdesc,
274 strerror( errno ));
275 return( -1 );
276 }
277
278 if ( *line != '2' ) {
279 fprintf( stderr, "%s\n", line );
280 return( 1 );
281 }
282
283 /* Get file size from server */
284 tv = timeout;
285 if (( line = snet_getline( sn, &tv )) == NULL ) {
286 fprintf( stderr, "retrieve applefile %s failed: 3-%s\n", pathdesc,
287 strerror( errno ));
288 return( -1 );
289 }
290 size = strtoofft( line, NULL, 10 );
291 if ( verbose ) printf( "<<< %" PRIofft "d\n", size );
292 if ( transize >= 0 && size != transize ) {
293 fprintf( stderr, "line %d: size in transcript does not match size"
294 "from server\n", linenum );
295 fprintf( stderr, "%s\n", pathdesc );
296 return( -1 );
297 }
298 if ( size < ( AS_HEADERLEN + ( 3 * sizeof( struct as_entry )) +
299 FINFOLEN )) {
300 fprintf( stderr,
301 "retrieve applefile %s failed: AppleSingle-encoded file too "
302 "short\n", path );
303 return( -1 );
304 }
305
306 /* read header to determine if file is encoded in applesingle */
307 tv = timeout;
308 if (( rc = snet_read( sn, ( char * )&ah, AS_HEADERLEN, &tv )) <= 0 ) {
309 fprintf( stderr, "retrieve applefile %s failed: 4-%s\n", pathdesc,
310 strerror( errno ));
311 return( -1 );
312 }
313 if (( rc != AS_HEADERLEN ) ||
314 ( memcmp( &as_header, &ah, AS_HEADERLEN ) != 0 )) {
315 fprintf( stderr,
316 "retrieve applefile %s failed: corrupt AppleSingle-encoded file\n",
317 path );
318 return( -1 );
319 }
320 if ( cksum ) {
321 EVP_DigestUpdate( mdctx, (char *)&ah, (unsigned int)rc );
322 }
323
324 /* name temp file */
325 if ( snprintf( temppath, MAXPATHLEN, "%s.radmind.%i", path,
326 getpid()) >= MAXPATHLEN ) {
327 fprintf( stderr, "%s.radmind.%i: too long", path, ( int )getpid());
328 return( -1 );
329 }
330
331 /* data fork must exist to write to rsrc fork */
332 /* Open here so messages from mkprefix don't verbose dots */
333 if (( dfd = open( temppath, O_CREAT | O_EXCL | O_WRONLY, tempmode )) < 0 ) {
334 if ( create_prefix && errno == ENOENT ) {
335 errno = 0;
336 if ( mkprefix( temppath ) != 0 ) {
337 perror( temppath );
338 return( -1 );
339 }
340 if (( dfd = open( temppath, O_CREAT | O_EXCL | O_WRONLY,
341 tempmode )) < 0 ) {
342 perror( temppath );
343 return( -1 );
344 }
345 } else {
346 perror( temppath );
347 return( -1 );
348 }
349 }
350
351 if ( verbose ) printf( "<<< " );
352 if ( dodots ) { putc( '.', stdout ); fflush( stdout ); }
353 size -= rc;
354 if ( showprogress ) {
355 progressupdate( rc, path );
356 }
357
358 /* read header entries */
359 tv = timeout;
360 if (( rc = snet_read( sn, ( char * )&ae_ents,
361 ( 3 * sizeof( struct as_entry )), &tv )) <= 0 ) {
362 fprintf( stderr, "retrieve applefile %s failed: 5-%s\n", pathdesc,
363 strerror( errno ));
364 returnval = -1;
365 goto error2;
366 }
367 if ( rc != ( 3 * sizeof( struct as_entry ))) {
368 fprintf( stderr,
369 "retrieve applefile %s failed: corrupt AppleSingle-encoded file\n",
370 path );
371 returnval = -1;
372 goto error2;
373 }
374
375 /* Should we check for valid ae_ents here? YES! */
376
377 if ( cksum ) {
378 EVP_DigestUpdate( mdctx, (char *)&ae_ents, (unsigned int)rc );
379 }
380 if ( dodots ) { putc( '.', stdout ); fflush( stdout ); }
381
382 size -= rc;
383 if ( showprogress ) {
384 progressupdate( rc, path );
385 }
386
387 /* read finder info */
388 tv = timeout;
389 if (( rc = snet_read( sn, finfo, FINFOLEN, &tv )) <= 0 ) {
390 fprintf( stderr, "retrieve applefile %s failed: 6-%s\n", pathdesc,
391 strerror( errno ));
392 returnval = -1;
393 goto error2;
394 }
395 if ( rc != FINFOLEN ) {
396 fprintf( stderr,
397 "retrieve applefile %s failed: corrupt AppleSingle-encoded file\n",
398 path );
399 returnval = -1;
400 goto error2;
401 }
402 if ( cksum ) {
403 EVP_DigestUpdate( mdctx, finfo, (unsigned int)rc );
404 }
405 if ( dodots ) { putc( '.', stdout ); fflush( stdout ); }
406 size -= rc;
407 if ( showprogress ) {
408 progressupdate( rc, path );
409 }
410
411 /*
412 * endian handling: swap bytes to architecture
413 * native from AppleSingle big-endian.
414 *
415 * This doesn't affect the checksum, since we
416 * already summed the header entries above.
417 */
418 as_entry_hostswap( &ae_ents[ AS_RFE ] );
419
420 if ( ae_ents[ AS_RFE ].ae_length > 0 ) {
421 /* make rsrc fork name */
422 if ( snprintf( rsrc_path, MAXPATHLEN, "%s%s", temppath,
423 _PATH_RSRCFORKSPEC ) >= MAXPATHLEN ) {
424 fprintf( stderr, "%s%s: path too long\n", temppath,
425 _PATH_RSRCFORKSPEC );
426 returnval = -1;
427 goto error2;
428 }
429
430 /* No need to mkprefix as dfd is already present */
431 if (( rfd = open( rsrc_path, O_WRONLY, 0 )) < 0 ) {
432 perror( rsrc_path );
433 returnval = -1;
434 goto error2;
435 }
436
437 for ( rsize = ae_ents[ AS_RFE ].ae_length;
438 rsize > 0; rsize -= rc ) {
439 tv = timeout;
440 if (( rc = snet_read( sn, buf, ( int )MIN( sizeof( buf ), rsize ),
441 &tv )) <= 0 ) {
442 fprintf( stderr, "retrieve applefile %s failed: 7-%s\n",
443 pathdesc, strerror( errno ));
444 returnval = -1;
445 goto error3;
446 }
447 if (( write( rfd, buf, ( unsigned int )rc )) != rc ) {
448 perror( rsrc_path );
449 returnval = -1;
450 goto error3;
451 }
452 if ( cksum ) {
453 EVP_DigestUpdate( mdctx, buf, (unsigned int)rc );
454 }
455 if ( dodots ) { putc( '.', stdout ); fflush( stdout ); }
456 if ( showprogress ) {
457 progressupdate( rc, path );
458 }
459 }
460
461 size -= ae_ents[ AS_RFE ].ae_length;
462
463 if ( close( rfd ) < 0 ) {
464 perror( rsrc_path );
465 goto error2;
466 }
467 }
468
469 /* write data fork to file */
470 for ( rc = 0; size > 0; size -= rc ) {
471 tv = timeout;
472 if (( rc = snet_read( sn, buf, MIN( sizeof( buf ), size ),
473 &tv )) <= 0 ) {
474 fprintf( stderr, "retrieve applefile %s failed: 8-%s\n", pathdesc,
475 strerror( errno ));
476 returnval = -1;
477 goto error2;
478 }
479
480 if ( write( dfd, buf, ( unsigned int )rc ) != rc ) {
481 perror( temppath );
482 returnval = -1;
483 goto error2;
484 }
485
486 if ( cksum ) {
487 EVP_DigestUpdate( mdctx, buf, (unsigned int)rc );
488 }
489 if ( dodots ) { putc( '.', stdout ); fflush( stdout); }
490 if ( showprogress ) {
491 progressupdate( rc, path );
492 }
493 }
494
495 if ( close( dfd ) < 0 ) {
496 perror( temppath );
497 returnval = -1;
498 goto error1;
499 }
500 if ( verbose ) printf( "\n" );
501
502 /* set finder info for newly decoded applefile */
503 if ( setattrlist( temppath, &setalist, finfo, FINFOLEN,
504 FSOPT_NOFOLLOW ) != 0 ) {
505 fprintf( stderr,
506 "retrieve applefile %s failed: Could not set attributes\n",
507 pathdesc );
508 returnval = -1;
509 goto error1;
510 }
511
512 tv = timeout;
513 if (( line = snet_getline( sn, &tv )) == NULL ) {
514 fprintf( stderr, "retrieve applefile %s failed: 9-%s\n", pathdesc,
515 strerror( errno ));
516 returnval = -1;
517 goto error1;
518 }
519 if ( strcmp( line, "." ) != 0 ) {
520 fprintf( stderr, "%s", line );
521 fprintf( stderr, "%s\n", pathdesc );
522 returnval = -1;
523 goto error1;
524 }
525 if ( verbose ) printf( "<<< .\n" );
526
527 if ( cksum ) {
528 EVP_DigestFinal( mdctx, md_value, &md_len );
529 base64_e(( char*)&md_value, md_len, cksum_b64 );
530 EVP_MD_CTX_free(mdctx);
531 if ( strcmp( trancksum, cksum_b64 ) != 0 ) {
532 fprintf( stderr, "line %d: checksum in transcript does not match "
533 "checksum from server\n", linenum );
534 fprintf( stderr, "%s\n", pathdesc );
535 returnval = 1;
536 goto error1;
537 }
538 }
539
540 return( 0 );
541
542 error3:
543 close( rfd );
544 error2:
545 close( dfd );
546 error1:
547 unlink( temppath );
548 return( returnval );
549 }
550
551 #else /* !__APPLE__ */
552
553 int
554 retr_applefile( SNET *sn, char *pathdesc, char *path, char *temppath,
555 mode_t tempmode, off_t transize, char *trancksum )
556 {
557 errno = EINVAL;
558 return( -1 );
559 }
560
561 #endif /* __APPLE__ */