mirror of https://github.com/sipwise/jitsi.git
parent
0d4f8ceebc
commit
936e6cbd52
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import net.java.sip.communicator.service.configuration.*;
|
||||
import net.java.sip.communicator.service.notification.*;
|
||||
import net.java.sip.communicator.service.resources.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import net.java.sip.communicator.util.swing.*;
|
||||
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
/**
|
||||
* Resolver that wraps a DNSSEC capable resolver and handles validation
|
||||
* failures according to the user's settings.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class ConfigurableDnssecResolver
|
||||
extends UnboundResolver
|
||||
{
|
||||
private final static Logger logger
|
||||
= Logger.getLogger(ConfigurableDnssecResolver.class);
|
||||
|
||||
/**
|
||||
* Name of the property that defines the default DNSSEC validation
|
||||
* behavior.
|
||||
*/
|
||||
public final static String PNAME_DNSSEC_VALIDATION_MODE
|
||||
= "net.java.sip.communicator.util.dns.DNSSEC_VALIDATION_MODE";
|
||||
|
||||
/**
|
||||
* Default value of {@link #PNAME_DNSSEC_VALIDATION_MODE}
|
||||
*/
|
||||
public final static String PNAME_BASE_DNSSEC_PIN
|
||||
= "net.java.sip.communicator.util.dns.pin";
|
||||
|
||||
final static String EVENT_TYPE = "DNSSEC_NOTIFICATION";
|
||||
|
||||
private ConfigurationService config
|
||||
= DnsUtilActivator.getConfigurationService();
|
||||
private ResourceManagementService R
|
||||
= DnsUtilActivator.getResources();
|
||||
private Map<String, Date> lastNotifications
|
||||
= new HashMap<String, Date>();
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class. Tries to use the system's
|
||||
* default forwarders.
|
||||
*/
|
||||
public ConfigurableDnssecResolver()
|
||||
{
|
||||
super();
|
||||
String forwarders = DnsUtilActivator.getConfigurationService()
|
||||
.getString(DnsUtilActivator.PNAME_DNSSEC_NAMESERVERS);
|
||||
if(!StringUtils.isNullOrEmpty(forwarders, true))
|
||||
{
|
||||
if(logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Setting DNSSEC forwarders to: "
|
||||
+ Arrays.toString(forwarders.split(",")));
|
||||
}
|
||||
super.setForwarders(forwarders.split(","));
|
||||
}
|
||||
DnsUtilActivator.getNotificationService().
|
||||
registerDefaultNotificationForEvent(
|
||||
ConfigurableDnssecResolver.EVENT_TYPE,
|
||||
NotificationAction.ACTION_POPUP_MESSAGE,
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects a DNS answer message and handles validation results according to
|
||||
* the user's preferences.
|
||||
*
|
||||
* @throws DnssecRuntimeException when the validation failed and the user
|
||||
* did not choose to ignore it.
|
||||
*/
|
||||
@Override
|
||||
protected void validateMessage(SecureMessage msg)
|
||||
throws DnssecRuntimeException
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
// || 1 | 2 | 3 | 4 | 5
|
||||
//---------------------------------------------------------------------
|
||||
// Sec. | Bog. || Ign. | Sec.Only | Sec.Or.Unsig | Warn.Bog | WarnAll
|
||||
//---------------------------------------------------------------------
|
||||
//a) 1 | 0 || ok | ok | ok | ok | ok
|
||||
//b) 0 | 1 || ok | nok | nok | ask | ask
|
||||
//c) 0 | 0 || ok | nok | ok | ok | ask
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
String fqdn = msg.getQuestion().getName().toString();
|
||||
String type = Type.string(msg.getQuestion().getType());
|
||||
String propName = createPropNameUnsigned(fqdn, type);
|
||||
SecureResolveMode defaultAction = Enum.valueOf(SecureResolveMode.class,
|
||||
config.getString(
|
||||
PNAME_DNSSEC_VALIDATION_MODE,
|
||||
SecureResolveMode.WarnIfBogus.name()
|
||||
)
|
||||
);
|
||||
SecureResolveMode pinned = Enum.valueOf(SecureResolveMode.class,
|
||||
config.getString(
|
||||
propName,
|
||||
defaultAction.name()
|
||||
)
|
||||
);
|
||||
|
||||
//create default entry
|
||||
if(pinned == defaultAction)
|
||||
config.setProperty(propName, pinned.name());
|
||||
|
||||
//check domain policy
|
||||
|
||||
//[abc]1, a[2-5]
|
||||
if(pinned == SecureResolveMode.IgnoreDnssec || msg.isSecure())
|
||||
return;
|
||||
|
||||
if(
|
||||
//b2, c2
|
||||
(pinned == SecureResolveMode.SecureOnly && !msg.isSecure())
|
||||
||
|
||||
//b3
|
||||
(pinned == SecureResolveMode.SecureOrUnsigned && msg.isBogus())
|
||||
)
|
||||
{
|
||||
String text = getExceptionMessage(msg);
|
||||
Date last = lastNotifications.get(text);
|
||||
if(last == null
|
||||
//wait at least 5 minutes before showing the same info again
|
||||
|| last.before(new Date(new Date().getTime() - 1000*60*5)))
|
||||
{
|
||||
DnsUtilActivator.getNotificationService().fireNotification(
|
||||
EVENT_TYPE,
|
||||
R.getI18NString("util.dns.INSECURE_ANSWER_TITLE"),
|
||||
text, null, null);
|
||||
lastNotifications.put(text, new Date());
|
||||
}
|
||||
throw new DnssecRuntimeException(text);
|
||||
}
|
||||
|
||||
//c3
|
||||
if(pinned == SecureResolveMode.SecureOrUnsigned && !msg.isBogus())
|
||||
return;
|
||||
|
||||
//c4
|
||||
if(pinned == SecureResolveMode.WarnIfBogus && !msg.isBogus())
|
||||
return;
|
||||
|
||||
//b4, b5, c5
|
||||
String reason = msg.isBogus()
|
||||
? R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_BOGUS",
|
||||
new String[]{fqdn, msg.getBogusReason()})
|
||||
: R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_UNSIGNED",
|
||||
new String[]{type, fqdn});
|
||||
DnssecDialog dlg = new DnssecDialog(fqdn, reason);
|
||||
dlg.setVisible(true);
|
||||
DnssecDialogResult result = dlg.getResult();
|
||||
switch(result)
|
||||
{
|
||||
case Accept:
|
||||
break;
|
||||
case Deny:
|
||||
throw new DnssecRuntimeException(getExceptionMessage(msg));
|
||||
case AlwaysAccept:
|
||||
if(msg.isBogus())
|
||||
config.setProperty(propName,
|
||||
SecureResolveMode.IgnoreDnssec.name());
|
||||
else
|
||||
config.setProperty(propName,
|
||||
SecureResolveMode.WarnIfBogus.name());
|
||||
break;
|
||||
case AlwaysDeny:
|
||||
config.setProperty(propName, SecureResolveMode.SecureOnly);
|
||||
throw new DnssecRuntimeException(getExceptionMessage(msg));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the return code from the DNSSEC verification dialog.
|
||||
*/
|
||||
private enum DnssecDialogResult
|
||||
{
|
||||
/** The DNS result shall be accepted. */
|
||||
Accept,
|
||||
/** The result shall be rejected. */
|
||||
Deny,
|
||||
/** The result shall be accepted permanently. */
|
||||
AlwaysAccept,
|
||||
/**
|
||||
* The result shall be rejected automatically unless it is valid
|
||||
* according to DNSSEC.
|
||||
*/
|
||||
AlwaysDeny
|
||||
}
|
||||
|
||||
/**
|
||||
* Dialog to ask and warn the user if he wants to continue to accept an
|
||||
* invalid dnssec result.
|
||||
*/
|
||||
private class DnssecDialog extends SIPCommDialog implements ActionListener
|
||||
{
|
||||
//UI controls
|
||||
private JPanel pnlAdvanced;
|
||||
private JPanel pnlStandard;
|
||||
private final String domain;
|
||||
private final String reason;
|
||||
private JButton cmdAck;
|
||||
private JButton cmdShowDetails;
|
||||
|
||||
//state
|
||||
private DnssecDialogResult result = DnssecDialogResult.Deny;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
* @param domain The FQDN of the domain that failed.
|
||||
* @param reason String describing why the validation failed.
|
||||
*/
|
||||
public DnssecDialog(String domain, String reason)
|
||||
{
|
||||
super(false);
|
||||
setModal(true);
|
||||
this.domain = domain;
|
||||
this.reason = reason;
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the UI controls
|
||||
*/
|
||||
private void initComponents()
|
||||
{
|
||||
setLayout(new BorderLayout(15, 15));
|
||||
setTitle(R.getI18NString("util.dns.INSECURE_ANSWER_TITLE"));
|
||||
|
||||
// warning text
|
||||
JLabel imgWarning =
|
||||
new JLabel(R.getImage("service.gui.icons.WARNING_ICON"));
|
||||
imgWarning.setBorder(BorderFactory
|
||||
.createEmptyBorder(10, 10, 10, 10));
|
||||
add(imgWarning, BorderLayout.WEST);
|
||||
JLabel lblWarning = new JLabel(
|
||||
R.getI18NString("util.dns.DNSSEC_WARNING", new String[]{
|
||||
R.getSettingsString("service.gui.APPLICATION_NAME"),
|
||||
domain
|
||||
})
|
||||
);
|
||||
add(lblWarning, BorderLayout.CENTER);
|
||||
|
||||
//standard panel (deny option)
|
||||
cmdAck = new JButton(R.getI18NString("service.gui.OK"));
|
||||
cmdAck.addActionListener(this);
|
||||
|
||||
cmdShowDetails = new JButton(
|
||||
R.getI18NString("util.dns.DNSSEC_ADVANCED_OPTIONS"));
|
||||
cmdShowDetails.addActionListener(this);
|
||||
|
||||
pnlStandard = new TransparentPanel(new BorderLayout());
|
||||
pnlStandard.setBorder(BorderFactory
|
||||
.createEmptyBorder(10, 10, 10, 10));
|
||||
pnlStandard.add(cmdShowDetails, BorderLayout.WEST);
|
||||
pnlStandard.add(cmdAck, BorderLayout.EAST);
|
||||
add(pnlStandard, BorderLayout.SOUTH);
|
||||
|
||||
//advanced panel
|
||||
pnlAdvanced = new TransparentPanel(new BorderLayout());
|
||||
JPanel pnlAdvancedButtons = new TransparentPanel(
|
||||
new FlowLayout(FlowLayout.RIGHT));
|
||||
pnlAdvancedButtons.setBorder(BorderFactory
|
||||
.createEmptyBorder(10, 10, 10, 10));
|
||||
pnlAdvanced.add(pnlAdvancedButtons, BorderLayout.EAST);
|
||||
for(DnssecDialogResult r : DnssecDialogResult.values())
|
||||
{
|
||||
JButton cmd = new JButton(R.getI18NString(
|
||||
DnssecDialogResult.class.getName() + "." + r.name()));
|
||||
cmd.setActionCommand(r.name());
|
||||
cmd.addActionListener(this);
|
||||
pnlAdvancedButtons.add(cmd);
|
||||
}
|
||||
JLabel lblReason = new JLabel(reason);
|
||||
lblReason.setBorder(BorderFactory
|
||||
.createEmptyBorder(10, 10, 10, 10));
|
||||
pnlAdvanced.add(lblReason, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the events coming from the buttons.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
if(e.getSource() == cmdAck)
|
||||
{
|
||||
result = DnssecDialogResult.Deny;
|
||||
dispose();
|
||||
}
|
||||
else if(e.getSource() == cmdShowDetails)
|
||||
{
|
||||
getContentPane().remove(pnlStandard);
|
||||
add(pnlAdvanced, BorderLayout.SOUTH);
|
||||
pack();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Enum.valueOf(DnssecDialogResult.class,
|
||||
e.getActionCommand());
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the option that user has chosen.
|
||||
* @return the option that user has chosen.
|
||||
*/
|
||||
public DnssecDialogResult getResult()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private String getExceptionMessage(SecureMessage msg)
|
||||
{
|
||||
//TODO parse bogus reason text and translate
|
||||
return msg.getBogusReason() == null
|
||||
? R.getI18NString(
|
||||
"util.dns.INSECURE_ANSWER_MESSAGE",
|
||||
new String[]{msg.getQuestion().getName().toString()}
|
||||
)
|
||||
: msg.getBogusReason();
|
||||
}
|
||||
|
||||
private String createPropNameUnsigned(String fqdn, String type)
|
||||
{
|
||||
return PNAME_BASE_DNSSEC_PIN + "." + fqdn.replace(".", "__");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
import net.java.sip.communicator.service.configuration.*;
|
||||
import net.java.sip.communicator.service.notification.*;
|
||||
import net.java.sip.communicator.service.resources.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
/**
|
||||
* The DNS Util activator registers the DNSSEC resolver if enabled.
|
||||
*
|
||||
* @author Emil Ivov
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class DnsUtilActivator
|
||||
implements BundleActivator
|
||||
{
|
||||
/**
|
||||
* The name of the property that enables or disables the DNSSEC resolver
|
||||
* (instead of a normal, non-validating local resolver).
|
||||
*/
|
||||
public static final String PNAME_DNSSEC_RESOLVER_ENABLED
|
||||
= "net.java.sip.communicator.util.dns.DNSSEC_ENABLED";
|
||||
|
||||
/**
|
||||
* Default value of {@link PNAME_DNSSEC_RESOLVER_ENABLED}.
|
||||
*/
|
||||
public static final boolean PDEFAULT_DNSSEC_RESOLVER_ENABLED = false;
|
||||
|
||||
/**
|
||||
* The name of the property that sets custom nameservers to use for all DNS
|
||||
* lookups when DNSSEC is enabled. Multiple servers are separated by a comma
|
||||
* (,).
|
||||
*/
|
||||
public static final String PNAME_DNSSEC_NAMESERVERS
|
||||
= "net.java.sip.communicator.util.dns.DNSSEC_NAMESERVERS";
|
||||
|
||||
/**
|
||||
* The <tt>Logger</tt> used by the <tt>UtilActivator</tt> class and its
|
||||
* instances for logging output.
|
||||
*/
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(DnsUtilActivator.class);
|
||||
|
||||
private static ConfigurationService configurationService;
|
||||
private static NotificationService notificationService;
|
||||
private static ResourceManagementService resourceService;
|
||||
private static BundleContext bundleContext;
|
||||
|
||||
/**
|
||||
* Calls <tt>Thread.setUncaughtExceptionHandler()</tt>
|
||||
*
|
||||
* @param context The execution context of the bundle being started
|
||||
* (unused).
|
||||
* @throws Exception If this method throws an exception, this bundle is
|
||||
* marked as stopped and the Framework will remove this bundle's
|
||||
* listeners, unregister all services registered by this bundle, and
|
||||
* release all services used by this bundle.
|
||||
*/
|
||||
public void start(BundleContext context)
|
||||
throws Exception
|
||||
{
|
||||
bundleContext = context;
|
||||
|
||||
if(getConfigurationService().getBoolean(
|
||||
PNAME_DNSSEC_RESOLVER_ENABLED,
|
||||
PDEFAULT_DNSSEC_RESOLVER_ENABLED))
|
||||
{
|
||||
getNotificationService().
|
||||
registerDefaultNotificationForEvent(
|
||||
ConfigurableDnssecResolver.EVENT_TYPE,
|
||||
NotificationAction.ACTION_POPUP_MESSAGE,
|
||||
null, null);
|
||||
}
|
||||
refreshResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a DNSSEC resolver as default resolver on lookup when DNSSEC is
|
||||
* enabled; creates a standard lookup otherwise.
|
||||
*/
|
||||
public static void refreshResolver()
|
||||
{
|
||||
if(getConfigurationService().getBoolean(
|
||||
PNAME_DNSSEC_RESOLVER_ENABLED,
|
||||
PDEFAULT_DNSSEC_RESOLVER_ENABLED))
|
||||
{
|
||||
logger.trace("DNSSEC is enabled");
|
||||
ConfigurableDnssecResolver res = new ConfigurableDnssecResolver();
|
||||
for(int i = 1;;i++)
|
||||
{
|
||||
String anchor = getResources().getSettingsString(
|
||||
"net.java.sip.communicator.util.dns.DS_ROOT." + i);
|
||||
if(anchor == null)
|
||||
break;
|
||||
res.addTrustAnchor(anchor);
|
||||
if(logger.isTraceEnabled())
|
||||
logger.trace("Loaded trust anchor " + anchor);
|
||||
}
|
||||
Lookup.setDefaultResolver(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.trace("DNSSEC is disabled, refresh default config");
|
||||
Lookup.refreshDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Doesn't do anything.
|
||||
*
|
||||
* @param context The execution context of the bundle being stopped.
|
||||
* @throws Exception If this method throws an exception, the bundle is
|
||||
* still marked as stopped, and the Framework will remove the bundle's
|
||||
* listeners, unregister all services registered by the bundle, and
|
||||
* release all services used by the bundle.
|
||||
*/
|
||||
public void stop(BundleContext context)
|
||||
throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <tt>ConfigurationService</tt> obtained from the bundle
|
||||
* context.
|
||||
* @return the <tt>ConfigurationService</tt> obtained from the bundle
|
||||
* context
|
||||
*/
|
||||
public static ConfigurationService getConfigurationService()
|
||||
{
|
||||
if (configurationService == null)
|
||||
{
|
||||
configurationService
|
||||
= ServiceUtils.getService(
|
||||
bundleContext,
|
||||
ConfigurationService.class);
|
||||
}
|
||||
return configurationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <tt>NotificationService</tt> obtained from the bundle context.
|
||||
*
|
||||
* @return the <tt>NotificationService</tt> obtained from the bundle context
|
||||
*/
|
||||
public static NotificationService getNotificationService()
|
||||
{
|
||||
if (notificationService == null)
|
||||
{
|
||||
notificationService
|
||||
= ServiceUtils.getService(
|
||||
bundleContext,
|
||||
NotificationService.class);
|
||||
}
|
||||
return notificationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service giving access to all application resources.
|
||||
*
|
||||
* @return the service giving access to all application resources.
|
||||
*/
|
||||
public static ResourceManagementService getResources()
|
||||
{
|
||||
if (resourceService == null)
|
||||
{
|
||||
resourceService
|
||||
= ResourceManagementServiceUtils.getService(bundleContext);
|
||||
}
|
||||
return resourceService;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
/**
|
||||
* Checked DNSSEC exception for code that knows how to deal with it.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class DnssecException
|
||||
extends Exception
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
* @param e the DNSSEC runtime exception to encapsulate.
|
||||
*/
|
||||
public DnssecException(DnssecRuntimeException e)
|
||||
{
|
||||
super(e);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Runtime exception that is thrown when a DNSSEC validation failure occurred.
|
||||
* This is not a checked exception or a derivative of
|
||||
* {@link UnknownHostException} so that existing code does not retry the lookup
|
||||
* (potentially in a loop).
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class DnssecRuntimeException
|
||||
extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
* @param message The reason why this exception is thrown.
|
||||
*/
|
||||
public DnssecRuntimeException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xbill.DNS.Message;
|
||||
|
||||
/**
|
||||
* DNS Message that adds DNSSEC validation information.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class SecureMessage
|
||||
extends Message
|
||||
{
|
||||
private boolean secure;
|
||||
private boolean bogus;
|
||||
private String bogusReason;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class based on data received from an
|
||||
* Unbound resolve.
|
||||
*
|
||||
* @param msg The answer of the Unbound resolver.
|
||||
* @throws IOException
|
||||
*/
|
||||
public SecureMessage(UnboundResult msg) throws IOException
|
||||
{
|
||||
super(msg.answerPacket);
|
||||
secure = msg.secure;
|
||||
bogus = msg.bogus;
|
||||
bogusReason = msg.whyBogus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the answer is secure.
|
||||
* @return True, if the result is validated securely.
|
||||
*/
|
||||
public boolean isSecure()
|
||||
{
|
||||
return secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if there was a validation failure.
|
||||
*
|
||||
* @return If the result was not secure (secure == false), and this result
|
||||
* is due to a security failure, bogus is true.
|
||||
*/
|
||||
public boolean isBogus()
|
||||
{
|
||||
return bogus;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the result is bogus this contains a string that describes the failure.
|
||||
*
|
||||
* @return string that describes the failure.
|
||||
*/
|
||||
public String getBogusReason()
|
||||
{
|
||||
return bogusReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Message to a String. The fields secure, bogus and whyBogus
|
||||
* are append as a comment.
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder s = new StringBuilder(super.toString());
|
||||
s.append('\n');
|
||||
s.append(";; Secure: ");
|
||||
s.append(secure);
|
||||
s.append('\n');
|
||||
s.append(";; Bogus: ");
|
||||
s.append(bogus);
|
||||
s.append('\n');
|
||||
if(bogus)
|
||||
{
|
||||
s.append(";; Reason: ");
|
||||
s.append(bogusReason);
|
||||
s.append('\n');
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
/**
|
||||
* Defines how DNSSEC validation errors should be handled.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public enum SecureResolveMode
|
||||
{
|
||||
/**
|
||||
* Any DNSSEC data is completely ignored.
|
||||
*/
|
||||
IgnoreDnssec,
|
||||
|
||||
/**
|
||||
* The result of a query is only returned if it validated successfully.
|
||||
*/
|
||||
SecureOnly,
|
||||
|
||||
/**
|
||||
* The result of a query is returned if it validated successfully or when
|
||||
* the zone is unsigned.
|
||||
*/
|
||||
SecureOrUnsigned,
|
||||
|
||||
/**
|
||||
* If the result of a query is bogus (manipulated, incorrect), the user is
|
||||
* to be asked how to proceed.
|
||||
*/
|
||||
WarnIfBogus,
|
||||
|
||||
/**
|
||||
* If the result of a query is bogus (manipulated, incorrect) or if the zone
|
||||
* is unsigned, the user is to be asked how to proceed.
|
||||
*/
|
||||
WarnIfBogusOrUnsigned
|
||||
}
|
||||
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
/**
|
||||
* Wrapper for the JUnbound JNI wrapper.
|
||||
* <p>
|
||||
* The JavaDoc of these methods is directly copied from libunbound, licensed as
|
||||
* follows:
|
||||
* <p>
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class UnboundApi
|
||||
{
|
||||
private static boolean isAvailable;
|
||||
private static final Object syncRoot = new Object();
|
||||
|
||||
static
|
||||
{
|
||||
tryLoadUnbound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load the Unbound native library. When successful,
|
||||
* {@link #isAvailable()} returns true.
|
||||
*/
|
||||
public static void tryLoadUnbound()
|
||||
{
|
||||
synchronized(syncRoot)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.loadLibrary("junbound");
|
||||
isAvailable = true;
|
||||
}
|
||||
catch(UnsatisfiedLinkError e)
|
||||
{
|
||||
isAvailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the Unbound library is loaded.
|
||||
* @return True when the JNI wrapper could be loaded, false otherwise.
|
||||
*/
|
||||
public static boolean isAvailable()
|
||||
{
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug verbosity for the context. Output is directed to stderr. Higher
|
||||
* debug level gives more output.
|
||||
*
|
||||
* @param context context.
|
||||
* @param level The debug level.
|
||||
*/
|
||||
public static native void setDebugLevel(long context, int level);
|
||||
|
||||
/**
|
||||
* Create a resolving and validation context.
|
||||
* @return a new context. default initialization. returns NULL on error.
|
||||
*/
|
||||
public static native long createContext();
|
||||
|
||||
/**
|
||||
* Destroy a validation context and free all its resources. Outstanding
|
||||
* async queries are killed and callbacks are not called for them.
|
||||
*
|
||||
* @param context context to delete
|
||||
*/
|
||||
public static native void deleteContext(long context);
|
||||
|
||||
/**
|
||||
* Set machine to forward DNS queries to, the caching resolver to use.
|
||||
* <p>
|
||||
* IP4 or IP6 address. Forwards all DNS requests to that machine, which is
|
||||
* expected to run a recursive resolver. If the proxy is not DNSSEC-capable,
|
||||
* validation may fail. Can be called several times, in that case the
|
||||
* addresses are used as backup servers.
|
||||
*
|
||||
* @param context context. At this time it is only possible to set
|
||||
* configuration before the first resolve is done.
|
||||
* @param server address, IP4 or IP6 in string format. If the server is
|
||||
* NULL, forwarding is disabled.
|
||||
*/
|
||||
public static native void setForwarder(long context, String server);
|
||||
|
||||
/**
|
||||
* Add a trust anchor to the given context.
|
||||
* <p>
|
||||
* The trust anchor is a string, on one line, that holds a valid DNSKEY or
|
||||
* DS RR.
|
||||
*
|
||||
* @param context context. At this time it is only possible to add trusted
|
||||
* keys before the first resolve is done.
|
||||
* @param anchor string, with zone-format RR on one line. [domainname] [TTL
|
||||
* optional] [type] [class optional] [rdata contents]
|
||||
*/
|
||||
public static native void addTrustAnchor(long context, String anchor);
|
||||
|
||||
/**
|
||||
* Perform resolution and validation of the target name.
|
||||
*
|
||||
* @param context context. The context is finalized, and can no longer
|
||||
* accept config changes.
|
||||
* @param name domain name in text format (a zero terminated text string).
|
||||
* @param rrtype type of RR in host order, 1 is A (address).
|
||||
* @param rrclass class of RR in host order, 1 is IN (for internet).
|
||||
* @return the result data is returned in a newly allocated result
|
||||
* structure. May be NULL on return, return value is set to an error
|
||||
* in that case (out of memory).
|
||||
* @throws UnboundException when an error occurred.
|
||||
*/
|
||||
public static native UnboundResult resolve(long context, String name,
|
||||
int rrtype, int rrclass) throws UnboundException;
|
||||
|
||||
/**
|
||||
* Perform resolution and validation of the target name.
|
||||
* <p>
|
||||
* Asynchronous, after a while, the callback will be called with your data
|
||||
* and the result.
|
||||
*
|
||||
* @param context context. If no thread or process has been created yet to
|
||||
* perform the work in the background, it is created now. The
|
||||
* context is finalized, and can no longer accept config changes.
|
||||
* @param name domain name in text format (a string).
|
||||
* @param rrtype type of RR in host order, 1 is A.
|
||||
* @param rrclass class of RR in host order, 1 is IN (for internet).
|
||||
* @param data this data is your own data (you can pass null), and is passed
|
||||
* on to the callback function.
|
||||
* @param cb this is called on completion of the resolution.
|
||||
* @return an identifier number is returned for the query as it is in
|
||||
* progress. It can be used to cancel the query.
|
||||
* @throws UnboundException when an error occurred.
|
||||
*/
|
||||
public static native int resolveAsync(long context, String name,
|
||||
int rrtype, int rrclass, Object data, UnboundCallback cb)
|
||||
throws UnboundException;
|
||||
|
||||
/**
|
||||
* Cancel an async query in progress. Its callback will not be called.
|
||||
*
|
||||
* @param context context.
|
||||
* @param asyncId which query to cancel.
|
||||
* @throws UnboundException This routine can error if the async_id passed
|
||||
* does not exist or has already been delivered. If another
|
||||
* thread is processing results at the same time, the result may
|
||||
* be delivered at the same time and the cancel fails with an
|
||||
* error. Also the cancel can fail due to a system error, no
|
||||
* memory or socket failures.
|
||||
*/
|
||||
public static native void cancelAsync(long context, int asyncId)
|
||||
throws UnboundException;
|
||||
|
||||
/**
|
||||
* Convert error value to a human readable string.
|
||||
*
|
||||
* @param code error code from one of the Unbound functions.
|
||||
* @return text string of the error code.
|
||||
*/
|
||||
public static native String errorCodeToString(int code);
|
||||
|
||||
/**
|
||||
* Wait for a context to finish with results. Call this routine to continue
|
||||
* processing results from the validating resolver. After the wait, there
|
||||
* are no more outstanding asynchronous queries.
|
||||
*
|
||||
* @param context context.
|
||||
* @throws UnboundException when an error occurred.
|
||||
*/
|
||||
public static native void processAsync(long context)
|
||||
throws UnboundException;
|
||||
|
||||
/**
|
||||
* Interface for the async resolve callback.
|
||||
*/
|
||||
public interface UnboundCallback
|
||||
{
|
||||
/**
|
||||
* Called on completion of the async resolution.
|
||||
*
|
||||
* @param data the same object as passed to
|
||||
* {@link UnboundApi#resolveAsync(long, String, int, int,
|
||||
* Object, UnboundCallback)}
|
||||
* @param err 0 when a result has been found, an Unbound error code
|
||||
* otherwise
|
||||
* @param result a newly allocated result structure. The result may be
|
||||
* null, in that case err is set.
|
||||
*/
|
||||
public void UnboundResolveCallback(Object data, int err,
|
||||
UnboundResult result);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
/**
|
||||
* Exception that is being thrown when native Unbound code resulted in an error.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class UnboundException
|
||||
extends Exception
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
*
|
||||
* @param message the detail message.
|
||||
*/
|
||||
public UnboundException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link Resolver} interface, wrapping the native NLnet
|
||||
* Labs Unbound resolver. Only the basic methods for queries are supported.
|
||||
*
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class UnboundResolver
|
||||
implements Resolver
|
||||
{
|
||||
private final static Logger logger =
|
||||
Logger.getLogger(UnboundResolver.class);
|
||||
|
||||
/**
|
||||
* Helper class to synchronize on asynchronous queries.
|
||||
*/
|
||||
private static class CallbackData
|
||||
{
|
||||
/**
|
||||
* The resolver consumer that wishes to be informed when the request
|
||||
* completed.
|
||||
*/
|
||||
ResolverListener listener;
|
||||
|
||||
/**
|
||||
* The unbound session context.
|
||||
*/
|
||||
long context;
|
||||
|
||||
/**
|
||||
* The ID of the unbound async query.
|
||||
*/
|
||||
int asyncId;
|
||||
|
||||
/**
|
||||
* Java synchronization on top of unbound.
|
||||
*/
|
||||
CountDownLatch sync = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout for DNS queries.
|
||||
*/
|
||||
private int timeout = 10000;
|
||||
|
||||
/**
|
||||
* The recursive DNS servers answering our queries.
|
||||
*/
|
||||
private String[] forwarders;
|
||||
|
||||
/**
|
||||
* DNSSEC trust anchors for signed zones (usually for the root zone).
|
||||
*/
|
||||
private List<String> trustAnchors = new LinkedList<String>();
|
||||
|
||||
/**
|
||||
* Pool that executes our queries.
|
||||
*/
|
||||
private ExecutorService threadPool;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
*/
|
||||
public UnboundResolver()
|
||||
{
|
||||
threadPool = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of forwarders to use instead of the system default.
|
||||
*
|
||||
* @param forwarders list of servers to use for our queries.
|
||||
*/
|
||||
public void setForwarders(String[] forwarders)
|
||||
{
|
||||
this.forwarders = forwarders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DNSSEC trust anchor validation of the DNSKEYs.
|
||||
*
|
||||
* @param anchor trust anchor in the form of
|
||||
* "'zone' IN DS 'key tag' 'algorithm' 'digest type' 'digest'"
|
||||
*/
|
||||
public void addTrustAnchor(String anchor)
|
||||
{
|
||||
trustAnchors.add(anchor);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SecureMessage send(final Message query) throws IOException
|
||||
{
|
||||
Future<SecureMessage> future = threadPool.submit(
|
||||
new Callable<SecureMessage>()
|
||||
{
|
||||
public SecureMessage call() throws Exception
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug(query);
|
||||
|
||||
SecureMessage secureMessage = null;
|
||||
final long context = prepareContext();
|
||||
try
|
||||
{
|
||||
UnboundResult result = UnboundApi.resolve(
|
||||
context,
|
||||
query.getQuestion().getName().toString(),
|
||||
query.getQuestion().getType(),
|
||||
query.getQuestion().getDClass()
|
||||
);
|
||||
secureMessage = new SecureMessage(result);
|
||||
validateMessage(secureMessage);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnboundApi.deleteContext(context);
|
||||
if(logger.isDebugEnabled() && secureMessage != null)
|
||||
logger.debug(secureMessage);
|
||||
}
|
||||
|
||||
return secureMessage;
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
return future.get(timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
logger.error(e);
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
if(e.getCause() instanceof DnssecRuntimeException)
|
||||
throw new DnssecRuntimeException(e.getCause().getMessage());
|
||||
logger.error(e);
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
catch (TimeoutException e)
|
||||
{
|
||||
throw new SocketTimeoutException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to allow overriders to inspect the message. This class'
|
||||
* implementation does nothing.
|
||||
*
|
||||
* @param msg The message to inspect.
|
||||
* @throws DnssecRuntimeException if the inspector does not want the code to
|
||||
* continue normal processing of the answer.
|
||||
*/
|
||||
protected void validateMessage(SecureMessage msg)
|
||||
throws DnssecRuntimeException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a unbound session context initialized with forwarders and trust
|
||||
* anchors.
|
||||
*
|
||||
* @return The context id
|
||||
*/
|
||||
private long prepareContext()
|
||||
{
|
||||
final long context = UnboundApi.createContext();
|
||||
if(logger.isTraceEnabled())
|
||||
UnboundApi.setDebugLevel(context, 100);
|
||||
for(String fwd : forwarders == null
|
||||
? ResolverConfig.getCurrentConfig().servers()
|
||||
: forwarders)
|
||||
{
|
||||
fwd = fwd.trim();
|
||||
if(NetworkUtils.isValidIPAddress(fwd))
|
||||
{
|
||||
if(fwd.startsWith("["))
|
||||
fwd = fwd.substring(1, fwd.length() - 1);
|
||||
UnboundApi.setForwarder(context, fwd);
|
||||
}
|
||||
}
|
||||
for(String anchor : trustAnchors)
|
||||
{
|
||||
UnboundApi.addTrustAnchor(context, anchor);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up an Unbound session context.
|
||||
*
|
||||
* @param cbData The helper object of the asynchronous call.
|
||||
* @param cancelAsync Whether an outstanding asynchronous unbound query
|
||||
* should be canceled.
|
||||
*/
|
||||
private static synchronized void deleteContext(CallbackData cbData,
|
||||
boolean cancelAsync)
|
||||
{
|
||||
if(cbData.context == 0)
|
||||
return;
|
||||
|
||||
if(cancelAsync)
|
||||
{
|
||||
try
|
||||
{
|
||||
UnboundApi.cancelAsync(cbData.context, cbData.asyncId);
|
||||
}
|
||||
catch (UnboundException ignore)
|
||||
{}
|
||||
}
|
||||
UnboundApi.deleteContext(cbData.context);
|
||||
cbData.context = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.xbill.DNS.Resolver#sendAsync(org.xbill.DNS.Message,
|
||||
* org.xbill.DNS.ResolverListener)
|
||||
*/
|
||||
public CallbackData sendAsync(Message query, ResolverListener listener)
|
||||
{
|
||||
if(listener == null)
|
||||
throw new IllegalArgumentException("listener cannot be null");
|
||||
|
||||
final long context = prepareContext();
|
||||
final CallbackData cbData = new CallbackData();
|
||||
cbData.listener = listener;
|
||||
cbData.context = context;
|
||||
int asyncId;
|
||||
try
|
||||
{
|
||||
asyncId = UnboundApi.resolveAsync(
|
||||
context,
|
||||
query.getQuestion().getName().toString(),
|
||||
query.getQuestion().getType(),
|
||||
query.getQuestion().getDClass(),
|
||||
cbData,
|
||||
new UnboundApi.UnboundCallback()
|
||||
{
|
||||
public void UnboundResolveCallback(Object data, int err,
|
||||
UnboundResult result)
|
||||
{
|
||||
CallbackData cbData = (CallbackData)data;
|
||||
deleteContext(cbData, false);
|
||||
|
||||
ResolverListener l = cbData.listener;
|
||||
if(err == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
l.receiveMessage(data,
|
||||
new SecureMessage(result));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
l.handleException(data, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
l.handleException(data,
|
||||
new Exception(
|
||||
UnboundApi.errorCodeToString(err)));
|
||||
|
||||
cbData.sync.countDown();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (UnboundException e)
|
||||
{
|
||||
listener.handleException(null, e);
|
||||
return null;
|
||||
}
|
||||
cbData.asyncId = asyncId;
|
||||
threadPool.execute(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
UnboundApi.processAsync(context);
|
||||
}
|
||||
catch(UnboundException ex)
|
||||
{
|
||||
cbData.listener.handleException(this, ex);
|
||||
deleteContext(cbData, false);
|
||||
cbData.sync.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
return cbData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setEDNS(int level)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setEDNS(int level, int payloadSize, int flags, List options)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setIgnoreTruncation(boolean flag)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setTCP(boolean flag)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setTSIGKey(TSIG key)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.xbill.DNS.Resolver#setTimeout(int)
|
||||
*/
|
||||
public void setTimeout(int secs)
|
||||
{
|
||||
timeout = secs * 1000;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.xbill.DNS.Resolver#setTimeout(int, int)
|
||||
*/
|
||||
public void setTimeout(int secs, int msecs)
|
||||
{
|
||||
timeout = secs * 1000 + msecs;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.util.dns;
|
||||
|
||||
/**
|
||||
* Class that contains the answer to query processed by the native Unbound
|
||||
* resolver. Corresponds to the <a
|
||||
* href="http://unbound.net/documentation/doxygen/structub__result.html"
|
||||
* >ub_result</a> data structure.
|
||||
*
|
||||
* The fields {@link #data} and {@link #canonname} are not filled.
|
||||
* <p>
|
||||
* The JavaDoc of these fields is directly copied from libunbound, licensed as
|
||||
* follows:
|
||||
* <p>
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* @author Ingo Bauersachs
|
||||
*/
|
||||
public class UnboundResult
|
||||
{
|
||||
/**
|
||||
* The original question, name text string.
|
||||
*/
|
||||
String qname;
|
||||
|
||||
/**
|
||||
* the type asked for
|
||||
*/
|
||||
int qtype;
|
||||
|
||||
/**
|
||||
* the type asked for
|
||||
*/
|
||||
int qclass;
|
||||
|
||||
|
||||
/**
|
||||
* a list of network order DNS rdata items, terminated with a NULL pointer,
|
||||
* so that data[0] is the first result entry, data[1] the second, and the
|
||||
* last entry is NULL.
|
||||
*/
|
||||
byte[][] data;
|
||||
|
||||
/**
|
||||
* canonical name for the result (the final cname).
|
||||
*/
|
||||
String canonname;
|
||||
|
||||
/**
|
||||
* DNS RCODE for the result.
|
||||
*/
|
||||
int rcode;
|
||||
|
||||
/**
|
||||
* The DNS answer packet.
|
||||
*/
|
||||
byte[] answerPacket;
|
||||
|
||||
|
||||
/**
|
||||
* If there is any data, this is true.
|
||||
*/
|
||||
boolean haveData;
|
||||
|
||||
/**
|
||||
* If there was no data, and the domain did not exist, this is true.
|
||||
*/
|
||||
boolean nxDomain;
|
||||
|
||||
/**
|
||||
* True, if the result is validated securely.
|
||||
*/
|
||||
boolean secure;
|
||||
|
||||
/**
|
||||
* If the result was not secure ({@link #secure} == false), and this result
|
||||
* is due to a security failure, bogus is true.
|
||||
*/
|
||||
boolean bogus;
|
||||
|
||||
/**
|
||||
* If the result is bogus this contains a string (zero terminated) that
|
||||
* describes the failure.
|
||||
*/
|
||||
String whyBogus;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
Bundle-Activator: net.java.sip.communicator.util.dns.DnsUtilActivator
|
||||
Bundle-Name: SIP Communicator DNS Utility Packages
|
||||
Bundle-SymbolicName: net.java.sip.communicator.util.dns
|
||||
Bundle-Description: A bundle that export packages with DNS utility classes.
|
||||
Bundle-Vendor: sip-communicator.org
|
||||
Bundle-Version: 0.0.1
|
||||
System-Bundle: yes
|
||||
Import-Package:
|
||||
org.osgi.framework,
|
||||
net.java.sip.communicator.util,
|
||||
net.java.sip.communicator.util.swing,
|
||||
net.java.sip.communicator.service.resources,
|
||||
net.java.sip.communicator.service.configuration,
|
||||
net.java.sip.communicator.service.notification,
|
||||
sun.net.dns,
|
||||
org.xbill.DNS,
|
||||
javax.swing
|
||||
Export-Package: net.java.sip.communicator.util.dns
|
||||
Loading…
Reference in new issue