Example #1
0
static void inserthashindex(struct CACHE_HEADER *cache,
			struct CACHED_GENERIC *current)
{
	int h;
	struct HASH_ENTRY *link;
	struct HASH_ENTRY *first;

	if (cache->dohash) {
		h = cache->dohash(current);
		if ((h >= 0) && (h < cache->max_hash)) {
			/* get a free link and insert at top of hash list */
			link = cache->free_hash;
			if (link) {
				cache->free_hash = link->next;
				first = cache->first_hash[h];
				if (first)
					link->next = first;
				else
					link->next = NULL;
				link->entry = current;
				cache->first_hash[h] = link;
			} else {
				ntfs_log_error("No more hash entries,"
						" cache %s hashing dropped\n",
						cache->name);
				cache->dohash = (cache_hash)NULL;
			}
		} else {
			ntfs_log_error("Illegal hash value,"
						" cache %s hashing dropped\n",
						cache->name);
			cache->dohash = (cache_hash)NULL;
		}
	}
}
Example #2
0
/**
 * ntfs_pkcs12_load_pfxfile
 */
static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
                                    unsigned *pfx_size)
{
    int f, to_read, total, attempts, br;
    struct stat key_stat;

    if (!keyfile || !pfx || !pfx_size) {
        ntfs_log_error("You have to specify the key file, a pointer "
                       "to hold the key file contents, and a pointer "
                       "to hold the size of the key file contents.\n");
        return -1;
    }
    f = open(keyfile, O_RDONLY);
    if (f == -1) {
        ntfs_log_perror("Failed to open key file");
        return -1;
    }
    if (fstat(f, &key_stat) == -1) {
        ntfs_log_perror("Failed to stat key file");
        goto file_out;
    }
    if (!S_ISREG(key_stat.st_mode)) {
        ntfs_log_error("Key file is not a regular file, cannot read "
                       "it.\n");
        goto file_out;
    }
    if (!key_stat.st_size) {
        ntfs_log_error("Key file has zero size.\n");
        goto file_out;
    }
    *pfx = malloc(key_stat.st_size + 1);
    if (!*pfx) {
        ntfs_log_perror("Failed to allocate buffer for key file "
                        "contents");
        goto file_out;
    }
    to_read = key_stat.st_size;
    total = attempts = 0;
    do {
        br = read(f, *pfx + total, to_read);
        if (br == -1) {
            ntfs_log_perror("Failed to read from key file");
            goto free_out;
        }
        if (!br)
            attempts++;
        to_read -= br;
        total += br;
    } while (to_read > 0 && attempts < 3);
    close(f);
    /* Make sure it is zero terminated. */
    (*pfx)[key_stat.st_size] = 0;
    *pfx_size = key_stat.st_size;
    return 0;
free_out:
    free(*pfx);
file_out:
    close(f);
    return -1;
}
Example #3
0
static int ntfs_ia_check(ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn)
{
	u32 ib_size = (unsigned)le32_to_cpu(ib->index.allocated_size) + 0x18;
	
	ntfs_log_trace("Entering\n");
	
	if (!ntfs_is_indx_record(ib->magic)) {
		
		ntfs_log_error("Corrupt index block signature: vcn %lld inode "
			       "%llu\n", (long long)vcn,
			       (unsigned long long)icx->ni->mft_no);
		return -1;
	}
	
	if (sle64_to_cpu(ib->index_block_vcn) != vcn) {
		
		ntfs_log_error("Corrupt index block: VCN (%lld) is different "
			       "from expected VCN (%lld) in inode %llu\n",
			       (long long)sle64_to_cpu(ib->index_block_vcn),
			       (long long)vcn,
			       (unsigned long long)icx->ni->mft_no);
		return -1;
	}
	
	if (ib_size != icx->block_size) {
		
		ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu "
			       "has a size (%u) differing from the index "
			       "specified size (%u)\n", (long long)vcn, 
			       (unsigned long long)icx->ni->mft_no, ib_size,
			       icx->block_size);
		return -1;
	}
	return 0;
}
Example #4
0
static int parse_options(int argc, char *argv[])
{
	int c;

	static const char *sopt = "-hrw";
	static const struct option lopt[] = {
		{ "readonly",	no_argument,	NULL, 'r' },
		{ "readwrite",	no_argument,	NULL, 'w' },
		{ "help",	no_argument,	NULL, 'h' },
		{ NULL,		0,		NULL,  0  }
	};

	opterr = 0; /* We handle errors. */
	opts.probetype = PROBE_UNSET;

	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
		switch (c) {
		case 1:	/* A non-option argument */
			if (!opts.device) {
				opts.device = ntfs_malloc(PATH_MAX + 1);
				if (!opts.device)
					return -1;
				
				strncpy(opts.device, optarg, PATH_MAX);
				opts.device[PATH_MAX] = 0;
			} else {
				ntfs_log_error("%s: You must specify exactly "
					       "one device\n", EXEC_NAME);
				return -1;
			}
			break;
		case 'h':
			usage();
			exit(0);
		case 'r':
			opts.probetype = PROBE_READONLY;
			break;
		case 'w':
			opts.probetype = PROBE_READWRITE;
			break;
		default:
			ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
				       argv[optind - 1]);
			return -1;
		}
	}

	if (!opts.device) {
		ntfs_log_error("ERROR: %s: Device is missing\n", EXEC_NAME);
		return -1;
	}

	if (opts.probetype == PROBE_UNSET) {
		ntfs_log_error("ERROR: %s: Probe type is missing\n", EXEC_NAME);
		return -1;
	}

	return 0;
}
Example #5
0
static int update_object_id(ntfs_inode *ni, ntfs_index_context *xo,
			const OBJECT_ID_ATTR *value, size_t size)
{
	OBJECT_ID_ATTR old_attr;
	ntfs_attr *na;
	int oldsize;
	int written;
	int res;

	res = 0;

	na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
	if (na) {

			/* remove the existing index entry */
		oldsize = remove_object_id_index(na,xo,&old_attr);
		if (oldsize < 0)
			res = -1;
		else {
			/* resize attribute */
			res = ntfs_attr_truncate(na, (s64)sizeof(GUID));
				/* write the object_id in attribute */
			if (!res && value) {
				written = (int)ntfs_attr_pwrite(na,
					(s64)0, (s64)sizeof(GUID),
					&value->object_id);
				if (written != (s64)sizeof(GUID)) {
					ntfs_log_error("Failed to update "
							"object id\n");
					errno = EIO;
					res = -1;
				}
			}
				/* write index part if provided */
			if (!res
			    && ((size < sizeof(OBJECT_ID_ATTR))
				 || set_object_id_index(ni,xo,value))) {
				/*
				 * If cannot index, try to remove the object
				 * id and log the error. There will be an
				 * inconsistency if removal fails.
				 */
				ntfs_attr_rm(na);
				ntfs_log_error("Failed to index object id."
						" Possible corruption.\n");
			}
		}
		ntfs_attr_close(na);
		NInoSetDirty(ni);
	} else
		res = -1;
	return (res);
}
Example #6
0
void utils_mount_error(const char *volume, const char *mntpoint, int err)
{
	switch (err) {
		case NTFS_VOLUME_NOT_NTFS:
			ntfs_log_error(invalid_ntfs_msg, volume);
			break;
		case NTFS_VOLUME_CORRUPT:
			ntfs_log_error("%s", corrupt_volume_msg);
			break;
		case NTFS_VOLUME_HIBERNATED:
			ntfs_log_error(hibernated_volume_msg, volume, mntpoint);
			break;
		case NTFS_VOLUME_UNCLEAN_UNMOUNT:
			ntfs_log_error(unclean_journal_msg);
			ntfs_log_error(forced_mount_msg, volume, mntpoint, 
				       volume, mntpoint);
			break;
		case NTFS_VOLUME_LOCKED:
			ntfs_log_error("%s", opened_volume_msg);
			break;
		case NTFS_VOLUME_RAID:
			ntfs_log_error("%s", fakeraid_msg);
			break;
		case NTFS_VOLUME_NO_PRIVILEGE:
			ntfs_log_error(access_denied_msg, volume);
			break;
	}
}
Example #7
0
static int update_reparse_data(ntfs_inode *ni, ntfs_index_context *xr,
			const char *value, size_t size)
{
	int res;
	int written;
	int oldsize;
	ntfs_attr *na;
	le32 reparse_tag;

	res = 0;
	na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
	if (na) {
			/* remove the existing reparse data */
		oldsize = remove_reparse_index(na,xr,&reparse_tag);
		if (oldsize < 0)
			res = -1;
		else {
			/* resize attribute */
			res = ntfs_attr_truncate(na, (s64)size);
			/* overwrite value if any */
			if (!res && value) {
				written = (int)ntfs_attr_pwrite(na,
						 (s64)0, (s64)size, value);
				if (written != (s64)size) {
					ntfs_log_error("Failed to update "
						"reparse data\n");
					errno = EIO;
					res = -1;
				}
			}
			if (!res
			    && set_reparse_index(ni,xr,
				((const REPARSE_POINT*)value)->reparse_tag)
			    && (oldsize > 0)) {
				/*
				 * If cannot index, try to remove the reparse
				 * data and log the error. There will be an
				 * inconsistency if removal fails.
				 */
				ntfs_attr_rm(na);
				ntfs_log_error("Failed to index reparse data."
						" Possible corruption.\n");
			}
		}
		ntfs_attr_close(na);
		NInoSetDirty(ni);
	} else
		res = -1;
	return (res);
}
Example #8
0
/**
 * ntfs_desx_decrypt
 */
