geom_eli.c (212554) | geom_eli.c (212934) |
---|---|
1/*- 2 * Copyright (c) 2004-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org> 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 --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2004-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org> 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 --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sbin/geom/class/eli/geom_eli.c 212554 2010-09-13 13:48:18Z pjd $"); | 28__FBSDID("$FreeBSD: head/sbin/geom/class/eli/geom_eli.c 212934 2010-09-20 22:04:59Z brian $"); |
29 30#include <stdio.h> 31#include <stdint.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <fcntl.h> 35#include <readpassphrase.h> 36#include <string.h> --- 24 unchanged lines hidden (view full) --- 61static void eli_init(struct gctl_req *req); 62static void eli_attach(struct gctl_req *req); 63static void eli_configure(struct gctl_req *req); 64static void eli_setkey(struct gctl_req *req); 65static void eli_delkey(struct gctl_req *req); 66static void eli_kill(struct gctl_req *req); 67static void eli_backup(struct gctl_req *req); 68static void eli_restore(struct gctl_req *req); | 29 30#include <stdio.h> 31#include <stdint.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <fcntl.h> 35#include <readpassphrase.h> 36#include <string.h> --- 24 unchanged lines hidden (view full) --- 61static void eli_init(struct gctl_req *req); 62static void eli_attach(struct gctl_req *req); 63static void eli_configure(struct gctl_req *req); 64static void eli_setkey(struct gctl_req *req); 65static void eli_delkey(struct gctl_req *req); 66static void eli_kill(struct gctl_req *req); 67static void eli_backup(struct gctl_req *req); 68static void eli_restore(struct gctl_req *req); |
69static void eli_resize(struct gctl_req *req); |
|
69static void eli_clear(struct gctl_req *req); 70static void eli_dump(struct gctl_req *req); 71 72static int eli_backup_create(struct gctl_req *req, const char *prov, 73 const char *file); 74 75/* 76 * Available commands: --- 4 unchanged lines hidden (view full) --- 81 * detach [-fl] prov ... 82 * stop - alias for 'detach' 83 * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov 84 * configure [-bB] prov ... 85 * setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov 86 * delkey [-afv] [-n keyno] prov 87 * kill [-av] [prov ...] 88 * backup [-v] prov file | 70static void eli_clear(struct gctl_req *req); 71static void eli_dump(struct gctl_req *req); 72 73static int eli_backup_create(struct gctl_req *req, const char *prov, 74 const char *file); 75 76/* 77 * Available commands: --- 4 unchanged lines hidden (view full) --- 82 * detach [-fl] prov ... 83 * stop - alias for 'detach' 84 * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov 85 * configure [-bB] prov ... 86 * setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov 87 * delkey [-afv] [-n keyno] prov 88 * kill [-av] [prov ...] 89 * backup [-v] prov file |
89 * restore [-v] file prov | 90 * restore [-fv] file prov 91 * resize [-v] -s oldsize prov |
90 * clear [-v] prov ... 91 * dump [-v] prov ... 92 */ 93struct g_command class_commands[] = { 94 { "init", G_FLAG_VERBOSE, eli_main, 95 { 96 { 'a', "aalgo", "", G_TYPE_STRING }, 97 { 'b', "boot", NULL, G_TYPE_BOOL }, --- 94 unchanged lines hidden (view full) --- 192 { 'a', "all", NULL, G_TYPE_BOOL }, 193 G_OPT_SENTINEL 194 }, 195 "[-av] [prov ...]" 196 }, 197 { "backup", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 198 "[-v] prov file" 199 }, | 92 * clear [-v] prov ... 93 * dump [-v] prov ... 94 */ 95struct g_command class_commands[] = { 96 { "init", G_FLAG_VERBOSE, eli_main, 97 { 98 { 'a', "aalgo", "", G_TYPE_STRING }, 99 { 'b', "boot", NULL, G_TYPE_BOOL }, --- 94 unchanged lines hidden (view full) --- 194 { 'a', "all", NULL, G_TYPE_BOOL }, 195 G_OPT_SENTINEL 196 }, 197 "[-av] [prov ...]" 198 }, 199 { "backup", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 200 "[-v] prov file" 201 }, |
200 { "restore", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 201 "[-v] file prov" | 202 { "restore", G_FLAG_VERBOSE, eli_main, 203 { 204 { 'f', "force", NULL, G_TYPE_BOOL }, 205 G_OPT_SENTINEL 206 }, 207 "[-fv] file prov" |
202 }, | 208 }, |
209 { "resize", G_FLAG_VERBOSE, eli_main, 210 { 211 { 's', "oldsize", NULL, G_TYPE_NUMBER }, 212 G_OPT_SENTINEL 213 }, 214 "[-v] -s oldsize prov" 215 }, |
|
203 { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 204 "[-v] prov ..." 205 }, 206 { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 207 "[-v] prov ..." 208 }, 209 G_CMD_SENTINEL 210}; --- 48 unchanged lines hidden (view full) --- 259 else if (strcmp(name, "delkey") == 0) 260 eli_delkey(req); 261 else if (strcmp(name, "kill") == 0) 262 eli_kill(req); 263 else if (strcmp(name, "backup") == 0) 264 eli_backup(req); 265 else if (strcmp(name, "restore") == 0) 266 eli_restore(req); | 216 { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 217 "[-v] prov ..." 218 }, 219 { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 220 "[-v] prov ..." 221 }, 222 G_CMD_SENTINEL 223}; --- 48 unchanged lines hidden (view full) --- 272 else if (strcmp(name, "delkey") == 0) 273 eli_delkey(req); 274 else if (strcmp(name, "kill") == 0) 275 eli_kill(req); 276 else if (strcmp(name, "backup") == 0) 277 eli_backup(req); 278 else if (strcmp(name, "restore") == 0) 279 eli_restore(req); |
280 else if (strcmp(name, "resize") == 0) 281 eli_resize(req); |
|
267 else if (strcmp(name, "dump") == 0) 268 eli_dump(req); 269 else if (strcmp(name, "clear") == 0) 270 eli_clear(req); 271 else 272 gctl_error(req, "Unknown command: %s.", name); 273} 274 --- 403 unchanged lines hidden (view full) --- 678} 679 680static void 681eli_attach(struct gctl_req *req) 682{ 683 struct g_eli_metadata md; 684 unsigned char key[G_ELI_USERKEYLEN]; 685 const char *prov; | 282 else if (strcmp(name, "dump") == 0) 283 eli_dump(req); 284 else if (strcmp(name, "clear") == 0) 285 eli_clear(req); 286 else 287 gctl_error(req, "Unknown command: %s.", name); 288} 289 --- 403 unchanged lines hidden (view full) --- 693} 694 695static void 696eli_attach(struct gctl_req *req) 697{ 698 struct g_eli_metadata md; 699 unsigned char key[G_ELI_USERKEYLEN]; 700 const char *prov; |
701 off_t mediasize; |
|
686 int nargs; 687 688 nargs = gctl_get_int(req, "nargs"); 689 if (nargs != 1) { 690 gctl_error(req, "Invalid number of arguments."); 691 return; 692 } 693 prov = gctl_get_ascii(req, "arg0"); 694 695 if (eli_metadata_read(req, prov, &md) == -1) 696 return; 697 | 702 int nargs; 703 704 nargs = gctl_get_int(req, "nargs"); 705 if (nargs != 1) { 706 gctl_error(req, "Invalid number of arguments."); 707 return; 708 } 709 prov = gctl_get_ascii(req, "arg0"); 710 711 if (eli_metadata_read(req, prov, &md) == -1) 712 return; 713 |
714 mediasize = g_get_mediasize(prov); 715 if (md.md_provsize != (uint64_t)mediasize) { 716 gctl_error(req, "Provider size mismatch."); 717 return; 718 } 719 |
|
698 if (eli_genkey(req, &md, key, 0) == NULL) { 699 bzero(key, sizeof(key)); 700 return; 701 } 702 703 gctl_ro_param(req, "key", sizeof(key), key); 704 if (gctl_issue(req) == NULL) { 705 if (verbose) --- 501 unchanged lines hidden (view full) --- 1207 strerror(errno)); 1208 goto out; 1209 } 1210 /* Check if this file contains geli metadata. */ 1211 if (eli_metadata_decode(sector, &md) != 0) { 1212 gctl_error(req, "MD5 hash mismatch: not a geli backup file?"); 1213 goto out; 1214 } | 720 if (eli_genkey(req, &md, key, 0) == NULL) { 721 bzero(key, sizeof(key)); 722 return; 723 } 724 725 gctl_ro_param(req, "key", sizeof(key), key); 726 if (gctl_issue(req) == NULL) { 727 if (verbose) --- 501 unchanged lines hidden (view full) --- 1229 strerror(errno)); 1230 goto out; 1231 } 1232 /* Check if this file contains geli metadata. */ 1233 if (eli_metadata_decode(sector, &md) != 0) { 1234 gctl_error(req, "MD5 hash mismatch: not a geli backup file?"); 1235 goto out; 1236 } |
1237 /* Check if the provider size has changed since we did the backup. */ 1238 if (md.md_provsize != (uint64_t)mediasize) { 1239 if (gctl_get_int(req, "force")) { 1240 md.md_provsize = mediasize; 1241 eli_metadata_encode(&md, sector); 1242 } else { 1243 gctl_error(req, "Provider size mismatch: " 1244 "wrong backup file?"); 1245 goto out; 1246 } 1247 } |
|
1215 /* Write metadata from the provider. */ 1216 if (pwrite(provfd, sector, secsize, mediasize - secsize) != 1217 (ssize_t)secsize) { 1218 gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); 1219 goto out; 1220 } 1221out: 1222 if (provfd > 0) 1223 close(provfd); 1224 if (filefd > 0) 1225 close(filefd); 1226 if (sector != NULL) { 1227 bzero(sector, secsize); 1228 free(sector); 1229 } 1230} 1231 1232static void | 1248 /* Write metadata from the provider. */ 1249 if (pwrite(provfd, sector, secsize, mediasize - secsize) != 1250 (ssize_t)secsize) { 1251 gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); 1252 goto out; 1253 } 1254out: 1255 if (provfd > 0) 1256 close(provfd); 1257 if (filefd > 0) 1258 close(filefd); 1259 if (sector != NULL) { 1260 bzero(sector, secsize); 1261 free(sector); 1262 } 1263} 1264 1265static void |
1266eli_resize(struct gctl_req *req) 1267{ 1268 struct g_eli_metadata md; 1269 const char *prov; 1270 unsigned char *sector; 1271 unsigned secsize; 1272 off_t mediasize, oldsize; 1273 int nargs, provfd; 1274 1275 nargs = gctl_get_int(req, "nargs"); 1276 if (nargs != 1) { 1277 gctl_error(req, "Invalid number of arguments."); 1278 return; 1279 } 1280 prov = gctl_get_ascii(req, "arg0"); 1281 1282 provfd = -1; 1283 sector = NULL; 1284 secsize = 0; 1285 1286 provfd = open(prov, O_RDWR); 1287 if (provfd == -1 && errno == ENOENT && prov[0] != '/') { 1288 char devprov[MAXPATHLEN]; 1289 1290 snprintf(devprov, sizeof(devprov), "%s%s", _PATH_DEV, prov); 1291 provfd = open(devprov, O_RDWR); 1292 } 1293 if (provfd == -1) { 1294 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1295 goto out; 1296 } 1297 1298 mediasize = g_get_mediasize(prov); 1299 secsize = g_get_sectorsize(prov); 1300 if (mediasize == 0 || secsize == 0) { 1301 gctl_error(req, "Cannot get information about %s: %s.", prov, 1302 strerror(errno)); 1303 goto out; 1304 } 1305 1306 sector = malloc(secsize); 1307 if (sector == NULL) { 1308 gctl_error(req, "Cannot allocate memory."); 1309 goto out; 1310 } 1311 1312 oldsize = gctl_get_intmax(req, "oldsize"); 1313 if (oldsize < 0 || oldsize > mediasize) { 1314 gctl_error(req, "Invalid oldsize: Out of range."); 1315 goto out; 1316 } 1317 1318 /* Read metadata from the 'oldsize' offset. */ 1319 if (pread(provfd, sector, secsize, oldsize - secsize) != 1320 (ssize_t)secsize) { 1321 gctl_error(req, "Cannot read old metadata: %s.", 1322 strerror(errno)); 1323 goto out; 1324 } 1325 1326 /* Check if this sector contains geli metadata. */ 1327 if (eli_metadata_decode(sector, &md) != 0) { 1328 gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); 1329 goto out; 1330 } 1331 1332 /* 1333 * If the old metadata doesn't have a correct provider size, refuse 1334 * to resize. 1335 */ 1336 if (md.md_provsize != (uint64_t)oldsize) { 1337 gctl_error(req, "Provider size mismatch at oldsize."); 1338 goto out; 1339 } 1340 1341 /* 1342 * Update the old metadata with the current provider size and write 1343 * it back to the correct place on the provider. 1344 */ 1345 md.md_provsize = mediasize; 1346 eli_metadata_encode(&md, sector); 1347 if (pwrite(provfd, sector, secsize, mediasize - secsize) != 1348 (ssize_t)secsize) { 1349 gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); 1350 goto out; 1351 } 1352 1353 /* Now trash the old metadata. */ 1354 arc4rand(sector, secsize); 1355 if (pwrite(provfd, sector, secsize, oldsize - secsize) != 1356 (ssize_t)secsize) { 1357 gctl_error(req, "Failed to clobber old metadata: %s.", 1358 strerror(errno)); 1359 goto out; 1360 } 1361out: 1362 if (provfd > 0) 1363 close(provfd); 1364 if (sector != NULL) { 1365 bzero(sector, secsize); 1366 free(sector); 1367 } 1368} 1369 1370static void |
|
1233eli_clear(struct gctl_req *req) 1234{ 1235 const char *name; 1236 int error, i, nargs; 1237 1238 nargs = gctl_get_int(req, "nargs"); 1239 if (nargs < 1) { 1240 gctl_error(req, "Too few arguments."); --- 51 unchanged lines hidden --- | 1371eli_clear(struct gctl_req *req) 1372{ 1373 const char *name; 1374 int error, i, nargs; 1375 1376 nargs = gctl_get_int(req, "nargs"); 1377 if (nargs < 1) { 1378 gctl_error(req, "Too few arguments."); --- 51 unchanged lines hidden --- |