mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-24 04:52:05 +01:00
Implement exporting secret key
This commit is contained in:
parent
55b9c1ac2a
commit
878ac56ed0
10 changed files with 179 additions and 17 deletions
|
@ -27,9 +27,9 @@ import org.jxmpp.jid.BareJid;
|
||||||
|
|
||||||
public interface BouncyCastleIdentityStore {
|
public interface BouncyCastleIdentityStore {
|
||||||
|
|
||||||
void storePubkeyList(BareJid jid, PublicKeysListElement list) throws FileNotFoundException, IOException;
|
void storeActivePubkeyList(BareJid jid, PublicKeysListElement list) throws FileNotFoundException, IOException;
|
||||||
|
|
||||||
PublicKeysListElement loadPubkeyList(BareJid jid) throws FileNotFoundException, IOException;
|
PublicKeysListElement loadActivePubkeyList(BareJid jid) throws FileNotFoundException, IOException;
|
||||||
|
|
||||||
void storePublicKeys(BareJid jid, PGPPublicKeyRingCollection keys);
|
void storePublicKeys(BareJid jid, PGPPublicKeyRingCollection keys);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpMessage;
|
import org.jivesoftware.smackx.ox.OpenPgpMessage;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpProvider;
|
import org.jivesoftware.smackx.ox.OpenPgpProvider;
|
||||||
|
@ -35,22 +36,30 @@ import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
||||||
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PGPSymmetricEncryptionAlgorithms;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.XmppKeySelectionStrategy;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.XmppKeySelectionStrategy;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfigs;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfigs;
|
||||||
|
import org.bouncycastle.bcpg.HashAlgorithmTags;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||||
|
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
||||||
|
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||||
|
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
@ -83,6 +92,38 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecretkeyElement createSecretkeyElement(String password) throws CorruptedOpenPgpKeyException {
|
||||||
|
try {
|
||||||
|
// Our unencrypted secret key
|
||||||
|
PGPSecretKey secretKey = ourKeys.getSecretKeyRings().getSecretKey(ourKeyId);
|
||||||
|
|
||||||
|
PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
|
.setProvider(BouncyGPG.getProvider())
|
||||||
|
.build()
|
||||||
|
.get(HashAlgorithmTags.SHA1);
|
||||||
|
|
||||||
|
PBESecretKeyEncryptor encryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||||
|
PGPSymmetricEncryptionAlgorithms.AES_256.getAlgorithmId())
|
||||||
|
.setProvider(BouncyGPG.getProvider())
|
||||||
|
.build(password.toCharArray());
|
||||||
|
|
||||||
|
PGPSecretKey encrypted = new PGPSecretKey(
|
||||||
|
secretKey.extractPrivateKey(null),
|
||||||
|
secretKey.getPublicKey(),
|
||||||
|
calculator,
|
||||||
|
true,
|
||||||
|
encryptor);
|
||||||
|
|
||||||
|
byte[] base64 = Base64.encode(encrypted.getEncoded());
|
||||||
|
|
||||||
|
return new SecretkeyElement(base64);
|
||||||
|
|
||||||
|
} catch (PGPException | IOException e) {
|
||||||
|
throw new CorruptedOpenPgpKeyException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPubkeyElement(PubkeyElement element, BareJid owner) throws CorruptedOpenPgpKeyException {
|
public void processPubkeyElement(PubkeyElement element, BareJid owner) throws CorruptedOpenPgpKeyException {
|
||||||
byte[] decoded = Base64.decode(element.getDataElement().getB64Data());
|
byte[] decoded = Base64.decode(element.getDataElement().getB64Data());
|
||||||
|
@ -159,6 +200,9 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpElement sign(SignElement element) throws Exception {
|
public OpenPgpElement sign(SignElement element) throws Exception {
|
||||||
|
|
||||||
|
throw new SmackException.FeatureNotSupportedException("Feature not implemented for now.");
|
||||||
|
/*
|
||||||
InMemoryKeyring signingConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
InMemoryKeyring signingConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
||||||
|
|
||||||
// Add our secret keys to signing config
|
// Add our secret keys to signing config
|
||||||
|
@ -170,16 +214,19 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpMessage verify(OpenPgpElement element, BareJid sender) throws Exception {
|
public OpenPgpMessage verify(OpenPgpElement element, BareJid sender) throws Exception {
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
return null;
|
throw new SmackException.FeatureNotSupportedException("Feature not implemented for now.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpMessage decrypt(OpenPgpElement element) throws Exception {
|
public OpenPgpMessage decrypt(OpenPgpElement element) throws Exception {
|
||||||
|
throw new SmackException.FeatureNotSupportedException("Feature not implemented for now.");
|
||||||
|
/*
|
||||||
InMemoryKeyring decryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
InMemoryKeyring decryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
||||||
|
|
||||||
// Add our secret keys to decryption config
|
// Add our secret keys to decryption config
|
||||||
|
@ -201,10 +248,13 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
Streams.pipeAll(decrypted, decryptedOut);
|
Streams.pipeAll(decrypted, decryptedOut);
|
||||||
|
|
||||||
return new OpenPgpMessage(OpenPgpMessage.State.crypt, new String(decryptedOut.toByteArray(), Charset.forName("UTF-8")));
|
return new OpenPgpMessage(OpenPgpMessage.State.crypt, new String(decryptedOut.toByteArray(), Charset.forName("UTF-8")));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpElement encrypt(CryptElement element, Set<BareJid> recipients) throws Exception {
|
public OpenPgpElement encrypt(CryptElement element, Set<BareJid> recipients) throws Exception {
|
||||||
|
throw new SmackException.FeatureNotSupportedException("Feature not implemented for now.");
|
||||||
|
/*
|
||||||
if (recipients.isEmpty()) {
|
if (recipients.isEmpty()) {
|
||||||
throw new IllegalArgumentException("Set of recipients must not be empty");
|
throw new IllegalArgumentException("Set of recipients must not be empty");
|
||||||
}
|
}
|
||||||
|
@ -249,6 +299,7 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
String base64 = Base64.encodeToString(encryptedOut.toByteArray());
|
String base64 = Base64.encodeToString(encryptedOut.toByteArray());
|
||||||
|
|
||||||
return new OpenPgpElement(base64);
|
return new OpenPgpElement(base64);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class FileBasedBouncyCastleIdentityStore implements BouncyCastleIdentityS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storePubkeyList(BareJid jid, PublicKeysListElement list) throws IOException {
|
public void storeActivePubkeyList(BareJid jid, PublicKeysListElement list) throws IOException {
|
||||||
File contactsDir = contactsDir(jid);
|
File contactsDir = contactsDir(jid);
|
||||||
File destination = new File(contactsDir, "pubkey_list");
|
File destination = new File(contactsDir, "pubkey_list");
|
||||||
DataOutputStream dataOut = new DataOutputStream(new FileOutputStream(destination));
|
DataOutputStream dataOut = new DataOutputStream(new FileOutputStream(destination));
|
||||||
|
@ -69,7 +69,7 @@ public class FileBasedBouncyCastleIdentityStore implements BouncyCastleIdentityS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PublicKeysListElement loadPubkeyList(BareJid jid) throws IOException {
|
public PublicKeysListElement loadActivePubkeyList(BareJid jid) throws IOException {
|
||||||
File contactsDir = contactsDir(jid);
|
File contactsDir = contactsDir(jid);
|
||||||
File source = new File(contactsDir, "pubkey_list");
|
File source = new File(contactsDir, "pubkey_list");
|
||||||
if (!source.exists()) {
|
if (!source.exists()) {
|
||||||
|
|
|
@ -66,11 +66,11 @@ public class FileBasedBouncyCastleIdentityStoreTest extends SmackTestSuite {
|
||||||
|
|
||||||
FileBasedBouncyCastleIdentityStore store = new FileBasedBouncyCastleIdentityStore(storePath);
|
FileBasedBouncyCastleIdentityStore store = new FileBasedBouncyCastleIdentityStore(storePath);
|
||||||
|
|
||||||
PublicKeysListElement shouldBeNull = store.loadPubkeyList(jid);
|
PublicKeysListElement shouldBeNull = store.loadActivePubkeyList(jid);
|
||||||
assertNull(shouldBeNull);
|
assertNull(shouldBeNull);
|
||||||
store.storePubkeyList(jid, list);
|
store.storeActivePubkeyList(jid, list);
|
||||||
|
|
||||||
PublicKeysListElement retrieved = store.loadPubkeyList(jid);
|
PublicKeysListElement retrieved = store.loadActivePubkeyList(jid);
|
||||||
assertEquals(list.getMetadata(), retrieved.getMetadata());
|
assertEquals(list.getMetadata(), retrieved.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.ox;
|
package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -30,8 +31,10 @@ import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.util.Async;
|
import org.jivesoftware.smack.util.Async;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
|
import org.jivesoftware.smackx.ox.callback.DisplayBackupCodeCallback;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
import org.jivesoftware.smackx.pep.PEPListener;
|
import org.jivesoftware.smackx.pep.PEPListener;
|
||||||
import org.jivesoftware.smackx.pep.PEPManager;
|
import org.jivesoftware.smackx.pep.PEPManager;
|
||||||
|
@ -57,6 +60,11 @@ public final class OpenPgpManager extends Manager {
|
||||||
*/
|
*/
|
||||||
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the OX secret key node.
|
||||||
|
*/
|
||||||
|
public static final String PEP_NODE_SECRET_KEY = "urn:xmpp:openpgp:0:secret-key";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature to be announced using the {@link ServiceDiscoveryManager} to subscribe to the OX metadata node.
|
* Feature to be announced using the {@link ServiceDiscoveryManager} to subscribe to the OX metadata node.
|
||||||
*
|
*
|
||||||
|
@ -272,12 +280,20 @@ public final class OpenPgpManager extends Manager {
|
||||||
/**
|
/**
|
||||||
* TODO: Implement and document.
|
* TODO: Implement and document.
|
||||||
*/
|
*/
|
||||||
public void depositSecretKey() {
|
public void depositSecretKey(DisplayBackupCodeCallback callback)
|
||||||
|
throws CorruptedOpenPgpKeyException, InterruptedException, PubSubException.NotALeafNodeException,
|
||||||
|
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
|
||||||
ensureProviderIsSet();
|
ensureProviderIsSet();
|
||||||
// Create key backup by appending serialized unencrypted secret keys.
|
|
||||||
// Encrypt the backup using a random generated password
|
String password = generateBackupPassword();
|
||||||
// Publish the backup to the secret key node (whitelist protected)
|
SecretkeyElement secretKeyElement = provider.createSecretkeyElement(password);
|
||||||
// Display the backup key to the user
|
|
||||||
|
PubSubManager pm = PubSubManager.getInstance(connection());
|
||||||
|
LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY);
|
||||||
|
PubSubHelper.whitelist(secretKeyNode);
|
||||||
|
|
||||||
|
secretKeyNode.publish(new PayloadItem<>(secretKeyElement));
|
||||||
|
callback.displayBackupCode(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -349,4 +365,32 @@ public final class OpenPgpManager extends Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a secure backup code.
|
||||||
|
*
|
||||||
|
* @see <a href="https://xmpp.org/extensions/xep-0373.html#sect-idm140425111347232">XEP-0373 §5.3</a>
|
||||||
|
* @return backup code
|
||||||
|
*/
|
||||||
|
private String generateBackupPassword() {
|
||||||
|
final String alphabet = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
StringBuilder code = new StringBuilder();
|
||||||
|
|
||||||
|
// 6 blocks
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
|
||||||
|
// of 4 chars
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
char c = alphabet.charAt(random.nextInt(alphabet.length()));
|
||||||
|
code.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dash after every block except the last one
|
||||||
|
if (i != 5) {
|
||||||
|
code.append('-');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
|
||||||
|
@ -151,4 +152,6 @@ public interface OpenPgpProvider {
|
||||||
* @throws CorruptedOpenPgpKeyException if for some reason the fingerprint cannot be derived from the key pair.
|
* @throws CorruptedOpenPgpKeyException if for some reason the fingerprint cannot be derived from the key pair.
|
||||||
*/
|
*/
|
||||||
String getFingerprint() throws CorruptedOpenPgpKeyException;
|
String getFingerprint() throws CorruptedOpenPgpKeyException;
|
||||||
|
|
||||||
|
SecretkeyElement createSecretkeyElement(String password) throws CorruptedOpenPgpKeyException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,18 @@ import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smackx.pubsub.AccessModel;
|
import org.jivesoftware.smackx.pubsub.AccessModel;
|
||||||
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
||||||
import org.jivesoftware.smackx.pubsub.LeafNode;
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
public class PubSubHelper {
|
public class PubSubHelper {
|
||||||
|
|
||||||
public static void whitelist(LeafNode node)
|
public static void whitelist(LeafNode node)
|
||||||
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
SmackException.NoResponseException {
|
SmackException.NoResponseException {
|
||||||
ConfigureForm config = node.getNodeConfiguration();
|
ConfigureForm old = node.getNodeConfiguration();
|
||||||
if (config.getAccessModel() != AccessModel.whitelist) {
|
if (old.getAccessModel() != AccessModel.whitelist) {
|
||||||
config.setAccessModel(AccessModel.whitelist);
|
ConfigureForm _new = new ConfigureForm(DataForm.Type.submit);
|
||||||
node.sendConfigurationForm(config);
|
_new.setAccessModel(AccessModel.whitelist);
|
||||||
|
node.sendConfigurationForm(_new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.ox.callback;
|
||||||
|
|
||||||
|
public interface AskForBackupCodeCallback {
|
||||||
|
String askForBackupCode();
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.ox.callback;
|
||||||
|
|
||||||
|
public interface DisplayBackupCodeCallback {
|
||||||
|
void displayBackupCode(String backupCode);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2017 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Callback classes for XEP-0373: OpenPGP for XMPP.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.ox.callback;
|
Loading…
Reference in a new issue