static void ntfs_desx_decrypt(ntfs_fek *fek, u8 *outbuf, const u8 *inbuf)
{
    gcry_error_t err;
    ntfs_desx_ctx *ctx = &fek->desx_ctx;

    err = gcry_cipher_reset(fek->gcry_cipher_hd);
    if (err != GPG_ERR_NO_ERROR)
        ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
                       err);
    *(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening;
    err = gcry_cipher_encrypt(fek->gcry_cipher_hd, outbuf, 8, NULL, 0);
    if (err != GPG_ERR_NO_ERROR)
        ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
    *(u64*)outbuf ^= ctx->in_whitening;
}
Example #9
0
/**
 * ntfs_rsa_private_key_import_from_gnutls
 */
static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
    gnutls_x509_privkey_t priv_key)
{
    int i, j;
    size_t tmp_size;
    gnutls_datum_t rd[6];
    gcry_mpi_t rm[6];
    gcry_sexp_t rsa_key;

    /* Extract the RSA parameters from the GNU TLS private key. */
    if (gnutls_x509_privkey_export_rsa_raw(priv_key, &rd[0], &rd[1],
                                           &rd[2], &rd[3], &rd[4], &rd[5])) {
        ntfs_log_error("Failed to export rsa parameters.  (Is the "
                       "key an RSA private key?)\n");
        return NULL;
    }
    /* Convert each RSA parameter to mpi format. */
    for (i = 0; i < 6; i++) {
        if (gcry_mpi_scan(&rm[i], GCRYMPI_FMT_USG, rd[i].data,
                          rd[i].size, &tmp_size) != GPG_ERR_NO_ERROR) {
            ntfs_log_error("Failed to convert RSA parameter %i "
                           "to mpi format (size %d)\n", i,
                           rd[i].size);
            rsa_key = NULL;
            break;
        }
    }
    /* Release the no longer needed datum values. */
    for (j = 0; j < 6; j++) {
        if (rd[j].data && rd[j].size)
            gnutls_free(rd[j].data);
    }
    /*
     * Build the gcrypt private key, note libgcrypt uses p and q inversed
     * to what gnutls uses.
     */
    if (i == 6 && gcry_sexp_build(&rsa_key, NULL,
                                  "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
                                  rm[0], rm[1], rm[2], rm[4], rm[3], rm[5]) !=
            GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to build RSA private key s-exp.\n");
        rsa_key = NULL;
    }
    /* Release the no longer needed mpi values. */
    for (j = 0; j < i; j++)
        gcry_mpi_release(rm[j]);
    return (ntfs_rsa_private_key)rsa_key;
}
Example #10
0
static int ntfs_merge_allocation(ntfs_attr *na, runlist_element *rl,
				s64 size)
{
	ntfs_volume *vol;
	int err;

	err = 0;
	vol = na->ni->vol;
	/* Newly allocated clusters before initialized size need be zeroed */
	if ((rl->vcn << vol->cluster_size_bits) < na->initialized_size) {
		err = ntfs_inner_zero(na, rl);
	}
	if (!err) {
		if (na->data_flags & ATTR_IS_SPARSE) {
			na->compressed_size += size;
			if (na->compressed_size >= na->allocated_size) {
				na->data_flags &= ~ATTR_IS_SPARSE;
				if (na->compressed_size > na->allocated_size) {
					ntfs_log_error("File size error : "
						"apparent %lld, "
						"compressed %lld > "
						"allocated %lld",
						(long long)na->data_size,
						(long long)na->compressed_size,
						(long long)na->allocated_size);
					errno = EIO;
					err = -1;
				}
			}
		}
	}
	if (!err) {
		rl = ntfs_runlists_merge(na->rl, rl);
		if (!rl) {
			ntfs_log_error("Failed to merge the new allocation\n");
			err = -1;
		} else {
			na->rl = rl;
				/* Update the runlist */
			if (ntfs_attr_update_mapping_pairs(na, 0)) {
				ntfs_log_error(
					"Failed to update the runlist\n");
				err = -1;
			}
		}
	}
	return (err);
}
Example #11
0
/**
 * ntfs_des_test
 */
