/** * Common routine for: * dir_get_volume_info() * and * dir_find_next_appendable_volume() * * NOTE!!! All calls to this routine must be protected by * locking vol_info_mutex before calling it so that * we don't have one thread modifying the parameters * and another reading them. * * Returns: true on success and vol info in dcr->VolCatInfo * false on failure */ static bool do_get_volume_info(DCR *dcr) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; VOLUME_CAT_INFO vol; int n; int32_t InChanger; dcr->setVolCatInfo(false); if (dir->recv() <= 0) { Dmsg0(dbglvl, "getvolname error bnet_recv\n"); Mmsg(jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n")); return false; } memset(&vol, 0, sizeof(vol)); Dmsg1(dbglvl, "<dird %s", dir->msg); n = sscanf(dir->msg, OK_media, vol.VolCatName, &vol.VolCatJobs, &vol.VolCatFiles, &vol.VolCatBlocks, &vol.VolCatBytes, &vol.VolCatMounts, &vol.VolCatErrors, &vol.VolCatWrites, &vol.VolCatMaxBytes, &vol.VolCatCapacityBytes, vol.VolCatStatus, &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, &InChanger, &vol.VolReadTime, &vol.VolWriteTime, &vol.EndFile, &vol.EndBlock, &vol.LabelType, &vol.VolMediaId, vol.VolEncrKey, &vol.VolMinBlocksize, &vol.VolMaxBlocksize); if (n != 24) { Dmsg3(dbglvl, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg); Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg); return false; } vol.InChanger = InChanger; /* bool in structure */ vol.is_valid = true; unbash_spaces(vol.VolCatName); bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName)); dcr->VolCatInfo = vol; /* structure assignment */ /* * If we received a new crypto key update the cache and write out the new cache on a change. */ if (*vol.VolEncrKey) { if (update_crypto_cache(vol.VolCatName, vol.VolEncrKey)) { write_crypto_cache(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); } } Dmsg4(dbglvl, "do_get_volume_info return true slot=%d Volume=%s, " "VolminBlocksize=%u VolMaxBlocksize=%u\n", vol.Slot, vol.VolCatName, vol.VolMinBlocksize, vol.VolMaxBlocksize); Dmsg2(dbglvl, "setting dcr->VolMinBlocksize(%u) to vol.VolMinBlocksize(%u)\n", dcr->VolMinBlocksize, vol.VolMinBlocksize); Dmsg2(dbglvl, "setting dcr->VolMaxBlocksize(%u) to vol.VolMaxBlocksize(%u)\n", dcr->VolMaxBlocksize, vol.VolMaxBlocksize); /* * Assign the volcatinfo to the dcr. */ dcr->VolMinBlocksize = vol.VolMinBlocksize; dcr->VolMaxBlocksize = vol.VolMaxBlocksize; return true; }
int main(int argc, char *const *argv) { int retval = 0; int ch, kfd, length; bool base64_transform = false, clear_encryption = false, drive_encryption_status = false, generate_passphrase = false, populate_cache = false, set_encryption = false, show_keydata = false, volume_encryption_status = false, wrapped_keys = false; char *keyfile = NULL; char *cache_file = NULL; char *wrap_keyfile = NULL; char keydata[64]; char wrapdata[64]; setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); while ((ch = getopt(argc, argv, "bcd:eg:k:p:s:vw:?")) != -1) { switch (ch) { case 'b': base64_transform = true; break; case 'c': clear_encryption = true; break; case 'd': debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } break; case 'e': drive_encryption_status = true; break; case 'g': generate_passphrase = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'k': show_keydata = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'p': populate_cache = true; cache_file = bstrdup(optarg); break; case 's': set_encryption = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'v': volume_encryption_status = true; break; case 'w': wrapped_keys = true; wrap_keyfile = bstrdup(optarg); break; case '?': default: usage(); goto bail_out; } } argc -= optind; argv += optind; if (!generate_passphrase && !show_keydata && !populate_cache && argc < 1) { fprintf(stderr, _("Missing device_name argument for this option\n")); usage(); retval = 1; goto bail_out; } if (generate_passphrase && show_keydata) { fprintf(stderr, _("Either use -g or -k not both\n")); retval = 1; goto bail_out; } if (clear_encryption && set_encryption) { fprintf(stderr, _("Either use -c or -s not both\n")); retval = 1; goto bail_out; } if ((clear_encryption || set_encryption) && (drive_encryption_status || volume_encryption_status)) { fprintf(stderr, _("Either set or clear the crypto key or ask for status not both\n")); retval = 1; goto bail_out; } if ((clear_encryption || set_encryption || drive_encryption_status || volume_encryption_status) && (generate_passphrase || show_keydata || populate_cache)) { fprintf(stderr, _("Don't mix operations which are incompatible " "e.g. generate/show vs set/clear etc.\n")); retval = 1; goto bail_out; } OSDependentInit(); init_msg(NULL, NULL); if (populate_cache) { char *VolumeName, *EncrKey; char new_cache_entry[256]; /* * Load any keys currently in the cache. */ read_crypto_cache(cache_file); /* * Read new entries from stdin and parse them to update * the cache. */ fprintf(stdout, _("Enter cache entrie(s) (close with ^D): ")); fflush(stdout); while (read(1, new_cache_entry, sizeof(new_cache_entry)) > 0) { strip_trailing_junk(new_cache_entry); /* * Try to parse the entry. */ VolumeName = new_cache_entry; EncrKey = strchr(new_cache_entry, '\t'); if (!EncrKey) { break; } *EncrKey++ = '\0'; update_crypto_cache(VolumeName, EncrKey); } /* * Write out the new cache entries. */ write_crypto_cache(cache_file); goto bail_out; } memset(keydata, 0, sizeof(keydata)); memset(wrapdata, 0, sizeof(wrapdata)); if (wrapped_keys) { /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(wrap_keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Key Encryption Key: ")); fflush(stdout); } else { kfd = open(wrap_keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), wrap_keyfile); retval = 1; goto bail_out; } } read(kfd, wrapdata, sizeof(wrapdata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(wrapdata); Dmsg1(10, "Wrapped keydata = %s\n", wrapdata); } /* * Generate a new passphrase allow it to be wrapped using the given wrapkey * and base64 if specified or when wrapped. */ if (generate_passphrase) { int cnt; char *passphrase; passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH); if (!passphrase) { retval = 1; goto bail_out; } Dmsg1(10, "Generated passphrase = %s\n", passphrase); /* * See if we need to wrap the passphrase. */ if (wrapped_keys) { char *wrapped_passphrase; length = DEFAULT_PASSPHRASE_LENGTH + 8; wrapped_passphrase = (char *)malloc(length); memset(wrapped_passphrase, 0, length); aes_wrap((unsigned char *)wrapdata, DEFAULT_PASSPHRASE_LENGTH / 8, (unsigned char *)passphrase, (unsigned char *)wrapped_passphrase); free(passphrase); passphrase = wrapped_passphrase; } else { length = DEFAULT_PASSPHRASE_LENGTH; } /* * See where to write the key. * - == stdout */ if (bstrcmp(keyfile, "-")) { kfd = 1; } else { kfd = open(keyfile, O_WRONLY | O_CREAT, 0644); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); free(passphrase); retval = 1; goto bail_out; } } if (base64_transform || wrapped_keys) { cnt = bin_to_base64(keydata, sizeof(keydata), passphrase, length, true); if (write(kfd, keydata, cnt) != cnt) { fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile); } } else { cnt = DEFAULT_PASSPHRASE_LENGTH; if (write(kfd, passphrase, cnt) != cnt) { fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile); } } Dmsg1(10, "Keydata = %s\n", keydata); if (kfd > 1) { close(kfd); } else { write(kfd, "\n", 1); } free(passphrase); goto bail_out; } if (show_keydata) { char *passphrase; /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Encryption Key: ")); fflush(stdout); } else { kfd = open(keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); retval = 1; goto bail_out; } } read(kfd, keydata, sizeof(keydata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(keydata); Dmsg1(10, "Keydata = %s\n", keydata); /* * See if we need to unwrap the passphrase. */ if (wrapped_keys) { char *wrapped_passphrase; /* * A wrapped key is base64 encoded after it was wrapped so first * convert it from base64 to bin. As we first go from base64 to bin * and the base64_to_bin has a check if the decoded string will fit * we need to alocate some more bytes for the decoded buffer to be * sure it will fit. */ length = DEFAULT_PASSPHRASE_LENGTH + 12; wrapped_passphrase = (char *)malloc(length); memset(wrapped_passphrase, 0, length); if (base64_to_bin(wrapped_passphrase, length, keydata, strlen(keydata)) == 0) { fprintf(stderr, _("Failed to base64 decode the keydata read from %s, aborting...\n"), keyfile); free(wrapped_passphrase); goto bail_out; } length = DEFAULT_PASSPHRASE_LENGTH; passphrase = (char *)malloc(length); memset(passphrase, 0, length); if (aes_unwrap((unsigned char *)wrapdata, length / 8, (unsigned char *)wrapped_passphrase, (unsigned char *)passphrase) == -1) { fprintf(stderr, _("Failed to aes unwrap the keydata read from %s using the wrap data from %s, aborting...\n"), keyfile, wrap_keyfile); free(wrapped_passphrase); goto bail_out; } free(wrapped_passphrase); } else { if (base64_transform) { /* * As we first go from base64 to bin and the base64_to_bin has a check * if the decoded string will fit we need to alocate some more bytes * for the decoded buffer to be sure it will fit. */ length = DEFAULT_PASSPHRASE_LENGTH + 4; passphrase = (char *)malloc(length); memset(passphrase, 0, length); base64_to_bin(passphrase, length, keydata, strlen(keydata)); } else { length = DEFAULT_PASSPHRASE_LENGTH; passphrase = (char *)malloc(length); memset(passphrase, 0, length); bstrncpy(passphrase, keydata, length); } } Dmsg1(10, "Unwrapped passphrase = %s\n", passphrase); fprintf(stdout, "%s\n", passphrase); free(passphrase); goto bail_out; } /* * Clear the loaded encryption key of the given drive. */ if (clear_encryption) { if (clear_scsi_encryption_key(-1, argv[0])) { goto bail_out; } else { retval = 1; goto bail_out; } } /* * Get the drive encryption status of the given drive. */ if (drive_encryption_status) { POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE); if (get_scsi_drive_encryption_status(-1, argv[0], encryption_status, 0)) { fprintf(stdout, "%s", encryption_status); free_pool_memory(encryption_status); } else { retval = 1; free_pool_memory(encryption_status); goto bail_out; } } /* * Load a new encryption key onto the given drive. */ if (set_encryption) { /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Encryption Key (close with ^D): ")); fflush(stdout); } else { kfd = open(keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); retval = 1; goto bail_out; } } read(kfd, keydata, sizeof(keydata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(keydata); if (set_scsi_encryption_key(-1, argv[0], keydata)) { goto bail_out; } else { retval = 1; goto bail_out; } } /* * Get the volume encryption status of volume currently loaded in the given drive. */ if (volume_encryption_status) { POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE); if (get_scsi_volume_encryption_status(-1, argv[0], encryption_status, 0)) { fprintf(stdout, "%s", encryption_status); free_pool_memory(encryption_status); } else { retval = 1; free_pool_memory(encryption_status); goto bail_out; } } bail_out: if (cache_file) { free(cache_file); } if (keyfile) { free(keyfile); } if (wrap_keyfile) { free(wrap_keyfile); } exit(retval); }