Exemple #1
0
int
add_host_to_hostfile(const char *filename, const char *host, const Key *key,
    int store_hash)
{
	FILE *f;
	int success = 0;
	char *hashed_host = NULL;

	if (key == NULL)
		return 1;	/* XXX ? */
	f = fopen(filename, "a");
	if (!f)
		return 0;

	if (store_hash) {
		if ((hashed_host = host_hash(host, NULL, 0)) == NULL) {
			error("add_host_to_hostfile: host_hash failed");
			fclose(f);
			return 0;
		}
	}
	fprintf(f, "%s ", store_hash ? hashed_host : host);

	if (key_write(key, f)) {
		success = 1;
	} else {
		error("add_host_to_hostfile: saving key in %s failed", filename);
	}
	fprintf(f, "\n");
	fclose(f);
	return success;
}
Exemple #2
0
static void
keyprint(con *c, Key *key)
{
    char *host = c->c_output_name ? c->c_output_name : c->c_name;

    if (!key)
        return;
    if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL)
        fatal("host_hash failed");

    fprintf(stdout, "%s ", host);
    key_write(key, stdout);
    fputs("\n", stdout);
}
Exemple #3
0
/**
 * ubifs_jrn_write_data - write a data node to the journal.
 * @c: UBIFS file-system description object
 * @inode: inode the data node belongs to
 * @key: node key
 * @buf: buffer to write
 * @len: data length (must not exceed %UBIFS_BLOCK_SIZE)
 *
 * This function writes a data node to the journal. Returns %0 if the data node
 * was successfully written, and a negative error code in case of failure.
 */
int ubifs_jrn_write_data(struct ubifs_info *c, const struct inode *inode,
			 const union ubifs_key *key, const void *buf, int len)
{
	int err, lnum, offs, compr_type, out_len;
	int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
	const struct ubifs_inode *ui = ubifs_inode(inode);
	struct ubifs_data_node *data;

	dbg_jrn_key(c, key, "ino %lu, blk %u, len %d, key ",
		    key_ino(c, key), key_block(c, key), len);
	ubifs_assert(len <= UBIFS_BLOCK_SIZE);

	data = kmalloc(dlen, GFP_NOFS);
	if (!data)
		return -ENOMEM;

	data->ch.node_type = UBIFS_DATA_NODE;
	key_write(c, key, &data->key);
	data->size = cpu_to_le32(len);
	zero_data_node_unused(data);

	if (!(ui->flags && UBIFS_COMPR_FL))
		/* Compression is disabled for this inode */
		compr_type = UBIFS_COMPR_NONE;
	else
		compr_type = ui->compr_type;

	out_len = dlen - UBIFS_DATA_NODE_SZ;
	ubifs_compress(buf, len, &data->data, &out_len, &compr_type);
	ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);

	dlen = UBIFS_DATA_NODE_SZ + out_len;
	data->compr_type = cpu_to_le16(compr_type);

	err = make_reservation(c, DATAHD, dlen);
	if (err)
		goto out_free;

	err = write_node(c, DATAHD, data, dlen, &lnum, &offs);
	if (!err)
		ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf,
					  key_ino(c, key));
	release_head(c, DATAHD);
	if (err)
		goto out_ro;

	err = ubifs_tnc_add(c, key, lnum, offs, dlen);
	if (err)
		goto out_ro;

	finish_reservation(c);
	kfree(data);
	return 0;

out_ro:
	ubifs_ro_mode(c, err);
	finish_reservation(c);