static BOOL ntfs_des_test(void)
{
    const u8 known_des_key[8] = {
        0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f
    };
    const u8 known_des_encrypted_data[8] = {
        0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f
    };
    const u8 known_decrypted_data[8] = {
        0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09
    };
    u8 test_decrypted_data[8];
    int res;
    gcry_error_t err;
    gcry_cipher_hd_t gcry_cipher_hd;

    err = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_DES,
                           GCRY_CIPHER_MODE_ECB, 0);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
                       err);
        return FALSE;
    }
    err = gcry_cipher_setkey(gcry_cipher_hd, known_des_key,
                             sizeof(known_des_key));
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to set des key (error 0x%x.\n", err);
        gcry_cipher_close(gcry_cipher_hd);
        return FALSE;
    }
    /*
     * Apply DES decryption (ntfs actually uses encryption when decrypting).
     */
    err = gcry_cipher_encrypt(gcry_cipher_hd, test_decrypted_data,
                              sizeof(test_decrypted_data), known_des_encrypted_data,
                              sizeof(known_des_encrypted_data));
    gcry_cipher_close(gcry_cipher_hd);
    if (err) {
        ntfs_log_error("Failed to des decrypt test data (error "
                       "0x%x).\n", err);
        return FALSE;
    }
    res = !memcmp(test_decrypted_data, known_decrypted_data,
                  sizeof(known_decrypted_data));
    ntfs_log_error("Testing whether des decryption works: %s\n",
                   res ? "SUCCESS" : "FAILED");
    return res;
}
Example #12
0
/**
 * ntfs_inode_update_times - update selected time fields for ntfs inode
 * @ni:		ntfs inode for which update time fields
 * @mask:	select which time fields should be updated
 *
 * This function updates time fields to current time. Fields to update are
 * selected using @mask (see enum @ntfs_time_update_flags for posssible values).
 */
