Skip to content

Commit

Permalink
Item12180: Email upgrade (mostly). This is still WIP, so expect rough…
Browse files Browse the repository at this point in the history
… edges.

git-svn-id: http://svn.foswiki.org/trunk@16160 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
TimotheLitt authored and TimotheLitt committed Dec 6, 2012
1 parent 9a248a5 commit 1ea62ba
Show file tree
Hide file tree
Showing 19 changed files with 1,689 additions and 212 deletions.
102 changes: 79 additions & 23 deletions core/lib/Foswiki.spec
Original file line number Diff line number Diff line change
Expand Up @@ -1696,9 +1696,15 @@ $Foswiki::cfg{Cache}{DBI}{PostgreSQL}{Password} = '';
#---++ Email general
# <p>Settings controlling if and how Foswiki handles email including the identity of the sender
# and other expert settings controlling the email process.</p>
# **BOOLEAN**
# **BOOLEAN \
# FEEDBACK='Auto-configure';\
# wait="Contacting your e-mail server, this may take several minutes...";\
# title="Attempts to automatically configure e-mail by scanning your system and contacting your mail server" \
# CHECK="prefer:perl" \
# **
# Enable email globally. Un-check this option to disable all outgoing
# email from Foswiki
# email from Foswiki. Use the action button to auto-configure e-mail service.
#
$Foswiki::cfg{EnableEmail} = $TRUE;
# **EMAILADDRESS FEEDBACK=AUTO FEEDBACK="Send Test Email" 30**
Expand All @@ -1707,9 +1713,31 @@ $Foswiki::cfg{EnableEmail} = $TRUE;
# NOTE: must be a single valid email address
$Foswiki::cfg{WebMasterEmail} = '';
# **STRING 30**
# **STRING FEEDBACK=AUTO \
# FEEDBACK="Generate S/MIME Certificate";\
# title="Generate a self-signed certficate for the WebMaster.\
# This allows immediate use of signed email." \
# CHECK="expires:1y passlen:15,35 O:'Foswiki Customers' OU:'Self-signed certificates' \
# #!C:US ST:'Mass Bay' L:'Greater Boston' \
# " \
# FEEDBACK="Generate S/MIME CSR";\
# title="Generate a Certificate Signing Request for the WebMaster.\
# This request must be signed by a Certificate Authority to create \
# a certificate, then installed." \
# FEEDBACK="Cancel CSR";\
# title="Cancel a pending Certificate Signing request. This destroys the private \
# key associated with the request." \
# 30**
# Wiki administrator's name address, for use in mails (first name and
# last name, e.g. <tt>Fred Smith</tt>) (used in %WIKIWEBMASTERNAME%)
#<p> The action button will generate a self-signed S/MIME certificate and install it
# for Foswiki e-mail. If you use this option, you will have to arrange for your
# users' e-mail clients to trust this certificate, or upgrade to a certificate
# issued by a Certificate Authority that you trust. This type of certificate
# is adequate for a small user base and for testing, but a certificate issued
# by your Certificate Authority or by a trusted commercial Certificate authority
# is prefered for production in most cases. Use the Generate CSR button to create
# a private key and signing request for this.
$Foswiki::cfg{WebMasterName} = 'Wiki Administrator';

