canonicalize: add check for algorithm type

closes #797
This commit is contained in:
Vincent Breitmoser 2014-08-30 17:00:58 +02:00
parent ac080b21ef
commit 5ff3043903
8 changed files with 50 additions and 16 deletions

View File

@ -19,6 +19,7 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPKeyFlags; import org.spongycastle.openpgp.PGPKeyFlags;
@ -219,6 +220,19 @@ public class UncachedKeyRing {
aos.close(); aos.close();
} }
// An array of known algorithms. Note this must be numerically sorted for binarySearch() to work!
static final int[] KNOWN_ALGORITHMS = new int[] {
PublicKeyAlgorithmTags.RSA_GENERAL, // 1
PublicKeyAlgorithmTags.RSA_ENCRYPT, // 2
PublicKeyAlgorithmTags.RSA_SIGN, // 3
PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, // 16
PublicKeyAlgorithmTags.DSA, // 17
PublicKeyAlgorithmTags.ECDH, // 18
PublicKeyAlgorithmTags.ECDSA, // 19
PublicKeyAlgorithmTags.ELGAMAL_GENERAL, // 20
// PublicKeyAlgorithmTags.DIFFIE_HELLMAN, // 21
};
/** "Canonicalizes" a public key, removing inconsistencies in the process. /** "Canonicalizes" a public key, removing inconsistencies in the process.
* *
* More specifically: * More specifically:
@ -250,7 +264,7 @@ public class UncachedKeyRing {
// do not accept v3 keys // do not accept v3 keys
if (getVersion() <= 3) { if (getVersion() <= 3) {
log.add(LogLevel.ERROR, LogType.MSG_KC_V3_KEY, indent); log.add(LogLevel.ERROR, LogType.MSG_KC_ERROR_V3, indent);
return null; return null;
} }
@ -262,6 +276,12 @@ public class UncachedKeyRing {
PGPPublicKey masterKey = mRing.getPublicKey(); PGPPublicKey masterKey = mRing.getPublicKey();
final long masterKeyId = masterKey.getKeyID(); final long masterKeyId = masterKey.getKeyID();
if (Arrays.binarySearch(KNOWN_ALGORITHMS, masterKey.getAlgorithm()) < 0) {
log.add(LogLevel.ERROR, LogType.MSG_KC_ERROR_MASTER_ALGO, indent,
Integer.toString(masterKey.getAlgorithm()));
return null;
}
{ {
log.add(LogLevel.DEBUG, LogType.MSG_KC_MASTER, log.add(LogLevel.DEBUG, LogType.MSG_KC_MASTER,
indent, PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())); indent, PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID()));
@ -490,7 +510,7 @@ public class UncachedKeyRing {
// If NO user ids remain, error out! // If NO user ids remain, error out!
if (!modified.getUserIDs().hasNext()) { if (!modified.getUserIDs().hasNext()) {
log.add(LogLevel.ERROR, LogType.MSG_KC_FATAL_NO_UID, indent); log.add(LogLevel.ERROR, LogType.MSG_KC_ERROR_NO_UID, indent);
return null; return null;
} }
@ -513,6 +533,16 @@ public class UncachedKeyRing {
log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB, log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB,
indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); indent, PgpKeyHelper.convertKeyIdToHex(key.getKeyID()));
indent += 1; indent += 1;
if (Arrays.binarySearch(KNOWN_ALGORITHMS, key.getAlgorithm()) < 0) {
ring = removeSubKey(ring, key);
log.add(LogLevel.ERROR, LogType.MSG_KC_SUB_UNKNOWN_ALGO, indent,
Integer.toString(key.getAlgorithm()));
indent -= 1;
continue;
}
// A subkey needs exactly one subkey binding certificate, and optionally one revocation // A subkey needs exactly one subkey binding certificate, and optionally one revocation
// certificate. // certificate.
PGPPublicKey modified = key; PGPPublicKey modified = key;

View File

@ -287,10 +287,11 @@ public class OperationResultParcel implements Parcelable {
MSG_IS_SUCCESS (R.string.msg_is_success), MSG_IS_SUCCESS (R.string.msg_is_success),
// keyring canonicalization // keyring canonicalization
MSG_KC_V3_KEY (R.string.msg_kc_v3_key),
MSG_KC_PUBLIC (R.string.msg_kc_public), MSG_KC_PUBLIC (R.string.msg_kc_public),
MSG_KC_SECRET (R.string.msg_kc_secret), MSG_KC_SECRET (R.string.msg_kc_secret),
MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid), MSG_KC_ERROR_V3 (R.string.msg_kc_error_v3),
MSG_KC_ERROR_NO_UID (R.string.msg_kc_error_no_uid),
MSG_KC_ERROR_MASTER_ALGO (R.string.msg_kc_error_master_algo),
MSG_KC_MASTER (R.string.msg_kc_master), MSG_KC_MASTER (R.string.msg_kc_master),
MSG_KC_REVOKE_BAD_ERR (R.string.msg_kc_revoke_bad_err), MSG_KC_REVOKE_BAD_ERR (R.string.msg_kc_revoke_bad_err),
MSG_KC_REVOKE_BAD_LOCAL (R.string.msg_kc_revoke_bad_local), MSG_KC_REVOKE_BAD_LOCAL (R.string.msg_kc_revoke_bad_local),
@ -314,6 +315,7 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_SUB_REVOKE_BAD_ERR (R.string.msg_kc_sub_revoke_bad_err), MSG_KC_SUB_REVOKE_BAD_ERR (R.string.msg_kc_sub_revoke_bad_err),
MSG_KC_SUB_REVOKE_BAD (R.string.msg_kc_sub_revoke_bad), MSG_KC_SUB_REVOKE_BAD (R.string.msg_kc_sub_revoke_bad),
MSG_KC_SUB_REVOKE_DUP (R.string.msg_kc_sub_revoke_dup), MSG_KC_SUB_REVOKE_DUP (R.string.msg_kc_sub_revoke_dup),
MSG_KC_SUB_UNKNOWN_ALGO (R.string.msg_kc_sub_unknown_algo),
MSG_KC_SUCCESS_BAD (R.plurals.msg_kc_success_bad), MSG_KC_SUCCESS_BAD (R.plurals.msg_kc_success_bad),
MSG_KC_SUCCESS_BAD_AND_RED (R.string.msg_kc_success_bad_and_red), MSG_KC_SUCCESS_BAD_AND_RED (R.string.msg_kc_success_bad_and_red),
MSG_KC_SUCCESS_REDUNDANT (R.plurals.msg_kc_success_redundant), MSG_KC_SUCCESS_REDUNDANT (R.plurals.msg_kc_success_redundant),

View File

@ -457,7 +457,7 @@
<!--Import Public log entries--> <!--Import Public log entries-->
<string name="msg_ip_apply_batch">Aplicando operación de inserción por lote.</string> <string name="msg_ip_apply_batch">Aplicando operación de inserción por lote.</string>
<string name="msg_ip_bad_type_secret">Se intentó importar un juego de claves (keyring) secreto como público. Esto es un fallo, por favor ¡consigne un informe!</string> <string name="msg_ip_bad_type_secret">Se intentó importar un juego de claves (keyring) secreto como público. Esto es un fallo, por favor ¡consigne un informe!</string>
<string name="msg_kc_v3_key">Esta clave es una clave OpenPGP versión 3 y por tanto insegura. No ha sido importada.</string> <string name="msg_kc_error_v3">Esta clave es una clave OpenPGP versión 3 y por tanto insegura. No ha sido importada.</string>
<string name="msg_ip_delete_old_fail">No se borró ninguna clave antigua (¿crear una nueva?)</string> <string name="msg_ip_delete_old_fail">No se borró ninguna clave antigua (¿crear una nueva?)</string>
<string name="msg_ip_delete_old_ok">Clave antigua borrada de la base de datos</string> <string name="msg_ip_delete_old_ok">Clave antigua borrada de la base de datos</string>
<string name="msg_ip_encode_fail">La operación falló debido a un error de codificación</string> <string name="msg_ip_encode_fail">La operación falló debido a un error de codificación</string>
@ -524,7 +524,7 @@
<!--Keyring Canonicalization log entries--> <!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">Canonicalizando juego de claves público %s</string> <string name="msg_kc_public">Canonicalizando juego de claves público %s</string>
<string name="msg_kc_secret">Canonicalizando juego de claves secreto %s</string> <string name="msg_kc_secret">Canonicalizando juego de claves secreto %s</string>
<string name="msg_kc_fatal_no_uid">Fallo en la canonicalización de juego de claves: El juego de claves no tiene identificaciones de usuario válidas</string> <string name="msg_kc_error_no_uid">Fallo en la canonicalización de juego de claves: El juego de claves no tiene identificaciones de usuario válidas</string>
<string name="msg_kc_master">Procesando clave maestra</string> <string name="msg_kc_master">Procesando clave maestra</string>
<string name="msg_kc_revoke_bad_err">Eliminando certificado defectuoso de revocación de juego de claves</string> <string name="msg_kc_revoke_bad_err">Eliminando certificado defectuoso de revocación de juego de claves</string>
<string name="msg_kc_revoke_bad_local">Eliminando certificado de revocación de juego de claves, con distintivo \"local\"</string> <string name="msg_kc_revoke_bad_local">Eliminando certificado de revocación de juego de claves, con distintivo \"local\"</string>

View File

@ -457,7 +457,7 @@
<!--Import Public log entries--> <!--Import Public log entries-->
<string name="msg_ip_apply_batch">Application de l\'opération d\'insertion par lot.</string> <string name="msg_ip_apply_batch">Application de l\'opération d\'insertion par lot.</string>
<string name="msg_ip_bad_type_secret">Tentative d\'importer le trousseau secret comme public. Ceci est un bogue, veuillez remplir un rapport !</string> <string name="msg_ip_bad_type_secret">Tentative d\'importer le trousseau secret comme public. Ceci est un bogue, veuillez remplir un rapport !</string>
<string name="msg_kc_v3_key">Cette clef est une clef d\'OpenPGP version 3 et n\'est, par conséquent, pas sécuritaire. Elle n\'a pas été importée. </string> <string name="msg_kc_error_v3">Cette clef est une clef d\'OpenPGP version 3 et n\'est, par conséquent, pas sécuritaire. Elle n\'a pas été importée. </string>
<string name="msg_ip_delete_old_fail">Aucune ancienne clef de supprimée (création d\'une nouvelle ?)</string> <string name="msg_ip_delete_old_fail">Aucune ancienne clef de supprimée (création d\'une nouvelle ?)</string>
<string name="msg_ip_delete_old_ok">L\'ancienne clef a été supprimée de la base de données</string> <string name="msg_ip_delete_old_ok">L\'ancienne clef a été supprimée de la base de données</string>
<string name="msg_ip_encode_fail">Échec de l\'opération causé par une erreur d\'encodage</string> <string name="msg_ip_encode_fail">Échec de l\'opération causé par une erreur d\'encodage</string>
@ -524,7 +524,7 @@
<!--Keyring Canonicalization log entries--> <!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">Canonicalisation du trousseau public %s</string> <string name="msg_kc_public">Canonicalisation du trousseau public %s</string>
<string name="msg_kc_secret">Canonicalisation du trousseau secret %s</string> <string name="msg_kc_secret">Canonicalisation du trousseau secret %s</string>
<string name="msg_kc_fatal_no_uid">La canonicalisation du trousseau a échoué : le trousseau n\'a pas d\'ID d\'utilisateur valides</string> <string name="msg_kc_error_no_uid">La canonicalisation du trousseau a échoué : le trousseau n\'a pas d\'ID d\'utilisateur valides</string>
<string name="msg_kc_master">Traitement de la clef maîtresse</string> <string name="msg_kc_master">Traitement de la clef maîtresse</string>
<string name="msg_kc_revoke_bad_err">Suppression du mauvais certificat de révocation du trousseau</string> <string name="msg_kc_revoke_bad_err">Suppression du mauvais certificat de révocation du trousseau</string>
<string name="msg_kc_revoke_bad_local">Suppression du certificat de révocation du trousseau ayant le drapeau « local »</string> <string name="msg_kc_revoke_bad_local">Suppression du certificat de révocation du trousseau ayant le drapeau « local »</string>

View File

@ -457,7 +457,7 @@
<!--Import Public log entries--> <!--Import Public log entries-->
<string name="msg_ip_apply_batch">Applicazione inserimento operazioni in batch.</string> <string name="msg_ip_apply_batch">Applicazione inserimento operazioni in batch.</string>
<string name="msg_ip_bad_type_secret">Ho cercato di importare portachiavi privato come pubblico. Questo è un bug, per cortesia inviateci un rapporto!</string> <string name="msg_ip_bad_type_secret">Ho cercato di importare portachiavi privato come pubblico. Questo è un bug, per cortesia inviateci un rapporto!</string>
<string name="msg_kc_v3_key">Questa chiave è una chiave OpenPGP versione 3 e quindi non sicura. Non è stata importata.</string> <string name="msg_kc_error_v3">Questa chiave è una chiave OpenPGP versione 3 e quindi non sicura. Non è stata importata.</string>
<string name="msg_ip_delete_old_fail">Nessuna vecchia chiave cancellata (stai creando una nuova?)</string> <string name="msg_ip_delete_old_fail">Nessuna vecchia chiave cancellata (stai creando una nuova?)</string>
<string name="msg_ip_delete_old_ok">Cancellate vecchie chiavi dal database</string> <string name="msg_ip_delete_old_ok">Cancellate vecchie chiavi dal database</string>
<string name="msg_ip_encode_fail">Operazione fallita a causa di un errore di codifica</string> <string name="msg_ip_encode_fail">Operazione fallita a causa di un errore di codifica</string>
@ -524,7 +524,7 @@
<!--Keyring Canonicalization log entries--> <!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">Canonicalizzazione portachiavi pubblico %s</string> <string name="msg_kc_public">Canonicalizzazione portachiavi pubblico %s</string>
<string name="msg_kc_secret">Canonicalizzazione portachiavi segreto %s</string> <string name="msg_kc_secret">Canonicalizzazione portachiavi segreto %s</string>
<string name="msg_kc_fatal_no_uid">Canonicalizzazione portachiavi fallita: il portachiavi non ha ID utenti validi</string> <string name="msg_kc_error_no_uid">Canonicalizzazione portachiavi fallita: il portachiavi non ha ID utenti validi</string>
<string name="msg_kc_master">Elaborazione chiave principale</string> <string name="msg_kc_master">Elaborazione chiave principale</string>
<string name="msg_kc_revoke_bad_err">Rimozione di certificato di revoca del portachiavi corrotto</string> <string name="msg_kc_revoke_bad_err">Rimozione di certificato di revoca del portachiavi corrotto</string>
<string name="msg_kc_revoke_bad_local">Rimozione certificato di revoca del portachiavi con caratteristica \"locale\"</string> <string name="msg_kc_revoke_bad_local">Rimozione certificato di revoca del portachiavi con caratteristica \"locale\"</string>

View File

@ -444,7 +444,7 @@
<!--Import Public log entries--> <!--Import Public log entries-->
<string name="msg_ip_apply_batch">連続挿入処理を適用する。</string> <string name="msg_ip_apply_batch">連続挿入処理を適用する。</string>
<string name="msg_ip_bad_type_secret">秘密鍵の鍵輪を公開鍵としてインポートを試行しました。これはバグで、ファイルをレポートしてください!</string> <string name="msg_ip_bad_type_secret">秘密鍵の鍵輪を公開鍵としてインポートを試行しました。これはバグで、ファイルをレポートしてください!</string>
<string name="msg_kc_v3_key">この鍵はOpenPGP v3形式の鍵で安全ではありません。そのためインポートできません。</string> <string name="msg_kc_error_v3">この鍵はOpenPGP v3形式の鍵で安全ではありません。そのためインポートできません。</string>
<string name="msg_ip_delete_old_fail">削除された古い鍵はありません (新しく作りますか?)</string> <string name="msg_ip_delete_old_fail">削除された古い鍵はありません (新しく作りますか?)</string>
<string name="msg_ip_delete_old_ok">データベースから古い鍵を削除しました</string> <string name="msg_ip_delete_old_ok">データベースから古い鍵を削除しました</string>
<string name="msg_ip_encode_fail">エンコードエラーにより操作が失敗しました</string> <string name="msg_ip_encode_fail">エンコードエラーにより操作が失敗しました</string>
@ -509,7 +509,7 @@
<!--Keyring Canonicalization log entries--> <!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">公開鍵の鍵輪 %s の正規化中</string> <string name="msg_kc_public">公開鍵の鍵輪 %s の正規化中</string>
<string name="msg_kc_secret">秘密鍵の鍵輪 %s の正規化中</string> <string name="msg_kc_secret">秘密鍵の鍵輪 %s の正規化中</string>
<string name="msg_kc_fatal_no_uid">鍵輪の正規化に失敗: 鍵輪が正しいユーザIDを含んでいませんでした</string> <string name="msg_kc_error_no_uid">鍵輪の正規化に失敗: 鍵輪が正しいユーザIDを含んでいませんでした</string>
<string name="msg_kc_master">主鍵処理中</string> <string name="msg_kc_master">主鍵処理中</string>
<string name="msg_kc_revoke_bad_err">問題のある鍵輪の破棄証明を破棄中</string> <string name="msg_kc_revoke_bad_err">問題のある鍵輪の破棄証明を破棄中</string>
<string name="msg_kc_revoke_bad_local">鍵輪のローカルフラグ付き破棄証明を破棄中</string> <string name="msg_kc_revoke_bad_local">鍵輪のローカルフラグ付き破棄証明を破棄中</string>

View File

@ -463,7 +463,7 @@
<!--Import Public log entries--> <!--Import Public log entries-->
<string name="msg_ip_apply_batch">Застосовується пакетна операція вставки.</string> <string name="msg_ip_apply_batch">Застосовується пакетна операція вставки.</string>
<string name="msg_ip_bad_type_secret">Спробували імпортувати секретну в\'язку як публічну. Це вада. Будь ласка, відправте звіт!</string> <string name="msg_ip_bad_type_secret">Спробували імпортувати секретну в\'язку як публічну. Це вада. Будь ласка, відправте звіт!</string>
<string name="msg_kc_v3_key">Цей ключ зроблений OpenPGP версії 3, а тому небезпечний. Його не можна імпортувати.</string> <string name="msg_kc_error_v3">Цей ключ зроблений OpenPGP версії 3, а тому небезпечний. Його не можна імпортувати.</string>
<string name="msg_ip_delete_old_fail">Нема вилученого старого ключа (створюється новий?)</string> <string name="msg_ip_delete_old_fail">Нема вилученого старого ключа (створюється новий?)</string>
<string name="msg_ip_delete_old_ok">Вилучений старий ключ з бази даних</string> <string name="msg_ip_delete_old_ok">Вилучений старий ключ з бази даних</string>
<string name="msg_ip_encode_fail">Операція не вдалася через помилку кодування</string> <string name="msg_ip_encode_fail">Операція не вдалася через помилку кодування</string>
@ -531,7 +531,7 @@
<!--Keyring Canonicalization log entries--> <!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">Канонізація публічної в\'язки %s</string> <string name="msg_kc_public">Канонізація публічної в\'язки %s</string>
<string name="msg_kc_secret">Канонізація секретної в\'язки %s</string> <string name="msg_kc_secret">Канонізація секретної в\'язки %s</string>
<string name="msg_kc_fatal_no_uid">Невдала канонізація в\'язки: в\'язка не має дійсних ІД користувача</string> <string name="msg_kc_error_no_uid">Невдала канонізація в\'язки: в\'язка не має дійсних ІД користувача</string>
<string name="msg_kc_master">Обробляється основний ключ…</string> <string name="msg_kc_master">Обробляється основний ключ…</string>
<string name="msg_kc_sub">Опрацьовується підключ %s</string> <string name="msg_kc_sub">Опрацьовується підключ %s</string>
<string name="msg_kc_sub_bad_type">Тип сертифікату невідомого ключа: %s</string> <string name="msg_kc_sub_bad_type">Тип сертифікату невідомого ключа: %s</string>

View File

@ -520,7 +520,6 @@
<!-- Import Public log entries --> <!-- Import Public log entries -->
<string name="msg_ip_apply_batch">Applying insert batch operation.</string> <string name="msg_ip_apply_batch">Applying insert batch operation.</string>
<string name="msg_ip_bad_type_secret">Tried to import secret keyring as public. This is a bug, please file a report!</string> <string name="msg_ip_bad_type_secret">Tried to import secret keyring as public. This is a bug, please file a report!</string>
<string name="msg_kc_v3_key">This key is an OpenPGP version 3 key and thus insecure. It has not been imported.</string>
<string name="msg_ip_delete_old_fail">No old key deleted (creating a new one?)</string> <string name="msg_ip_delete_old_fail">No old key deleted (creating a new one?)</string>
<string name="msg_ip_delete_old_ok">Deleted old key from database</string> <string name="msg_ip_delete_old_ok">Deleted old key from database</string>
<string name="msg_ip_encode_fail">Operation failed due to encoding error</string> <string name="msg_ip_encode_fail">Operation failed due to encoding error</string>
@ -589,7 +588,9 @@
<!-- Keyring Canonicalization log entries --> <!-- Keyring Canonicalization log entries -->
<string name="msg_kc_public">Canonicalizing public keyring %s</string> <string name="msg_kc_public">Canonicalizing public keyring %s</string>
<string name="msg_kc_secret">Canonicalizing secret keyring %s</string> <string name="msg_kc_secret">Canonicalizing secret keyring %s</string>
<string name="msg_kc_fatal_no_uid">Keyring canonicalization failed: Keyring has no valid user ids</string> <string name="msg_kc_error_v3">This is an OpenPGP version 3 key, which have been deprecated and are no longer supported!</string>
<string name="msg_kc_error_no_uid">Keyring has no valid user ids!</string>
<string name="msg_kc_error_master_algo">The master key uses an unknown (%s) algorithm!</string>
<string name="msg_kc_master">Processing master key</string> <string name="msg_kc_master">Processing master key</string>
<string name="msg_kc_revoke_bad_err">Removing bad keyring revocation certificate</string> <string name="msg_kc_revoke_bad_err">Removing bad keyring revocation certificate</string>
<string name="msg_kc_revoke_bad_local">Removing keyring revocation certificate with "local" flag</string> <string name="msg_kc_revoke_bad_local">Removing keyring revocation certificate with "local" flag</string>
@ -613,6 +614,7 @@
<string name="msg_kc_sub_revoke_bad_err">Removing bad subkey revocation certificate</string> <string name="msg_kc_sub_revoke_bad_err">Removing bad subkey revocation certificate</string>
<string name="msg_kc_sub_revoke_bad">Removing bad subkey revocation certificate</string> <string name="msg_kc_sub_revoke_bad">Removing bad subkey revocation certificate</string>
<string name="msg_kc_sub_revoke_dup">Removing redundant subkey revocation certificate</string> <string name="msg_kc_sub_revoke_dup">Removing redundant subkey revocation certificate</string>
<string name="msg_kc_sub_unknown_algo">Subkey uses an unknown algorithm, not importing…</string>
<string name="msg_kc_success">Keyring canonicalization successful, no changes</string> <string name="msg_kc_success">Keyring canonicalization successful, no changes</string>
<plurals name="msg_kc_success_bad"> <plurals name="msg_kc_success_bad">
<item quantity="one">Keyring canonicalization successful, removed one erroneous certificate</item> <item quantity="one">Keyring canonicalization successful, removed one erroneous certificate</item>