void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
{
	time_t now;

	if (!ni) {
		ntfs_log_error("%s(): Invalid arguments.\n", __FUNCTION__);
		return;
	}

	if ((ni->mft_no < FILE_first_user && ni->mft_no != FILE_root) ||
			NVolReadOnly(ni->vol) || !mask)
		return;

	now = time(NULL);
	if (mask & NTFS_UPDATE_ATIME)
		ni->last_access_time = now;
	if (mask & NTFS_UPDATE_MTIME)
		ni->last_data_change_time = now;
	if (mask & NTFS_UPDATE_CTIME)
		ni->last_mft_change_time = now;

	set_nino_flag(ni, TimesDirty);
	NInoFileNameSetDirty(ni);
	NInoSetDirty(ni);
}
Example #13
0
/**
 * Assumes mft_bitmap_rl is initialized.
 * return: 0 ok.
 *	   RETURN_OPERATIONAL_ERROR on error.
 */
static int mft_bitmap_load(ntfs_volume *rawvol)
{
	VCN vcn;
	u32 mft_bitmap_length;

	vcn = get_last_vcn(mft_bitmap_rl);
	if (vcn<=LCN_EINVAL) {
		mft_bitmap_buf = NULL;
		/* This case should not happen, not even with on-disk errors */
		goto error;
	}

	mft_bitmap_length = vcn * rawvol->cluster_size;
	mft_bitmap_records = 8 * mft_bitmap_length * rawvol->cluster_size /
		rawvol->mft_record_size;

	//printf("sizes: %d, %d.\n", mft_bitmap_length, mft_bitmap_records);

	mft_bitmap_buf = (u8*)ntfs_malloc(mft_bitmap_length);
	if (!mft_bitmap_buf)
		goto error;
	if (ntfs_rl_pread(rawvol, mft_bitmap_rl, 0, mft_bitmap_length,
			mft_bitmap_buf)!=mft_bitmap_length)
		goto error;
	return 0;
error:
	mft_bitmap_records = 0;
	ntfs_log_error("Could not load $MFT/Bitmap.\n");
	return RETURN_OPERATIONAL_ERROR;
}
Example #14
0
static void ntfs_restore_rl(ntfs_attr *na, runlist_element *oldrl)
{
	runlist_element *brl; /* Pointer to bad runlist */
	runlist_element *grl; /* Pointer to good runlist */
	ntfs_volume *vol;

	vol = na->ni->vol;
		/* Examine allocated entries from the bad runlist */
	for (brl=na->rl; brl->length; brl++) {
		if (brl->lcn != LCN_HOLE) {
// TODO improve by examining both list in parallel
		/* Find the holes in the good runlist which overlap */
			for (grl=oldrl; grl->length
			   && (grl->vcn<=(brl->vcn+brl->length)); grl++) {
				if (grl->lcn == LCN_HOLE) {
					free_common(vol, brl, brl->length, grl,
						grl->length);
				}
			}
			/* Free allocations beyond the end of good runlist */
			if (grl && !grl->length
			    && ((brl->vcn + brl->length) > grl->vcn)) {
				free_common(vol, brl, brl->length, grl,
					brl->vcn + brl->length - grl->vcn);
			}
		}
	}
	free(na->rl);
	na->rl = oldrl;
	if (ntfs_attr_update_mapping_pairs(na, 0)) {
		ntfs_log_error("Failed to restore the original runlist\n");
	}
}
Example #15
0
status_t 
fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
	void *buffer, size_t *len)
{
	nspace *ns = (nspace *)_vol->private_volume;
	//vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = cookie->inode;
	ntfs_attr *na = cookie->stream;
	size_t size = *len;
	int total = 0;
	status_t result = B_NO_ERROR;

	if (pos < 0) {
		*len = 0;
		return EINVAL;
	}


	LOCK_VOL(ns);

	TRACE("%s - ENTER\n", __FUNCTION__);

	// it is a named stream
	if (na) {
		if (pos + size > na->data_size)
			size = na->data_size - pos;

		while (size) {
			off_t bytesRead = ntfs_attr_pread(na, pos, size, buffer);
			if (bytesRead < (s64)size) {
				ntfs_log_error("ntfs_attr_pread returned less bytes than "
					"requested.\n");
			}
			if (bytesRead <= 0) {
				*len = 0;
				result = EINVAL;
				goto exit;
			}
			size -= bytesRead;
			pos += bytesRead;
			total += bytesRead;
		}

		*len = total;
	} else {
		*len = 0;
		result = ENOENT; // TODO
	}

	fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ?

exit:
	
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
Example #16
0
/**
 * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute
 * @mft_no:		mft record number where @attr is present
 * @attr:		attribute record used to check for the $Bad attribute
 *
 * Check if the mft record given by @mft_no and @attr contains the bad sector
 * list. Please note that mft record numbers describing $Badclus extent inodes
 * will not match the current $Badclus:$Bad check.
 *
 * On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
 * On error return -1 with errno set to the error code.
 */
int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
{
	int len, ret = 0;
	ntfschar *ustr;

	if (!attr) {
		ntfs_log_error("Invalid argument.\n");
		errno = EINVAL;
		return -1;
	}

	if (mft_no != FILE_BadClus)
	       	return 0;

	if (attr->type != AT_DATA)
	       	return 0;

	if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) {
		ntfs_log_perror("Couldn't convert '$Bad' to Unicode");
		return -1;
	}

	if (ustr && ntfs_names_are_equal(ustr, len,
			(ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)),
			attr->name_length, 0, NULL, 0))
		ret = 1;

	ntfs_ucsfree(ustr);

	return ret;
}
Example #17
0
/**
 * cat
 */
