2014年12月18日木曜日

play framework 2で「ファイル名が長すぎます」と出た時の対処法

Play Framework 2.1 を使っていた時に次のようなエラーが出たことがあった。
$ play ~compile
...
[error] 
[error]      while compiling: myproject/target/scala-2.10/src_managed/main/views/html/signup.template.scala
[error]         during phase: jvm
[error]      library version: version 2.10.0
[error]     compiler version: version 2.10.0
[error]   reconstructed args: -encoding utf8 -bootclasspath ...
[error] 
[error]   last tree to typer: Literal(Constant(play.api.templates.Html))
[error]               symbol: null
[error]    symbol definition: null
[error]                  tpe: Class(classOf[play.api.templates.Html])
[error]        symbol owners: 
[error]       context owners: anonymous class anonfun$f$1 -> package html
[error] 
[error] == Enclosing template or block ==
...

[error] == Expanded type of tree ==
[error] 
[error] ConstantType(value = Constant(play.api.templates.Html))
[error] 
[error] uncaught exception during compilation: java.io.IOException
[error] ファイル名が長すぎます
[error] two errors found
[error] (compile:compile) Compilation failed
[error] Total time: 25 s, completed 2014/12/18 11:57:36
1. Waiting for source changes... (press enter to interrupt)
どうやら、playが自動生成するファイルのクラス名が長すぎて、scalaコンパイラの扱う長さを超えてしまっていることが原因らしい。しかしscalacに渡すコンパイラオプションを指定することによって長い名前を許容することができる。 play frameworkの場合はSBTを使っているので、project/Build.scalaをつぎのように変更した。

object ApplicationBuild extends Build {
  ...

  val main = play.Project(appName, appVersion, appDependencies).settings(
    scalacOptions ++= Seq("-Xmax-classfile-name", "140")
  )
}
参考: https://github.com/scala/pickling/issues/10#issuecomment-31318136

2014年11月14日金曜日

Scalaで Netty を使った WebSocket Client

JBossのNettyというライブラリを使えばWebSocketクライアントを実装できると聞いてJava製のサンプルコードがあったのでそれをScala化してみた。バージョンはわけあって3.9系だけど多分4系でも同様に動く。

オリジナルのJavaコード:  https://github.com/netty/netty/tree/3.9.1/src/main/java/org/jboss/netty/example/http/websocketx/client

ついでにSBT化もしてみた。ディレクトリ構成はたったの3ファイル。sbt 'run ws://localhost/' で実行可能。
  • WebSocketClient.scala
  • WebSocketClientHandler.scala
  • build.sbt


