--- a/.hgignore Thu Nov 17 14:30:44 2011 +0100
+++ b/.hgignore Thu Nov 17 14:43:16 2011 +0100
@@ -16,5 +16,7 @@
sbt-launch*.jar
.scala_dependencies
*.orig
+.cache
+.settings
.idea
.idea_modules
--- a/project/build.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/project/build.scala Thu Nov 17 14:43:16 2011 +0100
@@ -23,8 +23,7 @@
val jena = "com.hp.hpl.jena" % "jena" % "2.6.4"
val arq = "com.hp.hpl.jena" % "arq" % "2.8.8"
val grizzled = "org.clapper" %% "grizzled-scala" % "1.0.8" % "test"
- val scalaz = "org.scalaz" %% "scalaz-core" % "6.0.2"
-
+ val scalaz = "org.scalaz" %% "scalaz-core" % "6.0.3"
val argot = "org.clapper" %% "argot" % "0.3.5"
val guava = "com.google.guava" % "guava" % "10.0.1"
// val restlet = "org.restlet.dev" % "org.restlet" % "2.1-SNAPSHOT"
--- a/project/plugins/build.sbt Thu Nov 17 14:30:44 2011 +0100
+++ b/project/plugins/build.sbt Thu Nov 17 14:43:16 2011 +0100
@@ -8,3 +8,6 @@
addSbtPlugin("com.github.siasia" % "xsbt-proguard-plugin" % "0.1")
+resolvers += "sbt-idea-repo" at "http://mpeltonen.github.com/maven/"
+
+addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "0.11.0")
\ No newline at end of file
--- a/src/main/scala/Filesystem.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/Filesystem.scala Thu Nov 17 14:43:16 2011 +0100
@@ -1,16 +1,16 @@
package org.w3.readwriteweb
-import org.w3.readwriteweb.util._
-
import java.io._
import java.net.URL
import org.slf4j.{Logger, LoggerFactory}
-import com.hp.hpl.jena.rdf.model.{Resource=>JResource,_}
+import com.hp.hpl.jena.rdf.model.{Resource => _, _}
import com.hp.hpl.jena.shared.JenaException
-import scalaz.{Resource => SzResource, sys => _, _}
+import scalaz.{Resource => _, _}
import Scalaz._
+import scala.sys
+
class Filesystem(
baseDirectory: File,
val basePath: String,
--- a/src/main/scala/HttpsTrustAll.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/HttpsTrustAll.scala Thu Nov 17 14:43:16 2011 +0100
@@ -29,7 +29,9 @@
import org.jsslutils.sslcontext.trustmanagers.TrustAllClientsWrappingTrustManager
import org.jsslutils.sslcontext.{X509TrustManagerWrapper, X509SSLContextFactory}
import sys.SystemProperties
+import scala.util.Properties.{propOrNone => getProperty, javaHome}
import unfiltered.jetty.{Ssl, Https}
+import unfiltered.jetty.Server
/**
@@ -37,7 +39,10 @@
* @created: 12/10/2011
*/
-case class HttpsTrustAll(override val port: Int, override val host: String) extends Https(port, host) with TrustAll
+class HttpsTrustAll(
+ override val port: Int,
+ override val host: String)
+extends Https(port, host) with TrustAll
/**
@@ -55,36 +60,45 @@
* the user experience would be very bad, since TLS does not give many options for explaining what the problem
* is.
*/
-trait TrustAll { self: Ssl =>
- import scala.sys.SystemProperties._
+trait TrustAll extends Ssl with Server with DelayedInit {
- lazy val sslContextFactory = new X509SSLContextFactory(
- serverCertKeyStore,
- tryProperty("jetty.ssl.keyStorePassword"),
- serverCertKeyStore); //this one is not needed since our wrapper ignores all trust managers
+ import scala.sys.SystemProperties._
- lazy val trustWrapper = new X509TrustManagerWrapper {
- def wrapTrustManager(trustManager: X509TrustManager) = new TrustAllClientsWrappingTrustManager(trustManager)
- }
-
- lazy val serverCertKeyStore = {
+ val sslContextFactory = {
+ val trustWrapper =
+ new X509TrustManagerWrapper {
+ def wrapTrustManager(trustManager: X509TrustManager) =
+ new TrustAllClientsWrappingTrustManager(trustManager)
+ }
+
+ val serverCertKeyStore = {
val keyStoreLoader = new KeyStoreLoader
- keyStoreLoader.setKeyStoreType(System.getProperty("jetty.ssl.keyStoreType","JKS"))
- keyStoreLoader.setKeyStorePath(trustStorePath)
- keyStoreLoader.setKeyStorePassword(System.getProperty("jetty.ssl.keyStorePassword","password"))
- keyStoreLoader.loadKeyStore();
- }
-
- sslContextFactory.setTrustManagerWrapper(trustWrapper);
+ keyStoreLoader.setKeyStoreType(getProperty("jetty.ssl.keyStoreType") getOrElse "JKS")
+ keyStoreLoader.setKeyStorePath(trustStorePath)
+ keyStoreLoader.setKeyStorePassword(getProperty("jetty.ssl.keyStorePassword") getOrElse "password")
+ keyStoreLoader.loadKeyStore()
+ }
+
+ val factory = new X509SSLContextFactory(
+ serverCertKeyStore,
+ getProperty("jetty.ssl.keyStorePassword") getOrElse sys.error("jetty.ssl.keyStorePassword not set"),
+ serverCertKeyStore) //this one is not needed since our wrapper ignores all trust managers
+
+ factory.setTrustManagerWrapper(trustWrapper)
+
+ factory
+ }
-
- lazy val trustStorePath = new SystemProperties().get("jetty.ssl.keyStore") match {
- case Some(path) => path
- case None => new File(new File(tryProperty("user.home")), ".keystore").getAbsolutePath
- }
-
- sslConn.setSslContext(sslContextFactory.buildSSLContext())
- sslConn.setWantClientAuth(true)
+ val trustStorePath =
+ getProperty("jetty.ssl.keyStore") getOrElse {
+ new File(new File(javaHome), ".keystore").getAbsolutePath
+ }
+
+ // not tested if ok, there was a problem anyway
+ def delayedInit(x: ⇒ Unit): Unit = {
+ sslConn.setSslContext(sslContextFactory.buildSSLContext())
+ sslConn.setWantClientAuth(true)
+ }
}
--- a/src/main/scala/ReadWriteWebMain.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/ReadWriteWebMain.scala Thu Nov 17 14:43:16 2011 +0100
@@ -106,7 +106,7 @@
//this is incomplete: we should be able to start both ports.... not sure how to do this yet.
val service = httpsPort.value match {
- case Some(port) => HttpsTrustAll(port,"0.0.0.0")
+ case Some(port) => new HttpsTrustAll(port,"0.0.0.0")
case None => Http(httpPort.value.get)
}
--- a/src/main/scala/Resource.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/Resource.scala Thu Nov 17 14:43:16 2011 +0100
@@ -4,18 +4,18 @@
import java.net.URL
import com.hp.hpl.jena.rdf.model._
-import scalaz._
+import scalaz.{Resource => _, _}
import Scalaz._
trait ResourceManager {
- def basePath: String
- def sanityCheck(): Boolean
- def resource(url: URL): Resource
+ def basePath:String
+ def sanityCheck():Boolean
+ def resource(url:URL):Resource
}
trait Resource {
- def get(): Validation[Throwable, Model]
- def save(model: Model): Validation[Throwable, Unit]
+ def get():Validation[Throwable, Model]
+ def save(model:Model):Validation[Throwable, Unit]
def createDirectory(model: Model): Validation[Throwable, Unit]
}
--- a/src/main/scala/auth/Authz.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/auth/Authz.scala Thu Nov 17 14:43:16 2011 +0100
@@ -25,7 +25,7 @@
import unfiltered.filter.Plan
import unfiltered.request._
-import collection.JavaConversions._
+import collection.JavaConverters._
import javax.security.auth.Subject
import java.net.URL
import com.hp.hpl.jena.query.{QueryExecutionFactory, QueryExecution, QuerySolutionMap, QueryFactory}
@@ -34,64 +34,44 @@
import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
import com.hp.hpl.jena.rdf.model.{RDFNode, ResourceFactory}
import org.w3.readwriteweb.{Authoritative, Resource, ResourceManager, WebCache}
+import org.w3.readwriteweb.util.HttpMethod
/**
* @author hjs
* @created: 14/10/2011
*/
-object HttpMethod {
- def unapply(req: HttpRequest[_]): Option[Method] =
- Some(
- req.method match {
- case "GET" => GET
- case "PUT" => PUT
- case "HEAD" => HEAD
- case "POST" => POST
- case "CONNECT" => CONNECT
- case "OPTIONS" => OPTIONS
- case "TRACE" => TRACE
- case m => new Method(m)
- })
-
-
-}
-
object AuthZ {
-
implicit def x509toSubject(x509c: X509Claim)(implicit cache: WebCache): Subject = {
val subject = new Subject()
subject.getPublicCredentials.add(x509c)
val verified = for (
- claim <- x509c.webidclaims;
- if (claim.verified)
+ claim <- x509c.webidclaims if (claim.verified)
) yield claim.principal
- subject.getPrincipals.addAll(verified)
+ subject.getPrincipals.addAll(verified.asJava)
subject
}
}
-class NullAuthZ[Request,Response] extends AuthZ[Request,Response] {
- override def subject(req: Req): Option[Subject] = None
+class NullAuthZ[Request, Response] extends AuthZ[Request, Response] {
+ def subject(req: Req): Option[Subject] = None
- override def guard(m: Method, path: URL): Guard = null
+ def guard(m: Method, path: URL): Guard = null
- override def protect(in: Req=>Res)(implicit m: Manifest[Request]) = in
+ override def protect(in: Req => Res)(implicit m: Manifest[Request]) = in
}
-abstract class AuthZ[Request,Response] {
+trait AuthZ[Request, Response] {
type Req = HttpRequest[Request]
type Res = ResponseFunction[Response]
-
- def protect(in: Req=>Res)(implicit m: Manifest[Request]): Req=>Res = {
- case req @ HttpMethod(method) & Authoritative(url,_) if guard(method, url).allow(() => subject(req)) => in(req)
- case _ => Unauthorized
- }
+ def protect(in: Req => Res)(implicit m: Manifest[Request]): Req => Res = {
+ case req @ HttpMethod(method) & Authoritative(url,_) if guard(method, url).allow(subject(req)) => in(req)
+ case _ => Unauthorized
+ }
-
protected def subject(req: Req): Option[Subject]
/** create the guard defined in subclass */
@@ -103,16 +83,18 @@
* verify if the given request is authorized
* @param subj function returning the subject to be authorized if the resource needs authorization
*/
- def allow(subj: () => Option[Subject]): Boolean
+ def allow(subj: => Option[Subject]): Boolean
}
}
-class RDFAuthZ[Request,Response](val webCache: WebCache, rm: ResourceManager)
+class RDFAuthZ[Request, Response](val webCache: WebCache, rm: ResourceManager)
(implicit val m: Manifest[Request]) extends AuthZ[Request,Response] {
+
import AuthZ.x509toSubject
- implicit val cache : WebCache = webCache
+
+ implicit val cache: WebCache = webCache
def subject(req: Req) = req match {
case X509Claim(claim) => Option(claim)
@@ -127,24 +109,21 @@
val Control = acl+"Control"
val selectQuery = QueryFactory.create("""
- PREFIX acl: <http://www.w3.org/ns/auth/acl#>
- SELECT ?mode ?group ?agent
- WHERE {
+ PREFIX acl: <http://www.w3.org/ns/auth/acl#>
+ SELECT ?mode ?group ?agent
+ WHERE {
?auth acl:accessTo ?res ;
acl:mode ?mode .
OPTIONAL { ?auth acl:agentClass ?group . }
- OPTIONAL { ?auth acl:agent ?agent . }
- }""")
+ OPTIONAL { ?auth acl:agent ?agent . }
+ }""")
}
def guard(method: Method, url: URL) = new Guard(method, url) {
import RDFGuard._
- import org.w3.readwriteweb.util.wrapValidation
- import org.w3.readwriteweb.util.ValidationW
+ import org.w3.readwriteweb.util.{ValidationW, wrapValidation}
-
-
- def allow(subj: () => Option[Subject]) = {
+ def allow(subj: => Option[Subject]) = {
val r: Resource = rm.resource(new URL(url,".meta.n3"))
val res: ValidationW[Boolean,Boolean] = for {
model <- r.get() failMap { x => true }
@@ -154,7 +133,7 @@
val qe = QueryExecutionFactory.create(selectQuery, model, initialBinding)
val agentsAllowed = try {
val exec = qe.execSelect()
- val res = for (qs <- exec) yield {
+ val res = for (qs <- exec.asScala) yield {
val methods = qs.get("mode").toString match {
case Read => List(GET)
case Write => List(PUT, POST)
@@ -170,10 +149,10 @@
}
if (agentsAllowed.size > 0) {
if (agentsAllowed.exists( pair => pair._2 == foafAgent )) true
- else subj() match {
+ else subj match {
case Some(s) => {
agentsAllowed.exists{
- p => s.getPrincipals(classOf[WebIdPrincipal]).
+ p => s.getPrincipals(classOf[WebIdPrincipal]).asScala.
exists(id=> {
val ps = if (p._1 != null) p._1.toString else null;
ps == id.webid
@@ -197,7 +176,6 @@
class ResourceGuard(path: String, reqMethod: Method) {
-
def allow(subjFunc: () => Option[Subject]) = {
subjFunc().isEmpty
}
--- a/src/main/scala/auth/X509Cert.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/auth/X509Cert.scala Thu Nov 17 14:43:16 2011 +0100
@@ -34,12 +34,16 @@
import interfaces.RSAPublicKey
import unfiltered.util.IO
import sun.security.x509._
-
+import org.w3.readwriteweb.util.trySome
object X509CertSigner {
- def apply(keyStoreLoc: URL, keyStoreType: String, password: String, alias: String) = {
- val keystore = KeyStore.getInstance(keyStoreType)
+ def apply(
+ keyStoreLoc: URL,
+ keyStoreType: String,
+ password: String,
+ alias: String): X509CertSigner = {
+ val keystore = KeyStore.getInstance(keyStoreType)
IO.use(keyStoreLoc.openStream()) { in =>
keystore.load(in, password.toCharArray)
@@ -48,11 +52,13 @@
val certificate = keystore.getCertificate(alias).asInstanceOf[X509Certificate]
//one could verify that indeed this is the private key corresponding to the public key in the cert.
- new X509CertSigner(certificate,privateKey)
+ new X509CertSigner(certificate, privateKey)
}
}
-class X509CertSigner(signingCert: X509Certificate, signingKey: PrivateKey ) {
+class X509CertSigner(
+ signingCert: X509Certificate,
+ signingKey: PrivateKey ) {
val WebID_DN="""O=FOAF+SSL, OU=The Community of Self Signers, CN=Not a Certification Authority"""
/**
@@ -69,136 +75,131 @@
* @param days how many days from now the Certificate is valid for
* @param algorithm the signing algorithm, eg "SHA1withRSA"
*/
- def generate(subjectDN: String,
- subjectKey: RSAPublicKey,
- days: Int,
- webId: URL): X509Certificate = { //todo: the algorithm should be deduced from private key in part
-
-
- var info = new X509CertInfo
- val from = new Date(System.currentTimeMillis()-10*1000*60) //start 10 minutes ago, to avoid network trouble
- val to = new Date(from.getTime + days*24*60*60*1000)
- val interval = new CertificateValidity(from, to)
- val serialNumber = new BigInteger(64, new SecureRandom)
- val subjectXN = new X500Name(subjectDN)
- val issuerXN = new X500Name(signingCert.getSubjectDN.toString)
-
- info.set(X509CertInfo.VALIDITY, interval)
- info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber))
- info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(subjectXN))
- info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuerXN))
- info.set(X509CertInfo.KEY, new CertificateX509Key(subjectKey))
- info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3))
-
- //
- //extensions
- //
- val extensions = new CertificateExtensions();
-
- val san = new SubjectAlternativeNameExtension(true, new GeneralNames().add(new GeneralName(new URIName(webId.toExternalForm))))
- extensions.set(san.getName,san)
-
- val basicCstrExt = new BasicConstraintsExtension(false,1)
- extensions.set(basicCstrExt.getName,basicCstrExt)
+ def generate(
+ subjectDN: String,
+ subjectKey: RSAPublicKey,
+ days: Int,
+ webId: URL): X509Certificate = { //todo: the algorithm should be deduced from private key in part
- { import KeyUsageExtension._
- val keyUsage = new KeyUsageExtension()
- List(DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, KEY_AGREEMENT, KEY_CERTSIGN).foreach {
- usage => keyUsage.set(usage,true)
- }
- extensions.set(keyUsage.getName,keyUsage)
- }
-
- { import NetscapeCertTypeExtension._
- val netscapeExt = new NetscapeCertTypeExtension()
- List(SSL_CLIENT, S_MIME) foreach { ext => netscapeExt.set(ext,true) }
- extensions.set(netscapeExt.getName, new NetscapeCertTypeExtension(false,netscapeExt.getValue))
- }
-
- val subjectKeyExt = new SubjectKeyIdentifierExtension(new KeyIdentifier(subjectKey).getIdentifier)
- extensions.set(subjectKeyExt.getName,subjectKeyExt)
-
- info.set(X509CertInfo.EXTENSIONS,extensions)
+ var info = new X509CertInfo
+ val from = new Date(System.currentTimeMillis()-10*1000*60) //start 10 minutes ago, to avoid network trouble
+ val to = new Date(from.getTime + days*24*60*60*1000)
+ val interval = new CertificateValidity(from, to)
+ val serialNumber = new BigInteger(64, new SecureRandom)
+ val subjectXN = new X500Name(subjectDN)
+ val issuerXN = new X500Name(signingCert.getSubjectDN.toString)
- val algo = signingCert.getPublicKey.getAlgorithm match {
- case "DSA" => new AlgorithmId(AlgorithmId.sha1WithDSA_oid )
- case "RSA" => new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid)
- case _ => throw new RuntimeException("Don't know how to sign with this type of key")
- }
-
- info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo))
+ info.set(X509CertInfo.VALIDITY, interval)
+ info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber))
+ info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(subjectXN))
+ info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuerXN))
+ info.set(X509CertInfo.KEY, new CertificateX509Key(subjectKey))
+ info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3))
- // Sign the cert to identify the algorithm that's used.
- val tmpCert = new X509CertImpl(info)
- tmpCert.sign(signingKey,algo.getName)
+ //
+ //extensions
+ //
+ val extensions = new CertificateExtensions
- //update the algorithm and re-sign
- val sigAlgo = tmpCert.get(X509CertImpl.SIG_ALG).asInstanceOf[AlgorithmId]
- info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgo)
- val cert = new X509CertImpl(info)
- cert.sign(signingKey,algo.getName)
-
- cert.verify(signingCert.getPublicKey)
- return cert
+ val san =
+ new SubjectAlternativeNameExtension(
+ true,
+ new GeneralNames().add(
+ new GeneralName(new URIName(webId.toExternalForm))))
+
+ extensions.set(san.getName, san)
+
+ val basicCstrExt = new BasicConstraintsExtension(false,1)
+ extensions.set(basicCstrExt.getName,basicCstrExt)
+
+ {
+ import KeyUsageExtension._
+ val keyUsage = new KeyUsageExtension
+ val usages =
+ List(DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, KEY_AGREEMENT, KEY_CERTSIGN)
+ usages foreach { usage => keyUsage.set(usage, true) }
+ extensions.set(keyUsage.getName,keyUsage)
}
+ {
+ import NetscapeCertTypeExtension._
+ val netscapeExt = new NetscapeCertTypeExtension
+ List(SSL_CLIENT, S_MIME) foreach { ext => netscapeExt.set(ext, true) }
+ extensions.set(
+ netscapeExt.getName,
+ new NetscapeCertTypeExtension(false, netscapeExt.getValue))
+ }
+
+ val subjectKeyExt =
+ new SubjectKeyIdentifierExtension(new KeyIdentifier(subjectKey).getIdentifier)
+
+ extensions.set(subjectKeyExt.getName, subjectKeyExt)
+
+ info.set(X509CertInfo.EXTENSIONS, extensions)
+
+ val algo = signingCert.getPublicKey.getAlgorithm match {
+ case "DSA" => new AlgorithmId(AlgorithmId.sha1WithDSA_oid )
+ case "RSA" => new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid)
+ case _ => sys.error("Don't know how to sign with this type of key")
+ }
+
+ info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo))
+
+ // Sign the cert to identify the algorithm that's used.
+ val tmpCert = new X509CertImpl(info)
+ tmpCert.sign(signingKey, algo.getName)
+
+ //update the algorithm and re-sign
+ val sigAlgo = tmpCert.get(X509CertImpl.SIG_ALG).asInstanceOf[AlgorithmId]
+ info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgo)
+ val cert = new X509CertImpl(info)
+ cert.sign(signingKey,algo.getName)
+
+ cert.verify(signingCert.getPublicKey)
+ return cert
+ }
}
object Certs {
-
def unapplySeq[T](r: HttpRequest[T])(implicit m: Manifest[T]): Option[IndexedSeq[Certificate]] = {
- if (m <:< manifest[HttpServletRequest]) unapplyServletRequest(r.asInstanceOf[HttpRequest[HttpServletRequest]])
- else if (m <:< manifest[ReceivedMessage]) unapplyReceivedMessage(r.asInstanceOf[HttpRequest[ReceivedMessage]])
- else None //todo: should throw an exception here?
+ if (m <:< manifest[HttpServletRequest])
+ unapplyServletRequest(r.asInstanceOf[HttpRequest[HttpServletRequest]])
+ else if (m <:< manifest[ReceivedMessage])
+ unapplyReceivedMessage(r.asInstanceOf[HttpRequest[ReceivedMessage]])
+ else
+ None //todo: should throw an exception here?
}
//todo: should perhaps pass back error messages, which they could in the case of netty
- private def unapplyServletRequest[T <: HttpServletRequest](r: HttpRequest[T]):
- Option[IndexedSeq[Certificate]] = {
+ private def unapplyServletRequest[T <: HttpServletRequest](r: HttpRequest[T]): Option[IndexedSeq[Certificate]] =
r.underlying.getAttribute("javax.servlet.request.X509Certificate") match {
case certs: Array[Certificate] => Some(certs)
case _ => None
}
- }
-
- private def unapplyReceivedMessage[T <: ReceivedMessage](r: HttpRequest[T]):
- Option[IndexedSeq[Certificate]] = {
+
+ private def unapplyReceivedMessage[T <: ReceivedMessage](r: HttpRequest[T]): Option[IndexedSeq[Certificate]] = {
import org.jboss.netty.handler.ssl.SslHandler
- r.underlying.context.getPipeline.get(classOf[SslHandler]) match {
- case sslh: SslHandler => try {
- //return the client certificate in the existing session if one exists
- Some(sslh.getEngine.getSession.getPeerCertificates)
- } catch {
- case e => {
- // request a certificate from the user
- sslh.setEnableRenegotiation(true)
- r match {
- case UserAgent(agent) if needAuth(agent) => sslh.getEngine.setNeedClientAuth(true)
- case _ => sslh.getEngine.setWantClientAuth(true)
- }
-
- val future = sslh.handshake()
- future.await(30000) //that's certainly way too long.
- if (future.isDone) {
- if (future.isSuccess) try {
- Some(sslh.getEngine.getSession.getPeerCertificates)
- } catch {
- case e => None
- } else {
- None
- }
- } else {
- None
- }
- }
+
+ val sslh = r.underlying.context.getPipeline.get(classOf[SslHandler])
+
+ trySome(sslh.getEngine.getSession.getPeerCertificates.toIndexedSeq) orElse {
+ sslh.setEnableRenegotiation(true)
+ r match {
+ case UserAgent(agent) if needAuth(agent) => sslh.getEngine.setNeedClientAuth(true)
+ case _ => sslh.getEngine.setWantClientAuth(true)
}
- case _ => None
+ val future = sslh.handshake()
+ future.await(30000) //that's certainly way too long.
+ if (future.isDone && future.isSuccess)
+ trySome(sslh.getEngine.getSession.getPeerCertificates.toIndexedSeq)
+ else
+ None
}
}
@@ -211,9 +212,8 @@
* so that changes to browsers could update server behavior
*
*/
- def needAuth(agent: String): Boolean = {
- agent.contains("Java")
- }
+ def needAuth(agent: String): Boolean =
+ agent contains "Java"
}
--- a/src/main/scala/auth/X509Claim.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/auth/X509Claim.scala Thu Nov 17 14:43:16 2011 +0100
@@ -45,16 +45,16 @@
final val logger = LoggerFactory.getLogger(classOf[X509Claim])
val idCache: Cache[X509Certificate, X509Claim] =
- CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).
- build(new CacheLoader[X509Certificate, X509Claim]() {
- def load(x509: X509Certificate) = new X509Claim(x509)
+ CacheBuilder.newBuilder()
+ .expireAfterWrite(30, TimeUnit.MINUTES)
+ .build(new CacheLoader[X509Certificate, X509Claim] {
+ def load(x509: X509Certificate) = new X509Claim(x509)
})
- def unapply[T](r: HttpRequest[T])(implicit webCache: WebCache,m: Manifest[T]): Option[X509Claim] =
- r match {
- case Certs(c1: X509Certificate, _*) => Some(idCache.get(c1))
- case _ => None
- }
+ def unapply[T](r: HttpRequest[T])(implicit webCache: WebCache,m: Manifest[T]): Option[X509Claim] = r match {
+ case Certs(c1: X509Certificate, _*) => Some(idCache.get(c1))
+ case _ => None
+ }
@@ -65,13 +65,14 @@
* @param cert X.509 certificate from which to extract the URIs.
* @return Iterator of URIs as strings found in the subjectAltName extension.
*/
- def getClaimedWebIds(cert: X509Certificate): Iterator[String] =
- if (cert == null) Iterator.empty;
+ def getClaimedWebIds(cert: X509Certificate): Iterator[String] =
+ if (cert == null)
+ Iterator.empty
else cert.getSubjectAlternativeNames() match {
case coll if (coll != null) => {
- for (sanPair <- coll
- if (sanPair.get(0) == 6)
- ) yield sanPair(1).asInstanceOf[String]
+ for {
+ sanPair <- coll if (sanPair.get(0) == 6)
+ } yield sanPair(1).asInstanceOf[String]
}.iterator
case _ => Iterator.empty
}
@@ -89,18 +90,19 @@
* @author bblfish
* @created: 30/03/2011
*/
-class X509Claim(val cert: X509Certificate) extends Refreshable {
+// should just be a case class
+class X509Claim(val cert: X509Certificate) extends Refreshable {
import X509Claim._
- val claimReceivedDate = new Date();
+ val claimReceivedDate = new Date()
lazy val tooLate = claimReceivedDate.after(cert.getNotAfter())
lazy val tooEarly = claimReceivedDate.before(cert.getNotBefore())
/* a list of unverified principals */
- lazy val webidclaims = getClaimedWebIds(cert).map {
- webid =>new WebIDClaim(webid, cert.getPublicKey)
- }.toSet
-
+ lazy val webidclaims = {
+ val claims = getClaimedWebIds(cert) map { webid => new WebIDClaim(webid, cert.getPublicKey) }
+ claims.toSet
+ }
//note could also implement Destroyable
@@ -112,28 +114,22 @@
//note: one could also take the validity period to be dependent on the validity of the profile representation
//in which case updating the validity period would make more sense.
- override
- def refresh() {
- }
+ override def refresh() = ()
/* The certificate is currently within the valid time zone */
- override
- def isCurrent(): Boolean = !(tooLate||tooEarly)
+ override def isCurrent(): Boolean = ! (tooLate || tooEarly)
- lazy val error = {}
+ lazy val error = ()
def canEqual(other: Any) = other.isInstanceOf[X509Claim]
- override
- def equals(other: Any): Boolean =
- other match {
- case that: X509Claim => (that eq this) || (that.canEqual(this) && cert == that.cert)
- case _ => false
- }
+ override def equals(other: Any): Boolean = other match {
+ case that: X509Claim => (that eq this) || (that.canEqual(this) && cert == that.cert)
+ case _ => false
+ }
- override
- lazy val hashCode: Int = 41 * (41 +
- (if (cert != null) cert.hashCode else 0))
+ override lazy val hashCode: Int =
+ 41 * (41 + (if (cert != null) cert.hashCode else 0))
}
--- a/src/main/scala/plan.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/plan.scala Thu Nov 17 14:43:16 2011 +0100
@@ -8,7 +8,6 @@
import org.slf4j.{Logger, LoggerFactory}
-import com.hp.hpl.jena.rdf.model.Model
import com.hp.hpl.jena.query.{Query, QueryExecution, QueryExecutionFactory}
import com.hp.hpl.jena.update.UpdateAction
import Query.{QueryTypeSelect => SELECT,
@@ -16,11 +15,13 @@
QueryTypeConstruct => CONSTRUCT,
QueryTypeDescribe => DESCRIBE}
-import scalaz.{Resource=>SzResource}
+import scalaz.{Resource => _}
import unfiltered.request._
import unfiltered.Cycle
import unfiltered.response._
+import com.hp.hpl.jena.rdf.model.Model
+
//object ReadWriteWeb {
//
// val defaultHandler: PartialFunction[Throwable, HttpResponse[_]] = {
@@ -33,12 +34,12 @@
* The ReadWriteWeb intent.
* It is independent of jetty or netty
*/
-trait ReadWriteWeb[Req,Res] {
+trait ReadWriteWeb[Req, Res] {
val rm: ResourceManager
implicit def manif: Manifest[Req]
- implicit val authz: AuthZ[Req,Res] = new NullAuthZ[Req,Res]
+ implicit val authz: AuthZ[Req, Res] = new NullAuthZ[Req, Res]
// a few type short cuts to make it easier to reason with the code here
- // one may want to generalise this code so that it does not depend so strongly on servlets.
+ // one may want to generalize this code so that it does not depend so strongly on servlets.
// type Request = HttpRequest[Req]
// type Response = ResponseFunction[Res]
@@ -50,7 +51,7 @@
* ( Note that we don't want to protect this intent, since that would be to apply the security to all other applications,
* many of which may want different authorization implementations )
*/
- def intent : Cycle.Intent[Req,Res] = {
+ def intent : Cycle.Intent[Req, Res] = {
case req @ Path(path) if path startsWith rm.basePath => authz.protect(rwwIntent)(manif)(req)
}
@@ -170,4 +171,4 @@
-}
\ No newline at end of file
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/HttpMethod.scala Thu Nov 17 14:43:16 2011 +0100
@@ -0,0 +1,20 @@
+package org.w3.readwriteweb.util
+
+import unfiltered.request._
+
+// TODO pull request to the unfiltered project!
+object HttpMethod {
+ def unapply(req: HttpRequest[_]): Option[Method] =
+ Some(
+ req.method match {
+ case "GET" => GET
+ case "PUT" => PUT
+ case "HEAD" => HEAD
+ case "POST" => POST
+ case "CONNECT" => CONNECT
+ case "OPTIONS" => OPTIONS
+ case "TRACE" => TRACE
+ case m => new Method(m)
+ })
+
+}
\ No newline at end of file
--- a/src/main/scala/util/package.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/main/scala/util/package.scala Thu Nov 17 14:43:16 2011 +0100
@@ -8,8 +8,6 @@
package object util {
-
-
def modelFromInputStream(
is: InputStream,
base: URL,
@@ -40,4 +38,12 @@
implicit def unwrap[E, F <: E, S <: E](v: Validation[F,S]): E = v.fold(e => e, s => s)
+ // I wonder if this is already defined somewhere...
+ def trySome[T](body: => T): Option[T] =
+ try {
+ Option(body)
+ } catch {
+ case _ => None
+ }
+
}
--- a/src/test/scala/auth/CreateWebIDSpec.scala Thu Nov 17 14:30:44 2011 +0100
+++ b/src/test/scala/auth/CreateWebIDSpec.scala Thu Nov 17 14:43:16 2011 +0100
@@ -42,10 +42,10 @@
* these test cases it does.
*/
class FlexiKeyManager extends X509ExtendedKeyManager {
- val keys = mutable.Map[String, Pair[Array[X509Certificate],PrivateKey]]()
+ val keys = mutable.Map[String, (Array[X509Certificate], PrivateKey)]()
def addClientCert(alias: String,certs: Array[X509Certificate], privateKey: PrivateKey) {
- keys.put(alias,Pair(certs,privateKey))
+ keys += (alias -> (certs -> privateKey))
}
var currentId: String = null