static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type,
		ntfschar *name, int namelen)
{
	const int bufsize = 4096;
	char *buffer;
	ntfs_attr *attr;
	s64 bytes_read, written;
	s64 offset;
	u32 block_size;

	buffer = malloc(bufsize);
	if (!buffer)
		return 1;

	attr = ntfs_attr_open(inode, type, name, namelen);
	if (!attr) {
		ntfs_log_error("Cannot find attribute type 0x%x.\n",
				le32_to_cpu(type));
		free(buffer);
		return 1;
	}

	if ((inode->mft_no < 2) && (attr->type == AT_DATA))
		block_size = vol->mft_record_size;
	else if (attr->type == AT_INDEX_ALLOCATION)
		block_size = index_get_size(inode);
	else
		block_size = 0;

	offset = 0;
	for (;;) {
		if (!opts.raw && block_size > 0) {
			// These types have fixup
			bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer);
			if (bytes_read > 0)
				bytes_read *= block_size;
		} else {
			bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer);
		}
		//ntfs_log_info("read %lld bytes\n", bytes_read);
		if (bytes_read == -1) {
			ntfs_log_perror("ERROR: Couldn't read file");
			break;
		}
		if (!bytes_read)
			break;

		written = fwrite(buffer, 1, bytes_read, stdout);
		if (written != bytes_read) {
			ntfs_log_perror("ERROR: Couldn't output all data!");
			break;
		}
		offset += bytes_read;
	}

	ntfs_attr_close(attr);
	free(buffer);
	return 0;
}
Example #18
0
static int missing_option_value(char *val, const char *s)
{
	if (!val) {
		ntfs_log_error("'%s' option should have a value.\n", s);
		return -1;
	}
	return 0;
}
Example #19
0
static int bogus_option_value(char *val, const char *s)
{
	if (val) {
		ntfs_log_error("'%s' option shouldn't have value.\n", s);
		return -1;
	}
	return 0;
}
Example #20
0
static int ntfs_inner_zero(ntfs_attr *na, runlist_element *rl)
{
	ntfs_volume *vol;
	char *buf;
	runlist_element *zrl;
	s64 cofs;
	s64 pos;
	s64 zeroed;
	int err;

	err = 0;
	vol = na->ni->vol;
	buf = (char*)malloc(vol->cluster_size);
	if (buf) {
		memset(buf, 0, vol->cluster_size);
		zrl = rl;
		pos = zrl->vcn << vol->cluster_size_bits;
		while (zrl->length
	 	    && !err
	    	    && (pos < na->initialized_size)) {
			for (cofs=0; cofs<zrl->length && !err; cofs++) {
				zeroed = ntfs_pwrite(vol->dev,
					(rl->lcn + cofs)
						<< vol->cluster_size_bits,
					vol->cluster_size, buf);
				if (zeroed != vol->cluster_size) {
					ntfs_log_error("Failed to zero at "
						"offset %lld\n",
						(long long)pos);
					errno = EIO;
					err = -1;
				}
				pos += vol->cluster_size;
			}
			zrl++;
			pos = zrl->vcn << vol->cluster_size_bits;
		}
		free(buf);
	} else {
		ntfs_log_error("Failed to allocate memory\n");
		errno = ENOSPC;
		err = -1;
	}
	return (err);
}
Example #21
0
/**
 * ntfs_crypto_init
 */
