blob: 7e7a9b139847eea19504147c595dc5087de7133a [file] [log] [blame]
Thomas Klausner7ed6a922016-12-16 15:50:12 +01001/*
2 zip_file_set_encryption.c -- set encryption for file in archive
Thomas Klausnere91cc0f2019-03-12 12:39:36 +01003 Copyright (C) 2016-2018 Dieter Baron and Thomas Klausner
Thomas Klausner7ed6a922016-12-16 15:50:12 +01004
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
19 written permission.
Thomas Klausner8eab1a22018-01-15 14:10:11 +010020
Thomas Klausner7ed6a922016-12-16 15:50:12 +010021 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
34
35#include "zipint.h"
36
37#include <stdlib.h>
38#include <string.h>
39
40ZIP_EXTERN int
Thomas Klausner8eab1a22018-01-15 14:10:11 +010041zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
Thomas Klausner7ed6a922016-12-16 15:50:12 +010042 zip_entry_t *e;
43 zip_uint16_t old_method;
44
45 if (idx >= za->nentry) {
46 zip_error_set(&za->error, ZIP_ER_INVAL, 0);
47 return -1;
48 }
49
50 if (ZIP_IS_RDONLY(za)) {
51 zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
52 return -1;
53 }
54
Dieter Baronbfd650a2017-01-29 11:01:30 +010055 if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) {
Thomas Klausner3bd9f992017-01-18 20:50:06 +010056 zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
Thomas Klausner7ed6a922016-12-16 15:50:12 +010057 return -1;
58 }
59
Thomas Klausner8eab1a22018-01-15 14:10:11 +010060 e = za->entry + idx;
61
Thomas Klausner7ed6a922016-12-16 15:50:12 +010062 old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
Thomas Klausner8eab1a22018-01-15 14:10:11 +010063
Thomas Klausner7ed6a922016-12-16 15:50:12 +010064 if (method == old_method && password == NULL) {
65 if (e->changes) {
66 if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
67 _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
68 free(e->changes->password);
Thomas Klausner39e11fa2017-02-19 10:59:09 +010069 e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
Thomas Klausner7ed6a922016-12-16 15:50:12 +010070 }
Thomas Klausner8eab1a22018-01-15 14:10:11 +010071 e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
Thomas Klausner7ed6a922016-12-16 15:50:12 +010072 if (e->changes->changed == 0) {
73 _zip_dirent_free(e->changes);
74 e->changes = NULL;
75 }
76 }
77 }
78 else {
79 char *our_password = NULL;
80
81 if (password) {
82 if ((our_password = strdup(password)) == NULL) {
83 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
84 return -1;
85 }
86 }
Thomas Klausner8eab1a22018-01-15 14:10:11 +010087
88 if (e->changes == NULL) {
89 if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
Thomas Klausner999c8ff2016-12-16 16:03:34 +010090 if (our_password) {
91 _zip_crypto_clear(our_password, strlen(our_password));
92 }
Thomas Klausner7ed6a922016-12-16 15:50:12 +010093 free(our_password);
Thomas Klausner8eab1a22018-01-15 14:10:11 +010094 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
95 return -1;
96 }
97 }
Thomas Klausner7ed6a922016-12-16 15:50:12 +010098
Thomas Klausner8eab1a22018-01-15 14:10:11 +010099 e->changes->encryption_method = method;
100 e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
Thomas Klausner7ed6a922016-12-16 15:50:12 +0100101 if (password) {
102 e->changes->password = our_password;
103 e->changes->changed |= ZIP_DIRENT_PASSWORD;
104 }
105 else {
106 if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
107 _zip_crypto_clear(e->changes->password, strlen(e->changes->password));
108 free(e->changes->password);
Thomas Klausnerbd0fe202016-12-16 16:02:26 +0100109 e->changes->password = e->orig ? e->orig->password : NULL;
Thomas Klausner7ed6a922016-12-16 15:50:12 +0100110 e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
111 }
112 }
113 }
Thomas Klausner8eab1a22018-01-15 14:10:11 +0100114
Thomas Klausner7ed6a922016-12-16 15:50:12 +0100115 return 0;
116}