use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class MailingOldImpl method transport_post.
/*
* post
* = procedure 1
*/
private static void transport_post(PostParams params, PostResults results) {
// log ingoing data
if (logParamsAndResults) {
StringBuilder sb = new StringBuilder();
params.append(sb, " ", "params");
log("##\n## procedure MailingImpl.transport_post() -- params\n%s\n##\n", sb.toString());
}
// check the credentials:
// - this procedure is called for the generic mail server ("Mail Service:CHServers:CHServers")
// - not for this specific mail service (which the 1st mail service name in the clearinghouse database)
// - so use the generic name
// - and: only the machine id for *this* mail service works...
Credentials credentials = params.authPair.credentials;
Verifier verifier = params.authPair.verifier;
StrongVerifier decodedVerifier = StrongVerifier.make();
int[] decodedConversationKey = new int[4];
ThreePartName senderName = // throws an exception on invalid credentials
mailService.checkCredentials(mailService.getChsDatabase().getGenericMailServiceName(), mailService.getMachineId(), credentials, verifier, decodedConversationKey, decodedVerifier);
// check the recipients
NameList allRecipients = NameList.make();
ChsDatabase chs = mailService.getChsDatabase();
for (int i = 0; i < params.recipients.size(); i++) {
Name rcpt = params.recipients.get(i);
String rcptFqn = chs.resolveName(rcpt);
List<Name> dlMemberNames;
if (rcptFqn != null && mailService.hasMailbox(rcptFqn)) {
Name rcptName = Name.make();
rcptName.from(rcptFqn);
allRecipients.addDistinct(rcptName);
} else if (params.allowDLRecipients.get() && rcptFqn != null && (dlMemberNames = getUserGroupMembersLcFqns(rcptFqn)) != null) {
for (Name dlMember : dlMemberNames) {
allRecipients.addDistinct(dlMember);
}
} else {
UndeliveredName undelivered = UndeliveredName.make();
undelivered.reason.set(UndeliveredNameType.noSuchRecipient);
undelivered.name.from(rcpt);
results.invalidNames.add(undelivered);
}
}
// if invalid recipients are not allowed and we have some or if all recipients are invalid: throw error...
if ((results.invalidNames.size() > 0 && !params.postIfInvalidNames.get()) || results.invalidNames.size() == params.recipients.size()) {
InvalidRecipientsErrorRecord err = new InvalidRecipientsErrorRecord();
for (int i = 0; i < results.invalidNames.size(); i++) {
err.nameList.add(results.invalidNames.get(i));
}
err.raise();
}
// so create the mail
try {
ByteContentSource source = new ByteContentSource(params.content);
if (allRecipients.size() > 0) {
int[] mailId = mailService.postMail(senderName, allRecipients, params.contentsType.get(), source);
for (int i = 0; i < mailId.length; i++) {
results.msgID.get(i).set(mailId[i]);
}
} else {
// abort bulk-data transfer
source.read(null);
}
} catch (EndOfMessageException e) {
new ConnectionErrorRecord(ConnectionProblem.otherCallProblem).raise();
}
// log outgoing data
if (logParamsAndResults) {
StringBuilder sb = new StringBuilder();
results.append(sb, " ", "results");
log("##\n## procedure MailingImpl.transport_post() -- results\n%s\n##\n", sb.toString());
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class Authentication2Impl method init.
/**
* Set values to use for responses.
*
* @param network networkId for the local network
* @param machine hostId of the local machine
* @param chsDb clearinghouse database to use for courier requests
* @param hostIds explicit list of network addresses to respond BfS requests with
* (if the local machine is to be part of the BfS responses, the host
* {@code network}/{@code machine} must be explicitely added to {@code hostIds})
*/
public static void init(long network, long machine, ChsDatabase chsDb, List<NetworkAddress> hostIds) {
networkId = network;
machineId = machine;
chsDatabase = chsDb;
bfsHosts.clear();
if (hostIds == null || hostIds.isEmpty()) {
// add the only known server to the address list: ourself
NetworkAddress addr = NetworkAddress.make();
addr.network.set((int) networkId);
addr.host.set(machineId);
addr.socket.set(0);
bfsHosts.add(addr);
} else {
bfsHosts.addAll(hostIds);
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class Clearinghouse3Impl method checkCredentials.
/* internal functionality */
private static void checkCredentials(String procName, Authenticator agent, boolean allowEmptyCredentials) {
boolean credentialsOk = false;
try {
if (agent.credentials.value.size() == 0) {
credentialsOk = allowEmptyCredentials;
} else if (agent.credentials.type.get() == CredentialsType.simple) {
credentialsOk = AuthChsCommon.simpleCheckPasswordForSimpleCredentials(chsDatabase, agent.credentials, agent.verifier) != null;
} else {
credentialsOk = AuthChsCommon.checkStrongCredentials(chsDatabase, agent.credentials, agent.verifier, chsDatabase.getChsQueryName(), machineId, null, null) != null;
}
} catch (IllegalArgumentException iac) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.credentialsInvalid);
Log.C.printf("CHS3", "Clearinghouse3Impl.%s() IllegalArgumentException (name not existing) -> rejecting with AuthenticationError[credentialsInvalid]\n", procName);
err.raise();
} catch (EndOfMessageException e) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.inappropriateCredentials);
Log.C.printf("CHS3", "Clearinghouse3Impl.%s() EndOfMessageException when deserializing credsObject -> rejecting with AuthenticationError[inappropriateCredentials]\n", procName);
err.raise();
} catch (Exception e) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.otherProblem);
Log.C.printf("CHS3", "Clearinghouse3Impl.%s() Exception when checking credentials -> rejecting with AuthenticationError[otherProblem]: %s\n", procName, e.getMessage());
err.raise();
}
if (!credentialsOk) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.credentialsInvalid);
Log.C.printf("CHS3", "Clearinghouse3Impl.%s() -> rejecting with AuthenticationError[credentialsInvalid]\n", procName);
err.raise();
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class AuthChsCommon method checkStrongCredentials.
/**
* Check that the strong credentials and the strong verifier are
* both valid for the recipient on the given machine.
*
* @param chsDatabase the clearinghouse database to check against
* @param credentials the credentials to verify
* @param verifier the verifier going with the credentials
* @param recipient the recipient for which the the strong credentials are encoded
* @param recipientMachineId the target machine for which the verifier is encoded
* @param decodedConversationKey target where to store the conversation encryption key for
* the session (the key will only be stored there if not {@code null} and at least
* 4 entries long).
* @return {@code null} if the credentials is not of strong type or the
* initiator encoded in the credentials is invalid or if the expiration time
* of the credentials are expired or the verifier timestamp is invalid;
* else the Clearinghouse name of the user if the credentials passed the tests.
* @throws EndOfMessageException if decoding the credentials or verifier after
* decryption fails
* @throws IllegalArgumentException if the recipient is invalid or has no
* strong password for decryption
* @throws Exception if any decryption fails
*/
public static ThreePartName checkStrongCredentials(ChsDatabase chsDatabase, Credentials credentials, Verifier verifier, ThreePartName recipient, long recipientMachineId, int[] decodedConversationKey, StrongVerifier decodedVerifier) throws Exception {
// get the recipient decryption password
if (credentials.type.get() != CredentialsType.strong) {
return null;
}
byte[] recipientStrongPw = chsDatabase.getStrongPassword(recipient);
if (recipientStrongPw == null) {
throw new IllegalArgumentException("Invalid recipient (strong password not found)");
}
int[] recipientDecryptPw = StrongAuthUtils.toWords(recipientStrongPw);
// decode the credentials with the recipient's strong password
StrongCredentials creds = StrongCredentials.make();
decryptFrom(recipientDecryptPw, credentials.value, creds);
// decrypt the verifier
if (decodedConversationKey == null || decodedConversationKey.length < 4) {
decodedConversationKey = new int[4];
}
decodedConversationKey[0] = creds.conversationKey.get(0).get();
decodedConversationKey[1] = creds.conversationKey.get(1).get();
decodedConversationKey[2] = creds.conversationKey.get(2).get();
decodedConversationKey[3] = creds.conversationKey.get(3).get();
StrongVerifier verfr = StrongVerifier.make();
decryptFrom(decodedConversationKey, verifier, verfr);
// left justified machine-id => upper 32 bits
long rcptTimestampMachineId32Bits = (recipientMachineId >> 16) & 0xFFFFFFFFL;
// left justified machine-id => lower 32 bits
long rcptTicksMachineId32Bits = (recipientMachineId & 0x0000FFFFL) << 16;
long verifierTicks = verfr.ticks.get() ^ rcptTicksMachineId32Bits;
long verifierTimestamp = verfr.timeStamp.get() ^ rcptTimestampMachineId32Bits;
if (decodedVerifier != null) {
decodedVerifier.ticks.set(verifierTicks);
decodedVerifier.timeStamp.set(verifierTimestamp);
}
// (temp) log the relevant data
Time now = Time.make().now();
System.out.printf("creds.initiator: %s:%s:%s\n", creds.initiator.object.get(), creds.initiator.domain.get(), creds.initiator.organization.get());
System.out.printf("creds.expiration: %d (now: %d)\n", creds.expirationTime.get(), now.get());
System.out.printf("verifier.timeStamp: 0x%08X = %d -> xor-ed(machineId): 0x%08X = %s (now: 0x%08X = %d)\n", verfr.timeStamp.get(), verfr.timeStamp.get(), verifierTimestamp, verifierTimestamp, now.get(), now.get());
System.out.printf("verifier.ticks: 0x%08X = %d -> xor-ed(machineId): 0x%08X = %d\n", verfr.ticks.get(), verfr.ticks.get(), verifierTicks, verifierTicks);
// check the credentials / verifier
if (!chsDatabase.isValidName(creds.initiator)) {
System.out.println("** checkStrongCredentials() => ERR: creds.initiator is not a valid name");
return null;
}
boolean skipTimestampChecks = MachineIds.getCfgBoolean(credentials.remoteHostId.get(), MachineIds.CFG_AUTH_SKIP_TIMESTAMP_CHECKS, false);
if (!skipTimestampChecks) {
if (now.get() > creds.expirationTime.get()) {
System.out.println("** checkStrongCredentials() => ERR: now > creds.expirationTime");
return null;
}
if (now.get() < verifierTimestamp) {
System.out.println("** checkStrongCredentials() => ERR: now < verifierTimestamp");
return null;
}
if (now.get() > (verifierTimestamp + 60)) {
System.out.println("** checkStrongCredentials() => ERR: now > verifierTimestamp+60secs");
return null;
}
} else {
System.out.println("** checkStrongCredentials() => timestamp checks skipped (creds.expirationTime, verifier.timestamp)");
}
System.out.println("** checkStrongCredentials() => strong credentials OK");
return new ThreePartName().from(creds.initiator);
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class DodoServer method main.
public static void main(String[] args) throws XnsException {
String machinesFile = null;
String baseCfgFile = null;
String cfgFile = null;
boolean dumpChs = false;
// get commandline args
for (String arg : args) {
if (arg.toLowerCase().startsWith("-machinecfg:")) {
String[] parts = arg.split(":");
machinesFile = parts[1];
} else if (arg.toLowerCase().startsWith("-basecfg:")) {
String[] parts = arg.split(":");
baseCfgFile = parts[1];
} else if ("-dumpchs".equalsIgnoreCase(arg)) {
dumpChs = true;
} else if (cfgFile == null) {
cfgFile = arg;
} else {
System.out.printf("Warning: ignoring unknown argument: %s\n", arg);
}
}
// load machines configuration
if (!MachineIds.loadDefinitions(machinesFile)) {
System.out.println("!! failed to load machines configuration");
}
// load configuration(s)
if (baseCfgFile == null) {
File f = new File(DEFAULT_BASECONFIG_FILE);
if (f.exists() && f.canRead()) {
baseCfgFile = DEFAULT_BASECONFIG_FILE;
System.out.printf("Found and using default commons configuration: %s\n", baseCfgFile);
}
}
if (cfgFile == null && (new File(DEFAULT_CONFIG_FILE)).canRead()) {
cfgFile = DEFAULT_CONFIG_FILE;
}
if (baseCfgFile != null) {
initializeConfiguration(baseCfgFile);
}
if (cfgFile != null && !initializeConfiguration(cfgFile)) {
return;
}
// put parts of the configuration data as defaults for client machines
MachineIds.setDefault(MachineIds.CFG_AUTH_SKIP_TIMESTAMP_CHECKS, authSkipTimestampChecks);
MachineIds.setDefault(MachineIds.CFG_BOOTSVC_SIMPLEDATA_SEND_INTERVAL, bootServiceSimpleDataSendInterval);
MachineIds.setDefault(MachineIds.CFG_BOOTSVC_SPPDATA_SEND_INTERVAL, bootServiceSppDataSendInterval);
MachineIds.setDefault(MachineIds.CFG_SPP_HANDSHAKE_SENDACK_COUNTDOWN, sppHandshakeSendackCountdown);
MachineIds.setDefault(MachineIds.CFG_SPP_RESEND_DELAY, sppResendDelay);
MachineIds.setDefault(MachineIds.CFG_SPP_HANDSHAKE_RESEND_COUNTDOWN, sppHandshakeResendCountdown);
MachineIds.setDefault(MachineIds.CFG_SPP_HANDSHAKE_MAX_RESENDS, sppHandshakeMaxResends);
MachineIds.setDefault(MachineIds.CFG_SPP_RESEND_PACKET_COUNT, sppResendPacketCount);
MachineIds.setDefault(MachineIds.CFG_SPP_SENDING_TIME_GAP, sppSendingTimeGap);
// this parameter is global to all SPP connections (cannot be specified at client machine level)
SppConnection.setHandshakeCheckInterval(sppHandshakeCheckInterval);
// open CHS database if there are services requiring it
ChsDatabase chsDatabase = null;
if (startChsAndAuth || !fileServiceSpecs.isEmpty()) {
// create the clearinghouse database
chsDatabase = new ChsDatabase(networkNo, organizationName, domainName, chsDatabaseRoot, allowBlanksInObjectNames);
if (dumpChs) {
System.out.println("\n==\n== machine-id pre-definitions:\n==\n");
MachineIds.dump();
System.out.println("\n==\n== clearinghouse database dump: \n==\n");
chsDatabase.dump();
System.out.println("\n==\n== end of machine-id and clearinghouse database dumps\n==\n");
}
}
// check if we have undefined machine names, aborting startup if any
List<String> undefinedMachineNames = MachineIds.getUndefinedMachineNames();
if (!undefinedMachineNames.isEmpty()) {
System.out.println("The following machine names or IDs are undefined or invalid:");
for (String name : undefinedMachineNames) {
System.out.printf(" -> name: %s\n", name);
}
System.out.printf("Aborting Dodo startup ...\n... please correct the configuration or define the above names in the machine ids file (%s)\n", machinesFile);
System.exit(2);
}
// configure and start the network engine
LocalSite.configureHub(netHubHost, netHubPort);
LocalSite.configureLocal(networkNo, machineId, "DodoServer", doChecksums, doDarkstarWorkaround);
localSite = LocalSite.getInstance();
// set time base for all time dependent items
Time2.setTimeWarp(daysBackInTime);
// boot service
if (startBootService) {
BootResponder bootService = new BootResponder(bootServiceBasedir, bootServiceVerbose);
localSite.clientBindToSocket(IDP.KnownSocket.BOOT.getSocket(), bootService);
}
// echo service
if (startEchoService) {
localSite.clientBindToSocket(IDP.KnownSocket.ECHO.getSocket(), new EchoResponder());
}
// time service
if (startTimeService) {
localSite.pexListen(IDP.KnownSocket.TIME.getSocket(), new TimeServiceResponder(localTimeOffsetMinutes, timeServiceSendingTimeGap));
}
// routing protocol responder
RipResponder ripResponder = null;
if (startRipService) {
ripResponder = new RipResponder();
localSite.clientBindToSocket(IDP.KnownSocket.ROUTING.getSocket(), ripResponder);
}
// clearinghouse and authentication services
if (startChsAndAuth) {
// broadcast for clearinghouse service
// one common implementation for versions 2 and 3, as both versions have the same RetrieveAddresses method
Clearinghouse3Impl.init(localSite.getNetworkId(), localSite.getMachineId(), chsDatabase);
localSite.pexListen(IDP.KnownSocket.CLEARINGHOUSE.getSocket(), new BfsClearinghouseResponder(ripResponder), null);
// broadcast for authentication service
// one common implementation for versions 1, 2 and 3, as all versions are assumed to have
// the same (undocumented) RetrieveAddresses method
Authentication2Impl.init(localSite.getNetworkId(), localSite.getMachineId(), chsDatabase);
localSite.pexListen(IDP.KnownSocket.AUTH.getSocket(), new BfsAuthenticationResponder());
// register clearinghouse and authentication courier programs in registry
Clearinghouse3Impl.register();
Authentication2Impl.register();
// start the mailService always co-located with the clearinghouse
if (mailServiceVolumePath != null) {
MailingOldImpl.init(localSite.getNetworkId(), localSite.getMachineId(), chsDatabase, mailServiceVolumePath);
MailingOldImpl.register();
MailingNewImpl.init(localSite.getNetworkId(), localSite.getMachineId(), chsDatabase, MailingOldImpl.getMailService());
MailingNewImpl.register();
localSite.pexListen(0x001A, new MailingExpeditedCourierResponder());
}
}
// print service
if (printServiceName != null && printServiceOutputDirectory != null) {
try {
Printing3Impl.init(printServiceName, printServiceOutputDirectory, printServiceDisassembleIp, printServicePaperSizes, printServiceIp2PsProcFilename, printServicePsPostprocessor);
Printing3Impl.register();
} catch (Exception e) {
System.out.printf("Error starting printservice '%s': %s\n", printServiceName, e.getMessage());
}
}
// file service(s)
if (fileServiceSpecs.size() > 0) {
// initialize
FilingImpl.init(localSite.getNetworkId(), localSite.getMachineId(), chsDatabase);
// open volume(s)
int openVolumes = 0;
for (Entry<String, String> spec : fileServiceSpecs.entrySet()) {
ThreePartName serviceName = ThreePartName.make().from(spec.getKey());
String volumeBasedirName = spec.getValue();
if (FilingImpl.addVolume(serviceName, volumeBasedirName)) {
openVolumes++;
}
}
// register Courier implementation if volume(s) were successfully opened
if (openVolumes > 0) {
FilingImpl.register();
} else {
System.out.printf("No volumes opened successfully, not registering Filing to Courier");
}
}
// run courier server with dispatcher
CourierServer courierServer = new CourierServer(localSite);
// silence logging a bit
Log.L0.doLog(false);
Log.L1.doLog(false);
Log.L2.doLog(false);
Log.L3.doLog(false);
Log.L4.doLog(false);
/*
* let the server machine run...
*/
}
Aggregations