static int ntfs_crypto_init(void)
{
    int err;

    /* Initialize gcrypt library.  Note: Must come before GNU TLS init. */
    if (gcry_control(GCRYCTL_DISABLE_SECMEM, 0) != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to initialize the gcrypt library.\n");
        return -1;
    }
    /* Initialize GNU TLS library.  Note: Must come after libgcrypt init. */
    err = gnutls_global_init();
    if (err < 0) {
        ntfs_log_error("Failed to initialize GNU TLS library: %s\n",
                       gnutls_strerror(err));
        return -1;
    }
    return 0;
}
Example #22
0
/**
 * __ntfs_inode_release - Destroy an NTFS inode object
 * @ni:
 *
 * Description...
 *
 * Returns:
 */
static void __ntfs_inode_release(ntfs_inode *ni)
{
	if (NInoDirty(ni))
		ntfs_log_error("Releasing dirty inode %lld!\n",
			       (long long)ni->mft_no);
	if (NInoAttrList(ni) && ni->attr_list)
		free(ni->attr_list);
	free(ni->mrec);
	free(ni);
	return;
}
Example #23
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char **argv)
{
	unsigned long mnt_flags = 0;
	int result = 0;
	ntfs_volume *vol;

	ntfs_log_set_handler(ntfs_log_handler_outerr);

	result = parse_options(argc, argv);
	if (result >= 0)
		return (result);

	result = 0;
	utils_set_locale();

	if ((opts.label || opts.new_serial)
	    && !opts.noaction
	    && !opts.force
	    && !ntfs_check_if_mounted(opts.device, &mnt_flags)
	    && (mnt_flags & NTFS_MF_MOUNTED)) {
		ntfs_log_error("Cannot make changes to a mounted device\n");
		result = 1;
		goto abort;
	}

	if (!opts.label && !opts.new_serial)
		opts.noaction++;

	vol = utils_mount_volume(opts.device,
			(opts.noaction ? NTFS_MNT_RDONLY : 0) |
			(opts.force ? NTFS_MNT_RECOVER : 0));
	if (!vol)
		return 1;

	if (opts.new_serial) {
		result = set_new_serial(vol);
		if (result)
			goto unmount;
	} else {
		if (opts.verbose)
			result = print_serial(vol);
	}
	if (opts.label)
		result = change_label(vol, opts.label);
	else
		result = print_label(vol, mnt_flags);

unmount :
	ntfs_umount(vol, FALSE);
abort :
		/* "result" may be a negative reply of a library function */
	return (result ? 1 : 0);
}
Example #24
0
/**
 * utils_set_locale
 */
