Deleted Added
full compact
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 ---