1 /*- 2 * Copyright (c) 2014 Michihiro NAKAJIMA 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "archive_platform.h" 27 28 #ifdef HAVE_ERRNO_H 29 #include <errno.h> 30 #endif 31 #include "archive_read_private.h" 32 33 static void 34 add_passphrase_to_tail(struct archive_read *a, 35 struct archive_read_passphrase *p) 36 { 37 *a->passphrases.last = p; 38 a->passphrases.last = &p->next; 39 p->next = NULL; 40 } 41 42 static struct archive_read_passphrase * 43 remove_passphrases_from_head(struct archive_read *a) 44 { 45 struct archive_read_passphrase *p; 46 47 p = a->passphrases.first; 48 if (p != NULL) 49 a->passphrases.first = p->next; 50 return (p); 51 } 52 53 static void 54 insert_passphrase_to_head(struct archive_read *a, 55 struct archive_read_passphrase *p) 56 { 57 p->next = a->passphrases.first; 58 a->passphrases.first = p; 59 if (&a->passphrases.first == a->passphrases.last) { 60 a->passphrases.last = &p->next; 61 p->next = NULL; 62 } 63 } 64 65 static struct archive_read_passphrase * 66 new_read_passphrase(struct archive_read *a, const char *passphrase) 67 { 68 struct archive_read_passphrase *p; 69 70 p = malloc(sizeof(*p)); 71 if (p == NULL) { 72 archive_set_error(&a->archive, ENOMEM, 73 "Can't allocate memory"); 74 return (NULL); 75 } 76 p->passphrase = strdup(passphrase); 77 if (p->passphrase == NULL) { 78 free(p); 79 archive_set_error(&a->archive, ENOMEM, 80 "Can't allocate memory"); 81 return (NULL); 82 } 83 return (p); 84 } 85 86 int 87 archive_read_add_passphrase(struct archive *_a, const char *passphrase) 88 { 89 struct archive_read *a = (struct archive_read *)_a; 90 struct archive_read_passphrase *p; 91 92 archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 93 "archive_read_add_passphrase"); 94 95 if (passphrase == NULL || passphrase[0] == '\0') { 96 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 97 "Empty passphrase is unacceptable"); 98 return (ARCHIVE_FAILED); 99 } 100 101 p = new_read_passphrase(a, passphrase); 102 if (p == NULL) 103 return (ARCHIVE_FATAL); 104 add_passphrase_to_tail(a, p); 105 106 return (ARCHIVE_OK); 107 } 108 109 int 110 archive_read_set_passphrase_callback(struct archive *_a, void *client_data, 111 archive_passphrase_callback *cb) 112 { 113 struct archive_read *a = (struct archive_read *)_a; 114 115 archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, 116 "archive_read_set_passphrase_callback"); 117 118 a->passphrases.callback = cb; 119 a->passphrases.client_data = client_data; 120 return (ARCHIVE_OK); 121 } 122 123 /* 124 * Call this in advance when you start to get a passphrase for decryption 125 * for a entry. 126 */ 127 void 128 __archive_read_reset_passphrase(struct archive_read *a) 129 { 130 131 a->passphrases.candidate = -1; 132 } 133 134 /* 135 * Get a passphrase for decryption. 136 */ 137 const char * 138 __archive_read_next_passphrase(struct archive_read *a) 139 { 140 struct archive_read_passphrase *p; 141 const char *passphrase; 142 143 if (a->passphrases.candidate < 0) { 144 /* Count out how many passphrases we have. */ 145 int cnt = 0; 146 147 for (p = a->passphrases.first; p != NULL; p = p->next) 148 cnt++; 149 a->passphrases.candidate = cnt; 150 p = a->passphrases.first; 151 } else if (a->passphrases.candidate > 1) { 152 /* Rotate a passphrase list. */ 153 a->passphrases.candidate--; 154 p = remove_passphrases_from_head(a); 155 add_passphrase_to_tail(a, p); 156 /* Pick a new passphrase candidate up. */ 157 p = a->passphrases.first; 158 } else if (a->passphrases.candidate == 1) { 159 /* This case is that all candidates failed to decrypt. */ 160 a->passphrases.candidate = 0; 161 if (a->passphrases.first->next != NULL) { 162 /* Rotate a passphrase list. */ 163 p = remove_passphrases_from_head(a); 164 add_passphrase_to_tail(a, p); 165 } 166 p = NULL; 167 } else /* There is no passphrase candidate. */ 168 p = NULL; 169 170 if (p != NULL) 171 passphrase = p->passphrase; 172 else if (a->passphrases.callback != NULL) { 173 /* Get a passphrase through a call-back function 174 * since we tried all passphrases out or we don't 175 * have it. */ 176 passphrase = a->passphrases.callback(&a->archive, 177 a->passphrases.client_data); 178 if (passphrase != NULL) { 179 p = new_read_passphrase(a, passphrase); 180 if (p == NULL) 181 return (NULL); 182 insert_passphrase_to_head(a, p); 183 a->passphrases.candidate = 1; 184 } 185 } else 186 passphrase = NULL; 187 188 return (passphrase); 189 } 190