int utils_set_locale(void)
{
	const char *locale;
	locale = setlocale(LC_ALL, "");
	if (!locale) {
		locale = setlocale(LC_ALL, NULL);
		ntfs_log_error("Couldn't set local environment, using default "
			       "'%s'.\n", locale);
		return 1;
	}
	return 0;
}
Example #25
0
/**
 * ntfs_inode_fek_get -
 */
static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
                                    ntfs_rsa_private_key rsa_key, char *thumbprint,
                                    int thumbprint_size, NTFS_DF_TYPES df_type)
{
    EFS_ATTR_HEADER *efs;
    EFS_DF_ARRAY_HEADER *df_array = NULL;
    ntfs_fek *fek = NULL;

    /* Obtain the $EFS contents. */
    efs = ntfs_attr_readall(inode, AT_LOGGED_UTILITY_STREAM, EFS, 4, NULL);
    if (!efs) {
        ntfs_log_perror("Failed to read $EFS attribute");
        return NULL;
    }
    /*
     * Depending on whether the key is a normal key or a data recovery key,
     * iterate through the DDF or DRF array, respectively.
     */
    if (df_type == DF_TYPE_DDF) {
        if (efs->offset_to_ddf_array)
            df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
                                              le32_to_cpu(efs->offset_to_ddf_array));
        else
            ntfs_log_error("There are no entries in the DDF "
                           "array.\n");
    } else if (df_type == DF_TYPE_DRF) {
        if (efs->offset_to_drf_array)
            df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
                                              le32_to_cpu(efs->offset_to_drf_array));
        else
            ntfs_log_error("There are no entries in the DRF "
                           "array.\n");
    } else
        ntfs_log_error("Invalid DF type.\n");
    if (df_array)
        fek = ntfs_df_array_fek_get(df_array, rsa_key, thumbprint,
                                    thumbprint_size);
    free(efs);
    return fek;
}
Example #26
0
/**
 * ntfs_desx_key_expand - expand a 128-bit desx key to the needed 192-bit key
 * @src:	source buffer containing 128-bit key
 *
 * Expands the on-disk 128-bit desx key to the needed des key, the in-, and the
 * out-whitening keys required to perform desx {de,en}cryption.
 */
static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key,
        u64 *out_whitening, u64 *in_whitening)
{
    static const u8 *salt1 = (const u8*)"Dan Simon  ";
    static const u8 *salt2 = (const u8*)"Scott Field";
    static const int salt_len = 12;
    gcry_md_hd_t hd1, hd2;
    u32 *md;
    gcry_error_t err;

    err = gcry_md_open(&hd1, GCRY_MD_MD5, 0);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to open MD5 digest.\n");
        return err;
    }
    /* Hash the on-disk key. */
    gcry_md_write(hd1, src, 128 / 8);
    /* Copy the current hash for efficiency. */
    err = gcry_md_copy(&hd2, hd1);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to copy MD5 digest object.\n");
        goto out;
    }
    /* Hash with the first salt and store the result. */
    gcry_md_write(hd1, salt1, salt_len);
    md = (u32*)gcry_md_read(hd1, 0);
    des_key[0] = md[0] ^ md[1];
    des_key[1] = md[2] ^ md[3];
    /* Hash with the second salt and store the result. */
    gcry_md_write(hd2, salt2, salt_len);
    md = (u32*)gcry_md_read(hd2, 0);
    *out_whitening = *(u64*)md;
    *in_whitening = *(u64*)(md + 2);
    gcry_md_close(hd2);
out:
    gcry_md_close(hd1);
    return err;
}
Example #27
0
/**
 * ntfs_fek_decrypt_sector
 */