out_free:
	kfree(data);
	return err;
}
Exemple #4
0
/**
 * ubifs_jrn_update - update inode.
 * @c: UBIFS file-system description object
 * @dir: parent inode or host inode in case of extended attributes
 * @nm: directory entry name
 * @inode: inode
 * @deletion: indicates a directory entry deletion i.e unlink or rmdir
 * @sync: non-zero if the write-buffer has to be synchronized
 * @xent: non-zero if the directory entry is an extended attribute entry
 *
 * This function updates an inode by writing a directory entry (or extended
 * attribute entry), the inode itself, and the parent directory inode (or the
 * host inode) to the journal.
 *
 * The function writes the host inode @dir last, which is important in case of
 * extended attributes. Indeed, then we guarantee that if the host inode gets
 * synchronized, and the write-buffer it sits in gets flushed, the extended
 * attribute inode gets flushed too. And this is exactly what the user expects -
 * synchronizing the host inode synchronizes its extended attributes.
 * Similarly, this guarantees that if @dir is synchronized, its directory entry
 * corresponding to @nm gets synchronized too.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
int ubifs_jrn_update(struct ubifs_info *c, const struct inode *dir,
		     const struct qstr *nm, const struct inode *inode,
		     int deletion, int sync, int xent)
{
	int err, dlen, ilen, len, lnum, ino_offs, dent_offs;
	int aligned_dlen, aligned_ilen;
	int last_reference = !!(deletion && inode->i_nlink == 0);
	struct ubifs_dent_node *dent;
	struct ubifs_ino_node *ino;
	union ubifs_key dent_key, ino_key;

	dbg_jrn("ino %lu, dent '%.*s', data len %d in dir ino %lu",
		inode->i_ino, nm->len, nm->name, ubifs_inode(inode)->data_len,
		dir->i_ino);
	ubifs_assert(ubifs_inode(dir)->data_len == 0);

	dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
	ilen = UBIFS_INO_NODE_SZ;

	/*
	 * If the last reference to the inode is being deleted, then there is no
	 * need to attach and write inode data, it is being deleted anyway.
	 */
	if (!last_reference)
		ilen += ubifs_inode(inode)->data_len;

	aligned_dlen = ALIGN(dlen, 8);
	aligned_ilen = ALIGN(ilen, 8);

	len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;

	dent = kmalloc(len, GFP_NOFS);
	if (!dent)
		return -ENOMEM;

	if (!xent) {
		dent->ch.node_type = UBIFS_DENT_NODE;
		dent_key_init(c, &dent_key, dir->i_ino, nm);
	} else {
		dent->ch.node_type = UBIFS_XENT_NODE;
		xent_key_init(c, &dent_key, dir->i_ino, nm);
	}

	key_write(c, &dent_key, dent->key);
	dent->inum = deletion ? 0 : cpu_to_le64(inode->i_ino);
	dent->type = get_dent_type(inode->i_mode);
	dent->nlen = cpu_to_le16(nm->len);
	memcpy(dent->name, nm->name, nm->len);
	dent->name[nm->len] = '\0';
	zero_dent_node_unused(dent);
	ubifs_prep_grp_node(c, dent, dlen, 0);

	ino = (void *)dent + aligned_dlen;
	pack_inode(c, ino, inode, 0, last_reference);

	ino = (void *)ino + aligned_ilen;
	pack_inode(c, ino, dir, 1, 0);

	err = make_reservation(c, BASEHD, len);
	if (err)
		goto out_free;

	if (last_reference) {
		err = ubifs_add_orphan(c, inode->i_ino);
		if (err) {
			release_head(c, BASEHD);
			goto out_finish;
		}
	}

	err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
	if (!sync && !err) {
		struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;

		ubifs_wbuf_add_ino_nolock(wbuf, inode->i_ino);
		ubifs_wbuf_add_ino_nolock(wbuf, dir->i_ino);
	}
	release_head(c, BASEHD);
	kfree(dent);
	if (err)
		goto out_ro;

	if (deletion) {
		err = ubifs_tnc_remove_nm(c, &dent_key, nm);
		if (err)
			goto out_ro;
		err = ubifs_add_dirt(c, lnum, dlen);
	} else
		err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, nm);
	if (err)
		goto out_ro;

	/*
	 * Note, we do not remove the inode from TNC even if the last reference
	 * to it has just been deleted, because the inode may still be opened.
	 * Instead, the inode has been added to orphan lists and the orphan
	 * subsystem will take further care about it.
	 */
	ino_key_init(c, &ino_key, inode->i_ino);
	ino_offs = dent_offs + aligned_dlen;
	err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen);
	if (err)
		goto out_ro;

	ino_key_init(c, &ino_key, dir->i_ino);
	ino_offs += aligned_ilen;
	err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
	if (err)
		goto out_ro;

	finish_reservation(c);
	return 0;

out_finish:
	finish_reservation(c);
out_free:
	kfree(dent);
	return err;