WebSocketClient.scala
import java.net.InetSocketAddress
import java.net.URI
import java.util.HashMap
import java.util.concurrent.Executors
import org.jboss.netty.bootstrap.ClientBootstrap
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.channel.Channel
import org.jboss.netty.channel.ChannelFuture
import org.jboss.netty.channel.ChannelPipeline
import org.jboss.netty.channel.ChannelPipelineFactory
import org.jboss.netty.channel.Channels
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory
import org.jboss.netty.handler.codec.http.HttpRequestEncoder
import org.jboss.netty.handler.codec.http.HttpResponseDecoder
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory
import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion
class WebSocketClient(uri : URI) {
def run() = {
val bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()))
var ch : Channel = null
try {
val protocol = uri.getScheme()
if (!"ws".equals(protocol)) {
throw new IllegalArgumentException("Unsupported protocol: " + protocol)
}
val customHeaders = new HashMap[String, String]()
customHeaders.put("MyHeader", "MyValue")
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
// If you change it to V00, ping is not supported and remember to change
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
val handshaker =
new WebSocketClientHandshakerFactory().newHandshaker(
uri, WebSocketVersion.V13, null, false, customHeaders)
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
def getPipeline() = {
val pipeline = Channels.pipeline()
pipeline.addLast("decoder", new HttpResponseDecoder())
pipeline.addLast("encoder", new HttpRequestEncoder())
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker))
pipeline
}
})
// Connect
println("WebSocket Client connecting")
val future =
bootstrap.connect(new InetSocketAddress(uri.getHost(), uri.getPort()))
future.syncUninterruptibly()
ch = future.getChannel()
handshaker.handshake(ch).syncUninterruptibly()
// Send 10 messages and wait for responses
println("WebSocket Client sending message")
for (i <- 0 to 1000) {
//ch.write(new TextWebSocketFrame("Message #" + i))
}
// Ping
println("WebSocket Client sending ping")
ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(Array(1, 2, 3, 4, 5, 6).map(_.toByte))))
// Close
println("WebSocket Client sending close")
ch.write(new CloseWebSocketFrame())
// WebSocketClientHandler will close the connection when the server
// responds to the CloseWebSocketFrame.
ch.getCloseFuture().awaitUninterruptibly()
}
if (ch != null) {
//ch.close()
}
bootstrap.releaseExternalResources()
}
}
object WebSocketClient {
def main(args : Array[String]) = {
val uri =
if (args.length > 0) new URI(args(0))
else new URI("ws://localhost:8080/websocket")
new WebSocketClient(uri).run()
}
}
WebSocketClientHandler.scala
import org.jboss.netty.channel.Channel
import org.jboss.netty.channel.ChannelHandlerContext
import org.jboss.netty.channel.ChannelStateEvent
import org.jboss.netty.channel.ExceptionEvent
import org.jboss.netty.channel.MessageEvent
import org.jboss.netty.channel.SimpleChannelUpstreamHandler
import org.jboss.netty.handler.codec.http.HttpResponse
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame
import org.jboss.netty.util.CharsetUtil
class WebSocketClientHandler(handshaker : WebSocketClientHandshaker) extends SimpleChannelUpstreamHandler {
override def channelClosed(ctx : ChannelHandlerContext , e : ChannelStateEvent) = {
println("WebSocket Client disconnected!")
}
override def messageReceived(ctx : ChannelHandlerContext, e : MessageEvent) {
val ch = ctx.getChannel()
if (!handshaker.isHandshakeComplete()) {
handshaker.finishHandshake(ch, e.getMessage().asInstanceOf[HttpResponse])
println("WebSocket Client connected!")
return
}
if (e.getMessage().isInstanceOf[HttpResponse]) {
val response = e.getMessage().asInstanceOf[HttpResponse]
throw new Exception("Unexpected HttpResponse (status=" + response.getStatus() + ", content="
+ response.getContent().toString(CharsetUtil.UTF_8) + ')')
}
val frame = e.getMessage().asInstanceOf[WebSocketFrame]
if (frame.isInstanceOf[TextWebSocketFrame]) {
val textFrame = frame.asInstanceOf[TextWebSocketFrame]
println("WebSocket Client received message: " + textFrame.getText())
} else if (frame .isInstanceOf [PongWebSocketFrame]) {
println("WebSocket Client received pong")
} else if (frame .isInstanceOf [CloseWebSocketFrame]) {
println("WebSocket Client received closing")
ch.close()
} else if (frame .isInstanceOf [PingWebSocketFrame]) {
println("WebSocket Client received ping, response with pong")
ch.write(new PongWebSocketFrame(frame.getBinaryData()))
}
}
override def exceptionCaught(ctx: ChannelHandlerContext, e: ExceptionEvent) ={
val t = e.getCause()
t.printStackTrace()
e.getChannel().close()
}
}
build.sbt
name := "Netty Websocket Client Example for Scala"
libraryDependencies ++= Seq(
"io.netty" % "netty" % "3.9.5.Final"
)
view raw build.sbt hosted with ❤ by GitHub
 単純な構文リプレイスなのでScalaらしくはない。

2014年9月11日木曜日

LinuxでWindowsのGoogle Chrome対応ブラウザサービスを利用する

Linuxでウェブブラウザを利用していると、だいたいどのサービスもWindowsや他のOSと同様に利用できるが、たまに次のように表示され、利用できないことがある。
Google Chrome対応となっております。
下記OSにて利用可能なGoogle Chromeのみ対応しております。
* Windows Vista/7/8
* Mac OS X 10.6/10.7/10.8/10.9
多くの場合、LinuxのGoogle Chromeでも原理上動作はするが、運営側がテストをしていないということで、対応OS以外であればサービスを無効にするような処理が施されている。 ウェブサービスでOSを判定するためには、多くの場合ブラウザのUser Agent情報を参照している。しかしこれは自分のブラウザが勝手に名乗っているだけで、偽装することが可能である。特にGoogle Chromeでは比較的簡単にUser Agentを偽装できる。 その手順は次の通り
  1. Google Chromeで利用したいページを開く
  2. F12またはCtrl-Shift-i を押してDeveloper Toolsウィンドウを開く
  3. 右下の歯車アイコンをクリックしてSettingsを開く(画像参照)
  4. 右上の方のOverride User Agentにチェック(画像参照)
  5. 偽装したいブラウザ,OSを選択
  6. ブラウザをリロード