static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
{
    gcry_error_t err;

    err = gcry_cipher_reset(fek->gcry_cipher_hd);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to reset cipher: %s\n",
                       gcry_strerror(err));
        return -1;
    }
    /*
     * Note: You may wonder why we are not calling gcry_cipher_setiv() here
     * instead of doing it by hand after the decryption.  The answer is
     * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
     * it a length of 16 for AES256 so it does not like it.
     */
    if (fek->alg_id == CALG_DESX) {
        int k;

        for (k=0; k<512; k+=8) {
            ntfs_desx_decrypt(fek, &data[k], &data[k]);
        }
    } else
        err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err));
        return -1;
    }
    /* Apply the IV. */
    if (fek->alg_id == CALG_AES_256) {
        ((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
        ((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
    } else {
        /* All other algos (Des, 3Des, DesX) use the same IV. */
        ((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
    }
    return 512;
}
Example #28
0
/**
 * print_label - display the current label of a mounted ntfs partition.
 * @dev:	device to read the label from
 * @mnt_flags:	mount flags of the device or 0 if not mounted
 * @mnt_point:	mount point of the device or NULL
 *
 * Print the label of the device @dev.
 */
static int print_label(ntfs_volume *vol, unsigned long mnt_flags)
{
	int result = 0;
	//XXX significant?
	if ((mnt_flags & (NTFS_MF_MOUNTED | NTFS_MF_READONLY)) ==
			NTFS_MF_MOUNTED) {
		ntfs_log_error("%s is mounted read-write, results may be "
			"unreliable.\n", opts.device);
		result = 1;
	}

	ntfs_log_info("%s\n", vol->vol_name);
	return result;
}
Example #29
0
static void drophashindex(struct CACHE_HEADER *cache,
			const struct CACHED_GENERIC *current, int hash)
{
	struct HASH_ENTRY *link;
	struct HASH_ENTRY *previous;

	if (cache->dohash) {
		if ((hash >= 0) && (hash < cache->max_hash)) {
			/* find the link and unlink */
			link = cache->first_hash[hash];
			previous = (struct HASH_ENTRY*)NULL;
			while (link && (link->entry != current)) {
				previous = link;
				link = link->next;
			}
			if (link) {
				if (previous)
					previous->next = link->next;
				else
					cache->first_hash[hash] = link->next;
				link->next = cache->free_hash;
				cache->free_hash = link;
			} else {
				ntfs_log_error("Bad hash list,"
						" cache %s hashing dropped\n",
						cache->name);
				cache->dohash = (cache_hash)NULL;
			}
		} else {
			ntfs_log_error("Illegal hash value,"
					" cache %s hashing dropped\n",
					cache->name);
			cache->dohash = (cache_hash)NULL;
		}
	}
}
Example #30
0
/**
 * ntfs_inode_sync_standard_information - update standard information attribute
 * @ni:		ntfs inode to update standard information
 *
 * Return 0 on success or -1 on error with errno set to the error code.
 */
static int ntfs_inode_sync_standard_information(ntfs_inode *ni)
{
	ntfs_attr_search_ctx *ctx;
	STANDARD_INFORMATION *std_info;
	u32 lth;
	le32 lthle;

	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);

	ctx = ntfs_attr_get_search_ctx(ni, NULL);
	if (!ctx)
		return -1;
	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
			     0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
		ntfs_log_perror("Failed to sync standard info (inode %lld)",
				(long long)ni->mft_no);
		ntfs_attr_put_search_ctx(ctx);
		return -1;
	}
	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
			le16_to_cpu(ctx->attr->value_offset));
	std_info->file_attributes = ni->flags;
	if (test_nino_flag(ni, TimesDirty)) {
		std_info->creation_time = utc2ntfs(ni->creation_time);
		std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time);
		std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
		std_info->last_access_time = utc2ntfs(ni->last_access_time);
	}

		/* JPA update v3.x extensions, ensuring consistency */

	lthle = ctx->attr->length;
	lth = le32_to_cpu(lthle);
	if (test_nino_flag(ni, v3_Extensions)
	    && (lth <= sizeof(STANDARD_INFORMATION)))
		ntfs_log_error("bad sync of standard information\n");

	if (lth > sizeof(STANDARD_INFORMATION)) {
		std_info->owner_id = ni->owner_id;
		std_info->security_id = ni->security_id;
		std_info->quota_charged = ni->quota_charged;
		std_info->usn = ni->usn;
	}
	ntfs_inode_mark_dirty(ctx->ntfs_ino);
	ntfs_attr_put_search_ctx(ctx);
	return 0;
}