From 3ee3e4abeb680cd8d8586956912c0939da842ba5 Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Wed, 22 May 2002 07:38:29 +0000 Subject: [PATCH] upgraded the internal Emailer class into the new MailSend class that can do pretty much anything; emailer and stock messages are now managed through the GlobalSite; security-releated generation is now handled through the Generator class instead of several different ones --- etc/venice-config.xml | 7 + .../core/impl/AdminUserContextImpl.java | 4 +- .../core/impl/CommunityUserContextImpl.java | 28 +- .../core/impl/ConferenceUserContextImpl.java | 9 +- .../venice/core/impl/MailerAgent.java | 34 +- .../venice/core/impl/PersonalMailSend.java | 159 ++++++++++ .../venice/core/impl/PostDeliveryAgent.java | 27 +- .../venice/core/impl/SimpleEmailer.java | 176 ----------- .../core/impl/TopicUserContextImpl.java | 9 +- .../venice/core/impl/UserContextImpl.java | 35 ++- .../venice/core/impl/UserProfileImpl.java | 18 +- .../venice/core/impl/VeniceEngineImpl.java | 122 ++------ .../venice/core/internals/BaseMailSend.java | 293 ++++++++++++++++++ .../venice/core/internals/EngineBackend.java | 10 - .../venice/core/internals/EnvEngine.java | 9 +- .../venice/core/internals/GlobalSiteImpl.java | 35 ++- .../venice/security/Generator.java | 210 +++++++++++++ .../venice/security/PasswordGenerator.java | 114 ------- .../venice/security/PasswordHash.java | 150 --------- .../venice/svc/internals/GlobalSite.java | 2 + .../Emailer.java => util/MailSend.java} | 28 +- 21 files changed, 835 insertions(+), 644 deletions(-) create mode 100644 src/com/silverwrist/venice/core/impl/PersonalMailSend.java delete mode 100644 src/com/silverwrist/venice/core/impl/SimpleEmailer.java create mode 100644 src/com/silverwrist/venice/core/internals/BaseMailSend.java create mode 100644 src/com/silverwrist/venice/security/Generator.java delete mode 100644 src/com/silverwrist/venice/security/PasswordGenerator.java delete mode 100644 src/com/silverwrist/venice/security/PasswordHash.java rename src/com/silverwrist/venice/{core/internals/Emailer.java => util/MailSend.java} (57%) diff --git a/etc/venice-config.xml b/etc/venice-config.xml index 45934b4..1289d58 100644 --- a/etc/venice-config.xml +++ b/etc/venice-config.xml @@ -331,6 +331,13 @@ Venice - community services, conferencing and more. ]]> + + +The Venice Project is not responsible for the contents of this message +Report abuses to: + ]]> + , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -23,6 +23,7 @@ import com.silverwrist.util.StringUtil; import com.silverwrist.venice.core.internals.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.htmlcheck.*; +import com.silverwrist.venice.util.MailSend; class MailerAgent extends Thread { @@ -38,29 +39,21 @@ class MailerAgent extends Thread *-------------------------------------------------------------------------------- */ - private EnvUser env; // the environment - private String from_name; // the "from" name - private String from_addr; // the "from" address + private MailSend msend; // the mail sender private List recipients; // who gets the message - private String subject; // message subject - private String text; // message text /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ - MailerAgent(EnvUser env, String from_name, String from_addr, List recipients, String subject, String text) + MailerAgent(MailSend msend, List recipients) { super(); setDaemon(false); - this.env = env; - this.from_name = from_name; - this.from_addr = from_addr; + this.msend = msend; this.recipients = recipients; - this.subject = subject; - this.text = text; } // end constructor @@ -74,16 +67,7 @@ class MailerAgent extends Thread NDC.push("MailerAgent"); try - { // attach the signature to the message - StringBuffer buf = new StringBuffer(text); - buf.append("\n--\n").append(env.getStockMessage("signature")); - - // Create the emailer object and load it up with most of the data. - Emailer em = env.getEngine().createEmailer(); - em.setSubject(subject); - em.setText(buf.toString()); - - // Deliver the mail to each of the target addresses in turn. + { // Deliver the mail to each of the target addresses in turn. Iterator it = recipients.iterator(); while (it.hasNext()) { // get ready to deliver the mail... @@ -93,9 +77,9 @@ class MailerAgent extends Thread try { // set the recipient and send it out - em.setFrom(from_name,from_addr); - em.setTo(addr); - em.send(); + msend.clearRecipients(MailSend.RECIP_TO); + msend.addRecipient(MailSend.RECIP_TO,addr); + msend.send(); } // end try catch (EmailException e) diff --git a/src/com/silverwrist/venice/core/impl/PersonalMailSend.java b/src/com/silverwrist/venice/core/impl/PersonalMailSend.java new file mode 100644 index 0000000..45b3498 --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/PersonalMailSend.java @@ -0,0 +1,159 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import com.silverwrist.util.*; +import com.silverwrist.venice.core.internals.UserBackend; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.svc.internal.GlobalSite; +import com.silverwrist.venice.util.MailSend; + +class PersonalMailSend implements MailSend +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private MailSend inner; // inner object that we pass through calls to + private GlobalSite site; // for getting stock messages + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + PersonalMailSend(MailSend inner, GlobalSite site, UserBackend user) throws DataException + { + this.inner = inner; + this.site = site; + + try + { // set the "From" address in advance + inner.setFrom(user.realFullName(),user.realEmailAddress()); + + } // end try + catch (EmailException ee) + { // this shouldn't happen + throw new InternalStateError("shouldn\'t be an EmailException here!",ee); + + } // end catch + + StringBuffer buf = new StringBuffer("uid "); + buf.append(user.realUID()).append("; username \"").append(user.realUserName()).append("\"; ip ["); + buf.append(user.userRemoteAddress()).append("]"); + inner.addHeader("X-Venice-Sender-Info",buf.toString()); + String[] headers = StringUtil.splitArray(site.getStockMessage("header-disclaimer"),"\r\n"); + for (int i=0; i. - * - * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT - * WARRANTY OF ANY KIND, either express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Original Code is the Venice Web Communities System. - * - * The Initial Developer of the Original Code is Eric J. Bowersox , - * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. - * - * Contributor(s): - */ -package com.silverwrist.venice.core.impl; - -import java.util.*; -import javax.mail.*; -import javax.mail.internet.*; -import com.silverwrist.venice.core.internals.Emailer; -import com.silverwrist.venice.except.EmailException; -import com.silverwrist.venice.except.InternalStateError; - -class SimpleEmailer implements Emailer -{ - /*-------------------------------------------------------------------------------- - * Attributes - *-------------------------------------------------------------------------------- - */ - - private Session session; // the email session - private MimeMessage msg; // the message being composed - - /*-------------------------------------------------------------------------------- - * Constructor - *-------------------------------------------------------------------------------- - */ - - SimpleEmailer(Properties props, javax.mail.Session session) - { - this.session = session; - msg = new MimeMessage(session); - try - { // set the X-Mailer header - msg.setHeader("X-Mailer",(String)(props.get("com.silverwrist.venice.email.mailer"))); - - } // end try - catch (Exception e) - { // do nothing - we don't really care about this too much - } // end catch - - try - { // set the From address on the message - msg.setFrom(InternetAddress.getLocalAddress(session)); - - } // end try - catch (MessagingException me) - { // this should be impossible - throw new InternalStateError("condition should not apply to message here",me); - - } // end catch - - } // end constructor - - /*-------------------------------------------------------------------------------- - * Implementations from interface Emailer - *-------------------------------------------------------------------------------- - */ - - public void setTo(String to) throws EmailException - { - try - { // create an Internet address and set the recipient to it - InternetAddress[] address = { new InternetAddress(to) }; - msg.setRecipients(Message.RecipientType.TO,address); - - } // end try - catch (AddressException e1) - { // the address was somehow invalid - throw new EmailException("invalid email recipient address",e1); - - } // end catch - catch (MessagingException e2) - { // msg.setRecipients should NOT be throwing a MessageException here! - throw new InternalStateError("condition should not apply to message here",e2); - - } // end catch - - } // end setTo - - public void setFrom(String from_name, String from_addr) throws EmailException - { - try - { // set the "from" address - InternetAddress addr = new InternetAddress(from_addr); - addr.setPersonal(from_name); - msg.setFrom(addr); - - // make sure the "Sender" address reflects our email address - InternetAddress sender = InternetAddress.getLocalAddress(session); - msg.setHeader("Sender",sender.toString()); - - } // end try - catch (AddressException e1) - { // the address was somehow invalid - throw new EmailException("invalid email sender address",e1); - - } // end catch - catch (MessagingException e2) - { // msg.setRecipients should NOT be throwing a MessageException here! - throw new InternalStateError("condition should not apply to message here",e2); - - } // end catch - catch (java.io.UnsupportedEncodingException e3) - { // we can't really have that happen here, either! - throw new InternalStateError("condition should not apply to message here",e3); - - } // end catch - - } // end setFrom - - public void setSubject(String subject) - { - try - { // set the mail message subject - msg.setSubject(subject); - - } // end try - catch (MessagingException e2) - { // msg.setSubject should NOT be throwing a MessageException here! - throw new InternalStateError("condition should not apply to message here",e2); - - } // end catch - - } // end setSubject - - public void setText(String text) - { - try - { // set the mail message subject - msg.setText(text); - - } // end try - catch (MessagingException e2) - { // msg.setText should NOT be throwing a MessageException here! - throw new InternalStateError("condition should not apply to message here",e2); - - } // end catch - - } // end setText - - public void send() throws EmailException - { - try - { // attempt to send the transport message - Transport.send(msg); - - } // end try - catch (SendFailedException e1) - { // convert this exception into an EmailException - throw new EmailException("send of the email message failed: " + e1.getMessage(),e1); - - } // end catch - catch (MessagingException e2) - { // msg.setText should NOT be throwing a MessageException here! - throw new InternalStateError("condition should not apply to message here",e2); - - } // end catch - - } // end send - -} // end class SimpleEmailer - diff --git a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java index b5f91dd..81a72af 100644 --- a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java @@ -28,6 +28,7 @@ import com.silverwrist.venice.db.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.htmlcheck.*; import com.silverwrist.venice.security.AuditRecord; +import com.silverwrist.venice.util.MailSend; class TopicUserContextImpl implements TopicContext { @@ -1370,7 +1371,7 @@ class TopicUserContextImpl implements TopicContext vars.put("community.name",env.getCommunityName()); vars.put("conference.name",env.getConferenceName()); vars.put("topic.name",name); - String extra_msg = env.getEngine().getStockMessage("add-topic-invite"); + String extra_msg = env.getStockMessage("add-topic-invite"); String msg = StringUtil.replaceAllVariables(extra_msg,vars); if (!StringUtil.isStringEmpty(personal_message)) msg += ("\n\n" + personal_message); @@ -1477,8 +1478,10 @@ class TopicUserContextImpl implements TopicContext buf.append("\n\n").append(StringUtil.replaceAllVariables(disklaimer,vars)); // send the actual E-mail messages in the background - MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), - rc,subject,buf.toString()); + MailSend msend = new PersonalMailSend(env.getMailSender(),env.getGlobalSite(),env.getUser()); + msend.setSubject(subject); + msend.setText(buf.toString()); + MailerAgent agent = new MailerAgent(msend,rc); agent.start(); } // end if diff --git a/src/com/silverwrist/venice/core/impl/UserContextImpl.java b/src/com/silverwrist/venice/core/impl/UserContextImpl.java index 2160c6c..e47ffe3 100644 --- a/src/com/silverwrist/venice/core/impl/UserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/UserContextImpl.java @@ -28,6 +28,7 @@ import com.silverwrist.venice.db.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.security.*; import com.silverwrist.venice.svc.ServiceControl; +import com.silverwrist.venice.util.MailSend; class UserContextImpl implements UserContext, UserBackend { @@ -184,7 +185,7 @@ class UserContextImpl implements UserContext, UserBackend logger.debug("sendEmailConfirmation(): sending to \"" + my_email + "\""); // Create the message to be sent. - String message = env.getEngine().getStockMessage("email-confirm"); + String message = env.getStockMessage("email-confirm"); if (message==null) { // no message defined? oy! logger.error("internal error condition: email-confirm stock message not defined"); @@ -198,16 +199,16 @@ class UserContextImpl implements UserContext, UserBackend vars.put("confnum",String.valueOf(confirm_num)); message = StringUtil.replaceAllVariables(message,vars); - String subject = env.getEngine().getStockMessage("email-confirm-subject"); + String subject = env.getStockMessage("email-confirm-subject"); if (subject==null) subject = "Venice Email Confirmation"; // Create the emailer and send the message. - Emailer emailer = env.getEngine().createEmailer(); - emailer.setTo(my_email); - emailer.setSubject(subject); - emailer.setText(message); - emailer.send(); + MailSend msend = env.getMailSender(); + msend.addRecipient(MailSend.RECIP_TO,my_email); + msend.setSubject(subject); + msend.setText(message); + msend.send(); if (logger.isDebugEnabled()) logger.debug("...email sent!"); @@ -440,8 +441,8 @@ class UserContextImpl implements UserContext, UserBackend } // end if // hash the password and compare it to the stored password hash - PasswordHash phash = new PasswordHash(password); - if (!(phash.equals(rs.getString("passhash")))) + String hash_value = Generator.hashPassword(password); + if (!(hash_value.equals(rs.getString("passhash")))) { // they specified an incorrect password // TODO: advance an "invalid" counter and lock the account out if more than X tries logger.warn("...invalid password"); @@ -572,7 +573,7 @@ class UserContextImpl implements UserContext, UserBackend stmt = conn.createStatement(); // generate new confirmation number - int new_confirm_num = env.getEngine().getNewConfirmationNumber(); + int new_confirm_num = Generator.get().getNewConfirmationNumber(); // create an SQL statement to reset the user account information, and execute it StringBuffer sql = new StringBuffer("UPDATE users SET email_confnum = "); @@ -684,7 +685,7 @@ class UserContextImpl implements UserContext, UserBackend logger.debug("email address changed, need to reconfirm"); // generate new confirmation number - int new_confirm_num = env.getEngine().getNewConfirmationNumber(); + int new_confirm_num = Generator.get().getNewConfirmationNumber(); Role new_role = env.getDefaultRole("Global.Unverified"); Statement stmt = null; @@ -816,9 +817,9 @@ class UserContextImpl implements UserContext, UserBackend { // retrieve a connection from the data pool conn = env.getConnection(); stmt = conn.createStatement(); - PasswordHash phash = new PasswordHash(password); + String hash_value = Generator.hashPassword(password); StringBuffer sql = new StringBuffer("UPDATE users SET passhash = '"); - sql.append(phash.toString()).append("', passreminder = '").append(SQLUtil.encodeString(reminder)); + sql.append(hash_value).append("', passreminder = '").append(SQLUtil.encodeString(reminder)); sql.append("' WHERE uid = ").append(uid).append(';'); stmt.executeUpdate(sql.toString()); @@ -1227,7 +1228,7 @@ class UserContextImpl implements UserContext, UserBackend } // end if // Generate a random authentication string and poke it into the database for this user. - String tokenauth = env.getEngine().generateRandomAuthString(); + String tokenauth = Generator.get().generateRandomAuthString(); Connection conn = null; Statement stmt = null; @@ -1314,7 +1315,7 @@ class UserContextImpl implements UserContext, UserBackend } // end if String pending_auth = token.substring(xstart,xend); - if (!(env.getEngine().isValidRandomAuthString(pending_auth))) + if (!(Generator.isValidRandomAuthString(pending_auth))) { // the auth string is not valid by the rules under which it was generated logger.error("Token parse error: invalid auth string value"); return false; @@ -1800,11 +1801,11 @@ class UserContextImpl implements UserContext, UserBackend SQLUtil.shutdown(rs); // Insert a new record for this user - PasswordHash phash = new PasswordHash(password); + String hash_value = Generator.hashPassword(password); StringBuffer sql = new StringBuffer("INSERT INTO users (username, passhash, verify_email, lockout, email_confnum, " + "base_lvl, created, lastaccess, passreminder, description) VALUES ('"); - sql.append(encode_username).append("', '").append(phash.toString()).append("', "); + sql.append(encode_username).append("', '").append(hash_value).append("', "); sql.append(verify_email ? '1' : '0').append(", ").append(lockout ? '1' : '0').append(", "); sql.append(confirm_num).append(", ").append(base_role.getLevel()).append(", '"); created = new java.util.Date(); diff --git a/src/com/silverwrist/venice/core/impl/UserProfileImpl.java b/src/com/silverwrist/venice/core/impl/UserProfileImpl.java index be11eb6..98eda80 100644 --- a/src/com/silverwrist/venice/core/impl/UserProfileImpl.java +++ b/src/com/silverwrist/venice/core/impl/UserProfileImpl.java @@ -25,6 +25,7 @@ import com.silverwrist.venice.core.*; import com.silverwrist.venice.core.internals.*; import com.silverwrist.venice.db.*; import com.silverwrist.venice.except.*; +import com.silverwrist.venice.util.MailSend; class UserProfileImpl implements UserProfile { @@ -455,21 +456,16 @@ class UserProfileImpl implements UserProfile if (is_anon) { // we can't send quick emails to the anonymous user logger.error("target user is the anonymous user"); - throw new AccessError("You cannot send email to the anonymous user."); + throw new AccessError("You cannot send E-mail to the anonymous user."); } // end if - // assemble the full text - StringBuffer text_buf = new StringBuffer(text); - text_buf.append("\n\n--\n").append(env.getEngine().getStockMessage("signature")); - // create the emailer object, fill it in, and send it - Emailer em = env.getEngine().createEmailer(); - em.setFrom(env.getUser().realUserName(),env.getUser().realEmailAddress()); - em.setTo(real_email); - em.setSubject(subject); - em.setText(text_buf.toString()); - em.send(); + MailSend msend = new PersonalMailSend(env.getMailSender(),env.getGlobalSite(),env.getUser()); + msend.addRecipient(MailSend.RECIP_TO,real_email); + msend.setSubject(subject); + msend.setText(text + "\n"); + msend.send(); } // end sendQuickEmail diff --git a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java index c332880..431ad84 100644 --- a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java +++ b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java @@ -34,6 +34,7 @@ import com.silverwrist.venice.htmlcheck.filters.*; import com.silverwrist.venice.security.*; import com.silverwrist.venice.svc.*; import com.silverwrist.venice.svc.internal.GlobalSite; +import com.silverwrist.venice.util.MailSend; import com.silverwrist.venice.util.XMLLoader; public class VeniceEngineImpl implements VeniceEngine, EngineBackend @@ -189,7 +190,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend this.uid = uid; this.username = username; this.email = email; - this.authentication = rng.nextInt(Integer.MAX_VALUE); + this.authentication = Generator.get().getAuthorizationNumber(); this.timestamp = System.currentTimeMillis(); } // end constructor @@ -242,10 +243,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend private static Category logger = Category.getInstance(VeniceEngineImpl.class); - private static final String AUTH_ALPHABET = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; - private static final int AUTH_STRING_LEN = 32; - private static final Dimension DEFAULT_DIM_USERPHOTO = new Dimension(100,100); private static final Dimension DEFAULT_DIM_COMMUNITYLOGO = new Dimension(110,65); @@ -256,10 +253,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend private GlobalSiteImpl globalsite = null; // my global site private EnvEngine env = null; // my environment - private Random rng; // random number generator - private Properties email_props = null; // email properties - private javax.mail.Session mailsession = null; // email session object - private StockMessages stock_messages = null; // stock messages holder private ObjectCache comm_objcache = new ObjectCache(new CommunityCoreDataCreator()); private ObjectCache conf_objcache = new ObjectCache(new ConferenceCoreDataCreator()); private HTMLCheckerConfig[] html_configs; // holder for HTML checker configurations @@ -282,11 +275,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend */ public VeniceEngineImpl() - { - // Initialize the random number generator. - java.util.Date seed_date = new java.util.Date(); - rng = new Random(seed_date.getTime()); - + { // do nothing } // end constructor /*-------------------------------------------------------------------------------- @@ -595,18 +584,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end for - // Get the section. - sect = loader.configGetSubSection(root_h,"email"); - sect_h = new DOMElementHelper(sect); - - // initialize the email properties and get a mail session object - email_props = new Properties(); - email_props.put("mail.transport.protocol","smtp"); - email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host")); - email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr")); - email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer")); - mailsession = javax.mail.Session.getInstance(email_props,null); - // Get the section. sect = loader.configGetSubSection(root_h,"dictionary"); @@ -639,12 +616,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end if // else no list, just proceed - // Get the section. - sect = loader.configGetSubSection(root_h,"messages"); - - // Initialize the stock messages list. - stock_messages = new StockMessages(sect); - // Now done with the master config... // Load the sidebox configuration file. Document subdoc = loader.loadConfigDocument(sidebox_config); @@ -927,7 +898,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend password_changes.put(new Integer(pcr.getUID()),pcr); // Create the message to be sent. - String message = getStockMessage("reminder"); + String message = globalsite.getStockMessage("reminder"); if (message==null) { // what? the message does not exist? logger.error("\"reminder\" message does not exist in config file!"); @@ -944,16 +915,16 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend message = StringUtil.replaceAllVariables(message,vars); // Find the message subject. - String subject = getStockMessage("reminder-subject"); + String subject = globalsite.getStockMessage("reminder-subject"); if (subject==null) subject = "Venice Password Reminder Message"; - // Create the emailer and send the message. - Emailer emailer = createEmailer(); - emailer.setTo(email_addr); - emailer.setSubject(subject); - emailer.setText(message); - emailer.send(); + // Create the mail sender and send the message. + MailSend msend = (MailSend)(globalsite.queryService(MailSend.class)); + msend.addRecipient(MailSend.RECIP_TO,email_addr); + msend.setSubject(subject); + msend.setText(message); + msend.send(); if (logger.isDebugEnabled()) logger.debug("...email sent"); @@ -997,8 +968,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend logger.debug("completePasswordChange for user \"" + pcr.getUserName() + "\""); // Request is valid; synthesize a new password - PasswordGenerator pgen = new PasswordGenerator(); - PasswordHash phash = new PasswordHash(pgen.toString()); + String new_password = Generator.get().generateRandomPassword(); + String hash_value = Generator.hashPassword(new_password); Connection conn = null; Statement stmt = null; try @@ -1006,7 +977,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend conn = env.getConnection(); stmt = conn.createStatement(); StringBuffer sql = new StringBuffer("UPDATE users SET passhash = '"); - sql.append(phash.toString()).append("' WHERE uid = ").append(uid).append(';'); + sql.append(hash_value).append("' WHERE uid = ").append(uid).append(';'); stmt.executeUpdate(sql.toString()); } // end try @@ -1024,7 +995,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end finally // Create the message to be sent. - String message = getStockMessage("password-change"); + String message = globalsite.getStockMessage("password-change"); if (message==null) { // what? the message does not exist? logger.error("\"password-change\" message does not exist in config file!"); @@ -1035,20 +1006,20 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend // Replace the message variables. HashMap vars = new HashMap(2); vars.put("username",pcr.getUserName()); - vars.put("password",pgen.toString()); + vars.put("password",new_password); message = StringUtil.replaceAllVariables(message,vars); // Find the message subject. - String subject = getStockMessage("password-change-subject"); + String subject = globalsite.getStockMessage("password-change-subject"); if (subject==null) subject = "Venice Password Changed"; - // Create the emailer and send the message. - Emailer emailer = createEmailer(); - emailer.setTo(pcr.getEmail()); - emailer.setSubject(subject); - emailer.setText(message); - emailer.send(); + // Create the mail sender and send the message. + MailSend msend = (MailSend)(globalsite.queryService(MailSend.class)); + msend.addRecipient(MailSend.RECIP_TO,pcr.getEmail()); + msend.setSubject(subject); + msend.setText(message); + msend.send(); if (logger.isDebugEnabled()) logger.debug("...email sent"); @@ -1060,7 +1031,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend checkInitialized(); Role new_role = global_security.getDefaultRole("Global.NewUser"); // email confirmation # is between 1000000 and 9999999 - int confirm_num = getNewConfirmationNumber(); + int confirm_num = Generator.get().getNewConfirmationNumber(); if (logger.isDebugEnabled()) logger.debug("createNewAccount(\"" + username + "\",,)..."); @@ -1541,27 +1512,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end getSelf - public Emailer createEmailer() - { - checkInitialized(); - return new SimpleEmailer(email_props,mailsession); - - } // end createEmailer - - public String getStockMessage(String key) - { - checkInitialized(); - return (String)(stock_messages.get(key)); - - } // end getStockMessage - - public int getNewConfirmationNumber() - { - checkInitialized(); - return rng.nextInt(9000000) + 1000000; - - } // end getNewConfirmationNumber - public CommunityData getCommunityDataObject(int cid) throws DataException { checkInitialized(); @@ -1749,30 +1699,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end unpublish - public String generateRandomAuthString() - { - StringBuffer buf = new StringBuffer(AUTH_STRING_LEN); - for (int i=0; i. + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.internals; + +import java.util.*; +import javax.mail.*; +import javax.mail.internet.*; +import com.silverwrist.util.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.svc.internal.GlobalSite; +import com.silverwrist.venice.util.MailSend; + +class BaseMailSend implements MailSend +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final InternetAddress[] ADDR_TEMPLATE = new InternetAddress[0]; + private static final Message.RecipientType[] TYPE_VALS = + { Message.RecipientType.TO, Message.RecipientType.CC, Message.RecipientType.BCC }; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private GlobalSite site; // the global site + private Session session; // the email session + private MimeMessage msg; // the message being composed + private ArrayList[] recips; // lists of recipients + private String subject = null; // subject string + private String text = null; // text string + private HashMap variables = null; // substitution variables for subject and text + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + BaseMailSend(GlobalSite site, Properties props, javax.mail.Session session) + { + this.site = site; + this.session = session; + msg = new MimeMessage(session); + try + { // set the X-Mailer header + msg.setHeader("X-Mailer",(String)(props.get("com.silverwrist.venice.email.mailer"))); + + } // end try + catch (Exception e) + { // do nothing - we don't really care about this too much + } // end catch + + try + { // set the From address on the message + msg.setFrom(InternetAddress.getLocalAddress(session)); + + } // end try + catch (MessagingException me) + { // this should be impossible + throw new InternalStateError("condition should not apply to message here",me); + + } // end catch + + recips = new ArrayList[3]; + recips[0] = recips[1] = recips[2] = null; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface MailSend + *-------------------------------------------------------------------------------- + */ + + public void addRecipient(int type, String addr) throws EmailException + { + if ((type<0) || (type>=recips.length)) + throw new IndexOutOfBoundsException("invalid recipient type"); + + try + { // create an Internet address and set the recipient to it + InternetAddress address = new InternetAddress(addr); + if (recips[type]==null) + recips[type] = new ArrayList(); + recips[type].add(address); + + } // end try + catch (AddressException e1) + { // the address was somehow invalid + throw new EmailException("invalid email recipient address",e1); + + } // end catch + + } // end addRecipient + + public void removeRecipient(int type, String addr) throws EmailException + { + if ((type<0) || (type>=recips.length)) + throw new IndexOutOfBoundsException("invalid recipient type"); + + if (recips[type]==null) + return; // nothing there + + for (int i=0; i=recips.length)) + throw new IndexOutOfBoundsException("invalid recipient type"); + + if (recips[type]!=null) + recips[type].clear(); + + } // end clearRecipients + + public void setFrom(String from_name, String from_addr) throws EmailException + { + try + { // set the "from" address + InternetAddress addr = new InternetAddress(from_addr); + addr.setPersonal(from_name); + msg.setFrom(addr); + + // make sure the "Sender" address reflects our email address + InternetAddress sender = InternetAddress.getLocalAddress(session); + msg.setHeader("Sender",sender.toString()); + + } // end try + catch (AddressException e1) + { // the address was somehow invalid + throw new EmailException("invalid email sender address",e1); + + } // end catch + catch (MessagingException e2) + { // msg.setRecipients should NOT be throwing a MessageException here! + throw new InternalStateError("condition should not apply to message here",e2); + + } // end catch + catch (java.io.UnsupportedEncodingException e3) + { // we can't really have that happen here, either! + throw new InternalStateError("condition should not apply to message here",e3); + + } // end catch + + } // end setFrom + + public void setSubject(String subject) + { + this.subject = subject; + + } // end setSubject + + public void setStockSubject(String identifier) + { + this.subject = site.getStockMessage(identifier); + + } // end setStockSubject + + public void setText(String text) + { + this.text = text; + + } // end setStockText + + public void setStockText(String identifier) + { + this.text = site.getStockMessage(identifier); + + } // end setStockText + + public void setVariable(String name, String value) + { + if (variables==null) + variables = new HashMap(); + if (value==null) + variables.remove(name); + else + variables.put(name,value); + + } // end setVariable + + public void addHeader(String name, String value) + { + try + { // pass through + msg.addHeader(name,value); + + } // end try + catch (MessagingException me) + { // this should be impossible + throw new InternalStateError("condition should not apply to message here",me); + + } // end catch + + } // end addHeader + + public void removeHeader(String name) + { + try + { // pass through + msg.removeHeader(name); + + } // end try + catch (MessagingException me) + { // this should be impossible + throw new InternalStateError("condition should not apply to message here",me); + + } // end catch + + } // end removeHeader + + public void send() throws EmailException + { + try + { // set the recipient addresses + for (int i=0; i section. + sect = loader.configGetSubSection(config_h,"email"); + DOMElementHelper sect_h = new DOMElementHelper(sect); + + // initialize the email properties and get a mail session object + email_props = new Properties(); + email_props.put("mail.transport.protocol","smtp"); + email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host")); + email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr")); + email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer")); + mailsession = javax.mail.Session.getInstance(email_props,null); + + // Get the section. + sect = loader.configGetSubSection(config_h,"messages"); + + // Initialize the stock messages list. + stock_messages = new StockMessages(sect); + } // end class GlobalSiteImpl /*-------------------------------------------------------------------------------- @@ -81,6 +104,8 @@ public class GlobalSiteImpl implements GlobalSite { if (klass==DataPool.class) return datapool; + if (klass==MailSend.class) + return new BaseMailSend(this,email_props,mailsession); throw new NoSuchServiceException("GlobalSite",klass); } // end queryService @@ -103,6 +128,12 @@ public class GlobalSiteImpl implements GlobalSite } // end getConnection + public String getStockMessage(String key) + { + return stock_messages.get(key); + + } // end getStockMessage + /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/security/Generator.java b/src/com/silverwrist/venice/security/Generator.java new file mode 100644 index 0000000..5c21635 --- /dev/null +++ b/src/com/silverwrist/venice/security/Generator.java @@ -0,0 +1,210 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.security; + +import java.security.MessageDigest; +import java.util.*; + +public class Generator +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + public static final int CONFIRM_MIN = 1000000; + public static final int CONFIRM_MAX = 9999999; + + private static final String AUTH_ALPHABET = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; + private static final int AUTH_STRING_LEN = 32; + + private static final String[] syllabary = { + "ba", "be", "bi", "bo", "bu", + "da", "de", "di", "do", "du", + "cha", "chi", "cho", "chu", + "fa", "fe", "fi", "fo", "fu", + "ga", "ge", "gi", "go", "gu", + "ha", "he", "hi", "ho", "hu", + "ja", "je", "ji", "jo", "ju", + "ka", "ke", "ki", "ko", "ku", + "la", "le", "li", "lo", "lu", + "ma", "me", "mi", "mo", "mu", + "na", "ne", "ni", "no", "nu", + "pa", "pe", "pi", "po", "pu", + "ra", "re", "ri", "ro", "ru", + "sa", "se", "si", "so", "su", + "sha", "she", "sho", "shu", + "ta", "te", "ti", "to", "tu", + "va", "ve", "vi", "vo", "vu", + "wa", "we", "wi", "wo", "wu", + "ya", "ye", "yi", "yo", "yu", + "za", "ze", "zi", "zo", "zu" + }; // 98 syllables + + private static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + + private static Generator self = null; // my own personal instance + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Random rng; // my random number generator + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + private Generator() + { + // Initialize the random number generator. + java.util.Date seed_date = new java.util.Date(); + rng = new Random(seed_date.getTime()); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public final String generateRandomAuthString() + { + StringBuffer buf = new StringBuffer(AUTH_STRING_LEN); + for (int i=0; i0)) + { // hash the password and save the hash value + MessageDigest hasher; + + try + { // get a hasher implementing the Secure Hashing Algorithm + hasher = MessageDigest.getInstance("SHA"); + + } // end try + catch (java.security.NoSuchAlgorithmException e) + { // SHA should be a standard algorithm...if it isn't, we're h0sed + throw new RuntimeException("HOSED JRE - SHA should be a standard algorithm"); + + } // end catch + + try + { // update the hasher with the UTF-8 bytes of the password + hasher.update(password.getBytes("UTF8")); + + } // end try + catch (java.io.UnsupportedEncodingException e) + { // WTF? How can the JRE NOT know about UTF-8? HOW?!? + throw new RuntimeException("HOSED JRE - UTF-8 encoding should be supported"); + + } // end catch + + // Retrieve the raw hash value (should be 160 bits, or 20 bytes) + byte[] raw_hash = hasher.digest(); + + // Convert the hash value to a hexadecimal string (40 chars in length) + StringBuffer hash_buf = new StringBuffer(raw_hash.length * 2); + StringBuffer tmp_buf = new StringBuffer(); + String tmp; + for (int i=0; i. - * - * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT - * WARRANTY OF ANY KIND, either express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Original Code is the Venice Web Communities System. - * - * The Initial Developer of the Original Code is Eric J. Bowersox , - * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. - * - * Contributor(s): - */ -package com.silverwrist.venice.security; - -import java.util.Random; - -public class PasswordGenerator -{ - /*-------------------------------------------------------------------------------- - * Static data members - *-------------------------------------------------------------------------------- - */ - - private static final String[] syllabary = { - "ba", "be", "bi", "bo", "bu", - "da", "de", "di", "do", "du", - "cha", "chi", "cho", "chu", - "fa", "fe", "fi", "fo", "fu", - "ga", "ge", "gi", "go", "gu", - "ha", "he", "hi", "ho", "hu", - "ja", "je", "ji", "jo", "ju", - "ka", "ke", "ki", "ko", "ku", - "la", "le", "li", "lo", "lu", - "ma", "me", "mi", "mo", "mu", - "na", "ne", "ni", "no", "nu", - "pa", "pe", "pi", "po", "pu", - "ra", "re", "ri", "ro", "ru", - "sa", "se", "si", "so", "su", - "sha", "she", "sho", "shu", - "ta", "te", "ti", "to", "tu", - "va", "ve", "vi", "vo", "vu", - "wa", "we", "wi", "wo", "wu", - "ya", "ye", "yi", "yo", "yu", - "za", "ze", "zi", "zo", "zu" - }; // 98 syllables - - private static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - - /*-------------------------------------------------------------------------------- - * Attributes - *-------------------------------------------------------------------------------- - */ - - private String value; // the password value - - /*-------------------------------------------------------------------------------- - * Constructor - *-------------------------------------------------------------------------------- - */ - - public PasswordGenerator() - { - Random rng = new Random(); - StringBuffer buf = new StringBuffer(); - int i; - for (i=0; i<4; i++) // 4 random syllables - buf.append(syllabary[rng.nextInt(syllabary.length)]); - for (i=0; i<3; i++) // 3 random digits - buf.append(digits[rng.nextInt(digits.length)]); - value = buf.toString(); - // total possible number of passwords = 92,236,816,000 - - } // end constructor - - /*-------------------------------------------------------------------------------- - * Overrides from class Object - *-------------------------------------------------------------------------------- - */ - - public String toString() - { - return value; - - } // end toString - - public boolean equals(Object obj) - { - if (obj==null) - return false; // trivial case - else if (obj==(Object)this) - return true; // trivial case - if (obj instanceof PasswordGenerator) - { // compare value of PasswordHash argument to value - PasswordGenerator other = (PasswordGenerator)obj; - return value.equals(other.value); - - } // end if - else - return value.equals(obj.toString()); - - } // end equals - - public int hashCode() - { - return value.hashCode(); - - } // end hashCode - -} // end class PasswordGenerator diff --git a/src/com/silverwrist/venice/security/PasswordHash.java b/src/com/silverwrist/venice/security/PasswordHash.java deleted file mode 100644 index 32bc80e..0000000 --- a/src/com/silverwrist/venice/security/PasswordHash.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public License Version 1.1 - * (the "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at . - * - * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT - * WARRANTY OF ANY KIND, either express or implied. See the License for the specific - * language governing rights and limitations under the License. - * - * The Original Code is the Venice Web Communities System. - * - * The Initial Developer of the Original Code is Eric J. Bowersox , - * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. - * - * Contributor(s): - */ -package com.silverwrist.venice.security; - -import java.security.MessageDigest; - -public class PasswordHash -{ - /*-------------------------------------------------------------------------------- - * Attributes - *-------------------------------------------------------------------------------- - */ - - private String value; // the hashed password value - - /*-------------------------------------------------------------------------------- - * Constructors - *-------------------------------------------------------------------------------- - */ - - public PasswordHash() - { - value = ""; - - } // end constructor - - public PasswordHash(String password) - { - if ((password!=null) && (password.length()>0)) - { // hash the password and save the hash value - MessageDigest hasher; - - try - { // get a hasher implementing the Secure Hashing Algorithm - hasher = MessageDigest.getInstance("SHA"); - - } // end try - catch (java.security.NoSuchAlgorithmException e) - { // SHA should be a standard algorithm...if it isn't, we're h0sed - throw new RuntimeException("HOSED JRE - SHA should be a standard algorithm"); - - } // end catch - - try - { // update the hasher with the UTF-8 bytes of the password - hasher.update(password.getBytes("UTF8")); - - } // end try - catch (java.io.UnsupportedEncodingException e) - { // WTF? How can the JRE NOT know about UTF-8? HOW?!? - throw new RuntimeException("HOSED JRE - UTF-8 encoding should be supported"); - - } // end catch - - // Retrieve the raw hash value (should be 160 bits, or 20 bytes) - byte[] raw_hash = hasher.digest(); - - // Convert the hash value to a hexadecimal string (40 chars in length) - StringBuffer hash_buf = new StringBuffer(raw_hash.length * 2); - StringBuffer tmp_buf = new StringBuffer(); - String tmp; - for (int i=0; i, * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ -package com.silverwrist.venice.core.internals; +package com.silverwrist.venice.util; import com.silverwrist.venice.except.EmailException; -public interface Emailer +public interface MailSend { - public abstract void setTo(String to) throws EmailException; + public static final int RECIP_TO = 0; + public static final int RECIP_CC = 1; + public static final int RECIP_BCC = 2; + + public abstract void addRecipient(int type, String addr) throws EmailException; + + public abstract void removeRecipient(int type, String addr) throws EmailException; + + public abstract void clearRecipients(int type); public abstract void setFrom(String from_name, String from_addr) throws EmailException; public abstract void setSubject(String subject); + public abstract void setStockSubject(String identifier); + public abstract void setText(String text); + public abstract void setStockText(String identifier); + + public abstract void setVariable(String name, String value); + + public abstract void addHeader(String name, String value); + + public abstract void removeHeader(String name); + public abstract void send() throws EmailException; -} // end interface Emailer +} // end interface MailSend