以上でUser Agentを選択できるが、Windows版のGoogle Chromeはなぜか選択肢に入ってない。その場合はOthersを選択して 次のUser Agentを直接指定すれば良い。
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36
試した環境は次の通り
  • Ubuntu 12.04
  • Google Chrome 18.0.1025.162

2014年6月6日金曜日

OpenSSLのCCSに関する脆弱性

以下、http://ccsinjection.lepidum.co.jp/ja.html より引用


[English]
最終更新日: Fri, 06 Jun 2014 01:29:36 +0900

CCS Injection Vulnerability

概要


OpenSSLのChangeCipherSpecメッセージの処理に欠陥が発見されました。
この脆弱性を悪用された場合、暗号通信の情報が漏えいする可能性があります。
サーバとクライアントの両方に影響があり、迅速な対応が求められます。
攻撃方法には充分な再現性があり、標的型攻撃等に利用される可能性は非常に高いと考えます。

対策

各ベンダから更新がリリースされると思われるので、それをインストールすることで対策できます。
(随時更新)

原因

OpenSSLのChangeCipherSpecメッセージの処理に発見された欠陥により、第三者が通信に介在することが可能であることを確認しました。
そのためOpenSSLに第三者が知ることのできる弱い鍵を使用させることができます。
今回発見された脆弱性により、これにより修正前のバージョンのOpenSSLを使用して通信の保護を実施していたウェブの閲覧、電子メールの送受信、VPNといったソフトウェアには通信内容や認証情報などを詐取・改ざんされる危険性があります。

Q&A

どのバージョンが影響を受けますか?

以下のバージョンにバグが存在する。
  • 1.0.1から1.0.1g
  • 1.0.0から1.0.0l
  • 0.9.8y以前の全て
以下のバージョンではバグが修正されている。
  • 1.0.1h
  • 1.0.0m
  • 0.9.8za

どのような攻撃が行われる恐れがありますか?

クライアントとサーバがともにバグが存在するバージョンで、サーバがバージョン1.0.1以降の場合に、通信の盗聴・改ざんを行う攻撃が行われる恐れがあります。 サーバだけがバグの存在するバージョンの場合は、クライアントの偽装を行う攻撃が行われる恐れがあります。

秘密鍵を再生成し、証明書を再発行する必要はありますか?

この脆弱性を悪用したとしても、秘密鍵を盗み出すことはできません。しかし、一度でもOpenSSLのSSL/TLSで保護された経路で秘密鍵を転送したことがある場合は慎重に考慮してください。

SSL/TLSのプロトコル設計の問題ですか?

いいえ。実装の問題です。

どのプロトコルが影響をうけますか?

SSL3.0, TLS1.0, TLS1.1, TLS1.2 のすべてが影響をうけます。

どの暗号アルゴリズムが影響を受けますか?

全ての暗号アルゴリズムが影響を受けます。

過去に攻撃を受けた形跡を確認することはできますか?

OpenSSLを使っていた場合は何の形跡も残らないため、おそらく確認することはできません。

IDS等で検知することは可能ですか?

通常と異なるタイミングで送信されるChangeCipherSpecパケットを検知するよう構成すれば、検知できると思われます。

どのようにして発見されましたか?

レピダムの菊池がCoqを用いたTLSの安全な実装の研究中に発見しました。

参照

CCS-InjectionのロゴはCC0で公開されます。SVGフォーマットでダウンロード

2014年3月25日火曜日

Beamerでテーマによって Undefined control sequence. のようなエラーが出る問題


Beamerを使っていて、次のようなエラーが出て困ったことがありました。

! Undefined control sequence.
\trans@languagepath ->\languagename 
                                    ,English
色々調べてみると、自分の場合はMadridというテーマを使っていて、次の行を削除するとエラーが出なくなることがわかりました。

\usetheme{Madrid}
テーマを指定しなかったり、別のテーマの場合は通ったりしたので、不思議だったのですが、原因がわかりました。タイトル情報が無かったということでした。 次の4行を追加し、エラーをなくすことが出来ました。

\title{タイトルタイトル}
\author{連続太郎}
\institute{株式会社連続体仮説}
\date{\today}
Madridというテーマでは各ページのした部分にタイトルや著者などの情報を表示しており、タイトル情報がきっと必須だったのでしょう。考えてみれば当然です。 しかし、LaTeXって便利だけれどエラーメッセージがわかりにくいですね。