# **BOOLEAN EXPERT**
Expand Down Expand Up @@ -1740,17 +1768,18 @@ qr(AERO|ARPA|ASIA|BIZ|CAT|COM|COOP|EDU|GOV|INFO|INT|JOBS|MIL|MOBI|MUSEUM|NAME|NE
#---++ Email server
# <p>Settings to select the destination mail server or local email agent used for forwarding email.</p>

# **SELECT Net::SMTP,Net::SMTP::SSL,MailProgram **
# **SELECT Net::SMTP,\
# Net::SMTP (SSL),\
# Net::SMTP (TLS),\
# Net::SMTP (STARTTLS),\
# MailProgram **
# Select the method Foswiki will use for sending email. On Unix/Linux hosts
# "MailProgram" is generally acceptable. Otherwise choose one of the Email
# methods required by your ISP or Email server.
# <ul><li><code>Net::SMTP</code> sends in cleartext.
# <li><code>Net::SMTP::SSL</code> sends using a secure encrypted connection.
# </ul>Both of the above methods will perform authentication if a Username and
# password are provided below.
# <ul><li><code>MailProgram</code> uses the program configured below to send email.
# Authentication and encryption is done externally to Foswiki and the remainder of
# the below fields are not used.
# You can select a method manually, or use the "Auto-configure" button to
# determine the best connection type for your ISP or Email server.
# Auto-configure requires {SMTP}{MAILHOST}, but you can leave everything else
# blank. You'll be told if the server requires a username and password.
#$Foswiki::cfg{Email}{MailMethod} = 'Net::SMTP';

# **COMMAND DISPLAY_IF {Email}{MailMethod} == 'MailProgram'**
Expand All @@ -1763,7 +1792,8 @@ $Foswiki::cfg{MailProgram} = '/usr/sbin/sendmail -t -oi -oeq';
# mode in SMTP. Output will go to the webserver error log.
$Foswiki::cfg{SMTP}{Debug} = 0;

# **STRING 30 EXPERT DISPLAY_IF {SMTP}{Debug} && {Email}{MailMethod} == 'MailProgram'**
# **STRING 30 EXPERT \
# DISPLAY_IF {SMTP}{Debug} && {Email}{MailMethod} == 'MailProgram'**
# These flags are passed to the mail program selected by {MailProgram}
# when {SMTP}{Debug} is enabled in addition to any specified with
# the program. These flags should enable tracing of the SMTP
Expand All @@ -1777,20 +1807,21 @@ $Foswiki::cfg{SMTP}{Debug} = 0;

$Foswiki::cfg{SMTP}{DebugFlags} = '-X /dev/stderr';

# **STRING 30 DISPLAY_IF /Net::SMTP/.test({Email}{MailMethod})**
# **STRING 30 FEEDBACK=AUTO \
# DISPLAY_IF /Net::SMTP/.test({Email}{MailMethod})**
# Mail host for outgoing mail. This is only used if Net::SMTP is used.
# Examples: <tt>mail.your.company</tt> If the smtp server uses a different port
# than the default 25 # use the syntax <tt>mail.your.company:portnumber</tt>
# <p><b>CAUTION</b> This setting can be overridden by a setting of SMTPMAILHOST
# in SitePreferences. Make sure you delete that setting if you are using a
# SitePreferences topic from a previous release of Foswiki.</p>
# <p>For Gmail, set MailMethod to Net::SMTP::SSL, set MAILHOST to <tt>smtp.gmail.com:465</tt>
# and provide your gmail email address and password below for authentication.</p>
# <p>For Gmail, set MailMethod to Net::SMTP, set MAILHOST to <tt>smtp.gmail.com</tt>
# provide your gmail email address and password below for authentication, and click <strong>Auto-configure</strong>.</p>
$Foswiki::cfg{SMTP}{MAILHOST} = '';

# **STRING 30 DISPLAY_IF /Net::SMTP/.test({Email}{MailMethod})**
# Mail domain sending mail, required. SMTP
# requires that you identify the server sending mail. If not set,
# requires that you identify the server sending mail. If not set, <b>Auto-configure</b> or
# <tt>Net::SMTP</tt> will guess it for you. Example: foswiki.your.company.
# <b>CAUTION</b> This setting can be overridden by a setting of %SMTPSENDERHOST%
# in SitePreferences. Make sure you delete that setting.
Expand Down Expand Up @@ -1819,13 +1850,13 @@ $Foswiki::cfg{Email}{EnableSMIME} = $FALSE;
# must be in PEM format. <p>
# If your issuer requires an intermediate CA certificate(s), include them in this
# file after the sender's certificate in order from least to most authoritative CA.
$Foswiki::cfg{Email}{SmimeCertificateFile} = '$Foswiki::cfg{DataDir}/cert.pem';
$Foswiki::cfg{Email}{SmimeCertificateFile} = '$Foswiki::cfg{DataDir}/SmimeCertificate.pem';

# **PATH FEEDBACK=auto DISPLAY_IF {Email}{EnableSMIME}**
# Specify the file containing the private key corresponding to the administrator's X.509 certificate.
# It must be in PEM format. <p><em>Be sure that this file is only readable by the
# Foswiki software; it must NOT be readable by users!</em>
$Foswiki::cfg{Email}{SmimeKeyFile} = '$Foswiki::cfg{DataDir}/key.pem';
$Foswiki::cfg{Email}{SmimeKeyFile} = '$Foswiki::cfg{DataDir}/SmimePrivateKey.pem';

# **PASSWORD 30 FEEDBACK=auto DISPLAY_IF {Email}{EnableSMIME}**
# If the file containing the certificate's private key is encrypted, specify the password.
Expand All @@ -1835,11 +1866,36 @@ $Foswiki::cfg{Email}{SmimeKeyFile} = '$Foswiki::cfg{DataDir}/key.pem';
# <i>openssl rsa -in keyfile.pem -out keyfile.pem -des3</i>
$Foswiki::cfg{Email}{SmimeKeyPassword} = '';

#---++ Email test
# IMPORTANT: Verify your configuration before enabling email or testing user
# registration, before attempting to register any users to Foswiki.
# *TESTEMAIL* Marker used by bin/configure script - do not remove!
#---+++ Certificate Management
# The following paramenters can be used to specify commonly used components of the subject
# name for Certificate Signing Requests.<p>
# You can also install a signed certificate with the action button.
# **STRING LABEL="Country Code"**
# ISO country code (2 letters)
$Foswiki::cfg{Email}{SmimeCertC} = '';

# **STRING LABEL="State or Province"**
# State or Province
$Foswiki::cfg{Email}{SmimeCertST} = '';

# **STRING LABEL="Locality"**
# Locality (city or town)
$Foswiki::cfg{Email}{SmimeCertL} = '';

# **STRING LABEL="Organization"**
# Organization - Required
$Foswiki::cfg{Email}{SmimeCertO} = '';

# **STRING LABEL="Organizational Unit"**
# Organizational unit (e.g. Department) - Required
$Foswiki::cfg{Email}{SmimeCertOU} = '';

# **STRING 70x10 \
# FEEDBACK="Display CSR" NOLABEL \
# title="Display pending Certificate Signing Request" \
# FEEDBACK="Install Certificate" NOLABEL \
# title="Install a signed certificate" **
$Foswiki::cfg{ConfigureGUI}{SMIME}{InstallCert} = '';

#---+ Miscellaneous -- EXPERT
# <p>Miscellaneous expert options.</p>
Expand Down
57 changes: 29 additions & 28 deletions core/lib/Foswiki/Configure/Checker.pm
Original file line number Diff line number Diff line change
Expand Up @@ -69,35 +69,36 @@ sub parseOptions {

return () unless ($optionList);

my @options;

foreach my $optionString (@$optionList) {
push @options, {
map {
my @option = split( /:/, $_, 2 );
if ( @option && $option[0] ) {
my ( $name, $value ) = @option;
if ( @option == 1 ) {
$value = [1];
}
elsif ( $value =~ /^(['"])((?:\\.|[^\1])+)\1$/ ) {
$value = $2;
$value =~ s/\\(.)/$1/g;
$value = [$value];
}
else {
$value = [ split( /,\s*/, $value ) ];
}
@option = ( $name => $value );
}
else {
@option = ();
}
@option
} split( /\s+/, $optionString )
};
my @optionList;

foreach my $optionStr (@$optionList) {
my $optionString = $optionStr;
my @options;
while ( length $optionString ) {
next if ( $optionString =~ s/^\s+// );
$optionString =~ s/^(\w+)//ms
or die "Expected name in CHECK "
. $this->{item}->getKeys()
. " at $optionString\n";
my $name = $1;
unless ( $optionString =~ s/^:\s*// ) {
push @options, $name => [1];
next;
}
if ( $optionString =~
s/^((?:(?:"(?:\\.|[^"])*")|(?:'(?:\\.|[^'])*')))//ms )
{ #
my $value = $1;
$value =~ s/\\(.)/$1/g;
push @options, $name => [$value];
next;
}
( my $list, $optionString ) = split( /\s+/, $optionString, 2 );
push @options, $name => [ split( ',', $list ) ];
}
push @optionList, {@options};
}
return @options;
return @optionList;
}

=begin TML
Expand Down
55 changes: 41 additions & 14 deletions core/lib/Foswiki/Configure/Checkers/Certificate.pm
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Validates a Certificate item for the configure GUI
* =$usage= - Required use (email, client, server, clientserver)
Returns empty string if OK, error string with any errors
Optionally returns list of subjects.
=cut

Expand All @@ -97,46 +98,70 @@ sub checkUsage {
my $valobj = shift;
my $usage = shift;

my $keys = $valobj->getKeys() or die "No keys for value";
my $keys = ( ref($valobj) ? $valobj->getKeys() : $valobj )
or die "No keys for value";
my $value = eval "\$Foswiki::cfg$keys";
return $this->ERROR("Can't evaluate current value of $keys: $@") if ($@);
my $e = '';
if ($@) {
$e = $this->ERROR("Can't evaluate current value of $keys: $@");
return ( $e, ) if (wantarray);
return $e;
}

# The default value may not have been available when the other defaulting is done.

unless ( defined $value ) {
$value = eval "\$Foswiki::defaultCfg->$keys";
return $this->ERROR("Can't evaluate default value of $keys: $@")
if ($@);
if ($@) {
$e = $this->ERROR("Can't evaluate default value of $keys: $@");
return ( $e, ) if (wantarray);
return $e;
}
$value = "***UNDEF***" unless defined $value;
}

# Expand any references to other variables

Foswiki::Configure::Load::expandValue($value);

return '' unless ( defined $value && length $value );
unless ( defined $value && length $value ) {
return ( '', ) if (wantarray);
return '';
}
my $xpv = "<b>Note:</b> $value";
my $xpn = $this->NOTE($xpv);

my ( $errors, @certs ) = loadCert($value);

return $xpn . $this->ERROR( "No certificate in file: " . $certs[0] )
if ($errors);

( ( stat $value )[2] || 0 ) & 002
and return $xpn . $this->ERROR("File permissions allow world write");
if ($errors) {
$e = $xpn . $this->ERROR( "No certificate in file: " . $certs[0] );
}
else {
( ( stat $value )[2] || 0 ) & 002
and $e = $xpn . $this->ERROR("File permissions allow world write");
}
if ($e) {
return ( $e, ) if (wantarray);
return $e;
}

eval { require Crypt::X509; };
if ($@) {
return $xpn
$e =
$xpn
. $this->WARN(
"Unable to verify certificate: Please install Crypt::X509 from CPAN"
);
return ( $e, ) if (wantarray);
return $e;
}

my $x = Crypt::X509->new( cert => shift @certs );
return $xpn . $this->ERROR( "Invalid certificate: " . $x->error )
if ( $x->error );
if ( $x->error ) {
$e = $xpn . $this->ERROR( "Invalid certificate: " . $x->error );
return ( $e, ) if (wantarray);
return $e;
}

my $sts = '';
my $warnings = '';
Expand Down Expand Up @@ -169,7 +194,8 @@ Issued by %s for %s", $xpv, ( $x->issuer_cn || 'Unknown issuer' ),
}
}
if (@ans) {
$notes .= ": " . join( ', ', dedup( $hostnames, @ans ) );
@ans = dedup( $hostnames, @ans );
$notes .= ": " . join( ', ', @ans );
}
$notes .= "<br />";

Expand Down Expand Up @@ -290,6 +316,7 @@ Issued by %s for %s<br />", ( $x->issuer_cn || 'Unknown issuer' ),
( $notes, $warnings, $errors ) = ('') x 3;
}
}
return ( $sts, @ans ) if (wantarray);
return $sts;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ sub check {
my $valobj = shift;
my $passkey = shift;

my $keys = $valobj->getKeys() or die "No keys for value";
my $keys = ( ref($valobj) ? $valobj->getKeys() : $valobj )
or die "No keys for value";
my $value = eval "\$Foswiki::cfg$keys";
return $this->ERROR("Can't evaluate current value of $keys: $@") if ($@);

Expand Down
Loading

0 comments on commit 1ea62ba

Please sign in to comment.