out_ro:
	ubifs_ro_mode(c, err);
	if (last_reference)
		ubifs_delete_orphan(c, inode->i_ino);
	finish_reservation(c);
	return err;
}
Exemple #5
0
int ubifs_jrn_delete_xattr(struct ubifs_info *c, const struct inode *host,
			   const struct inode *inode, const struct qstr *nm,
			   int sync)
{
	int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen;
	struct ubifs_dent_node *xent;
	struct ubifs_ino_node *ino;
	union ubifs_key xent_key, key1, key2;

	dbg_jrn("host %lu, xattr ino %lu, name '%s', data len %d",
		host->i_ino, inode->i_ino, nm->name,
		ubifs_inode(inode)->data_len);
	ubifs_assert(inode->i_nlink == 0);

	/*
	 * Since we are deleting the inode, we do not bother to attach any data
	 * to it and assume its length is %UBIFS_INO_NODE_SZ.
	 */
	xlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
	aligned_xlen = ALIGN(xlen, 8);
	hlen = ubifs_inode(host)->data_len + UBIFS_INO_NODE_SZ;
	len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);

	xent = kmalloc(len, GFP_NOFS);
	if (!xent)
		return -ENOMEM;

	xent->ch.node_type = UBIFS_XENT_NODE;
	xent_key_init(c, &xent_key, host->i_ino, nm);
	key_write(c, &xent_key, xent->key);
	xent->inum = 0;
	xent->type = get_dent_type(inode->i_mode);
	xent->nlen = cpu_to_le16(nm->len);
	memcpy(xent->name, nm->name, nm->len);
	xent->name[nm->len] = '\0';
	zero_dent_node_unused(xent);
	ubifs_prep_grp_node(c, xent, xlen, 0);

	ino = (void *)xent + aligned_xlen;
	pack_inode(c, ino, inode, 0, 1);

	ino = (void *)ino + UBIFS_INO_NODE_SZ;
	pack_inode(c, ino, host, 1, 0);

	err = make_reservation(c, BASEHD, len);
	if (err) {
		kfree(xent);
		return err;
	}

	err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync);
	if (!sync && !err)
		ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino);
	release_head(c, BASEHD);
	kfree(xent);
	if (err)
		goto out_ro;

	/* Remove the extended attribute entry from TNC */
	err = ubifs_tnc_remove_nm(c, &xent_key, nm);
	if (err)
		goto out_ro;
	err = ubifs_add_dirt(c, lnum, xlen);
	if (err)
		goto out_ro;

	/*
	 * Remove all nodes belonging to the extended attribute inode from TNC.
	 * Well, there actually must be only one node - the inode itself.
	 */
	lowest_ino_key(c, &key1, inode->i_ino);
	highest_ino_key(c, &key2, inode->i_ino);
	err = ubifs_tnc_remove_range(c, &key1, &key2);
	if (err)
		goto out_ro;
	err = ubifs_add_dirt(c, lnum, UBIFS_INO_NODE_SZ);
	if (err)
		goto out_ro;

	/* And update TNC with the new host inode position */
	ino_key_init(c, &key1, host->i_ino);
	err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen);
	if (err)
		goto out_ro;

	finish_reservation(c);
	return 0;

out_ro:
	ubifs_ro_mode(c, err);
	finish_reservation(c);
	return err;
}
Exemple #6
0
/* check to see if the script specified by file can authorize the key
 *
 * the script will have the key written to STDIN, which is identical
 * to the normal public key format.
 *
 * the script must exit with either 0 for success or 1 for failure.
 * the script can print login options (if any) to STDOUT. No whitepace should be added
 * to the output.
 *
 * Use with caution: the script can hang sshd. It is recommended you code the script
 * with a timeout set if it cannot determine authenication quickly.
 */
static int
user_key_found_by_script(struct passwd *pw, Key *key, char *file)
{
	pid_t pid;
	char line[SSH_MAX_PUBKEY_BYTES];
	int pipe_in[2];
	int pipe_out[2];
	int exit_code = 1;
	int success = 0;
	FILE *f;
	//mysig_t oldsig;

	pipe(pipe_in);
	pipe(pipe_out);

	//oldsig = signal(SIGCHLD, SIG_IGN);
	temporarily_use_uid(pw);

	debug3("user_key_found_by_script: executing %s", file);

	switch ((pid = fork())) {
	case -1:
		error("fork(): %s", strerror(errno));
		restore_uid();
		return (-1);
	case 0:
		/* setup input pipe */
		close(pipe_in[1]);
		dup2(pipe_in[0], 0);
		close(pipe_in[0]);

		/* setup output pipe */
		close(pipe_out[0]);
		dup2(pipe_out[1], 1);
		close(pipe_out[1]);

		execl(file, file, NULL);

		/* exec failed */
		error("execl(): %s", strerror(errno));
		_exit(1);
	default:
		debug3("user_key_found_by_script: script pid %d", pid);

		close(pipe_in[0]);
		close(pipe_out[1]);

		f = fdopen(pipe_in[1], "w");
		key_write(key, f);
		fclose(f);

		while(waitpid(pid, &exit_code, 0) < 0) {
			switch(errno) {
			case EINTR:
				debug3("user_key_found_by_script: waitpid() EINTR, continuing");
				continue;
			default:
				error("waitpid(): %s", strerror(errno));
				goto waitpid_error;
			}
		}
		if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0) {
			int amt_read = read(pipe_out[0], line, sizeof(line) - 1);
			line[amt_read] = ' ';
			line[amt_read + 1] = 0;
			debug3("user_key_found_by_script: options: %s", line);
			if (auth_parse_options(pw, line, file, 0) == 1)
				success = 1;
		}
	 waitpid_error:
		close(pipe_out[0]);
	}

	restore_uid();
	//signal(SIGCHLD, oldsig);

	return success;
}