Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
86ea65ab
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
86ea65ab
编写于
10月 29, 2014
作者:
S
Stephen Connolly
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make it possible for sub-classes to have a sub-class specific trust anchor chain
上级
4cb7414e
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
77 addition
and
64 deletion
+77
-64
core/src/main/java/hudson/model/UpdateSite.java
core/src/main/java/hudson/model/UpdateSite.java
+10
-1
core/src/main/java/jenkins/util/JSONSignatureValidator.java
core/src/main/java/jenkins/util/JSONSignatureValidator.java
+67
-63
未找到文件。
core/src/main/java/hudson/model/UpdateSite.java
浏览文件 @
86ea65ab
...
@@ -218,7 +218,16 @@ public class UpdateSite {
...
@@ -218,7 +218,16 @@ public class UpdateSite {
* Verifies the signature in the update center data file.
* Verifies the signature in the update center data file.
*/
*/
private
FormValidation
verifySignature
(
JSONObject
o
)
throws
IOException
{
private
FormValidation
verifySignature
(
JSONObject
o
)
throws
IOException
{
return
new
JSONSignatureValidator
(
"update site '"
+
id
+
"'"
).
verifySignature
(
o
);
return
getJsonSignatureValidator
().
verifySignature
(
o
);
}
/**
* Let sub-classes of UpdateSite provide their own signature validator.
* @return the signature validator.
*/
@Nonnull
protected
JSONSignatureValidator
getJsonSignatureValidator
()
{
return
new
JSONSignatureValidator
(
"update site '"
+
id
+
"'"
);
}
}
/**
/**
...
...
core/src/main/java/jenkins/util/JSONSignatureValidator.java
浏览文件 @
86ea65ab
...
@@ -72,6 +72,64 @@ public class JSONSignatureValidator {
...
@@ -72,6 +72,64 @@ public class JSONSignatureValidator {
certs
.
add
(
c
);
certs
.
add
(
c
);
}
}
CertificateUtil
.
validatePath
(
certs
,
loadTrustAnchors
(
cf
));
}
// this is for computing a digest to check sanity
MessageDigest
sha1
=
MessageDigest
.
getInstance
(
"SHA1"
);
DigestOutputStream
dos
=
new
DigestOutputStream
(
new
NullOutputStream
(),
sha1
);
// this is for computing a signature
Signature
sig
=
Signature
.
getInstance
(
"SHA1withRSA"
);
sig
.
initVerify
(
certs
.
get
(
0
));
SignatureOutputStream
sos
=
new
SignatureOutputStream
(
sig
);
// until JENKINS-11110 fix, UC used to serve invalid digest (and therefore unverifiable signature)
// that only covers the earlier portion of the file. This was caused by the lack of close() call
// in the canonical writing, which apparently leave some bytes somewhere that's not flushed to
// the digest output stream. This affects Jenkins [1.424,1,431].
// Jenkins 1.432 shipped with the "fix" (1eb0c64abb3794edce29cbb1de50c93fa03a8229) that made it
// compute the correct digest, but it breaks all the existing UC json metadata out there. We then
// quickly discovered ourselves in the catch-22 situation. If we generate UC with the correct signature,
// it'll cut off [1.424,1.431] from the UC. But if we don't, we'll cut off [1.432,*).
//
// In 1.433, we revisited 1eb0c64abb3794edce29cbb1de50c93fa03a8229 so that the original "digest"/"signature"
// pair continues to be generated in a buggy form, while "correct_digest"/"correct_signature" are generated
// correctly.
//
// Jenkins should ignore "digest"/"signature" pair. Accepting it creates a vulnerability that allows
// the attacker to inject a fragment at the end of the json.
o
.
writeCanonical
(
new
OutputStreamWriter
(
new
TeeOutputStream
(
dos
,
sos
),
"UTF-8"
)).
close
();
// did the digest match? this is not a part of the signature validation, but if we have a bug in the c14n
// (which is more likely than someone tampering with update center), we can tell
String
computedDigest
=
new
String
(
Base64
.
encode
(
sha1
.
digest
()));
String
providedDigest
=
signature
.
optString
(
"correct_digest"
);
if
(
providedDigest
==
null
)
{
return
FormValidation
.
error
(
"No correct_digest parameter in "
+
name
+
". This metadata appears to be old."
);
}
if
(!
computedDigest
.
equalsIgnoreCase
(
providedDigest
))
{
String
msg
=
"Digest mismatch: computed="
+
computedDigest
+
" vs expected="
+
providedDigest
+
" in "
+
name
;
if
(
LOGGER
.
isLoggable
(
Level
.
SEVERE
))
{
LOGGER
.
severe
(
msg
);
LOGGER
.
severe
(
o
.
toString
(
2
));
}
return
FormValidation
.
error
(
msg
);
}
String
providedSignature
=
signature
.
getString
(
"correct_signature"
);
if
(!
sig
.
verify
(
Base64
.
decode
(
providedSignature
.
toCharArray
())))
{
return
FormValidation
.
error
(
"Signature in the update center doesn't match with the certificate in "
+
name
);
}
if
(
warning
!=
null
)
return
warning
;
return
FormValidation
.
ok
();
}
catch
(
GeneralSecurityException
e
)
{
return
FormValidation
.
error
(
e
,
"Signature verification failed in "
+
name
);
}
}
protected
Set
<
TrustAnchor
>
loadTrustAnchors
(
CertificateFactory
cf
)
throws
IOException
{
// if we trust default root CAs, we end up trusting anyone who has a valid certificate,
// if we trust default root CAs, we end up trusting anyone who has a valid certificate,
// which isn't useful at all
// which isn't useful at all
Set
<
TrustAnchor
>
anchors
=
new
HashSet
<
TrustAnchor
>();
// CertificateUtil.getDefaultRootCAs();
Set
<
TrustAnchor
>
anchors
=
new
HashSet
<
TrustAnchor
>();
// CertificateUtil.getDefaultRootCAs();
...
@@ -134,61 +192,7 @@ public class JSONSignatureValidator {
...
@@ -134,61 +192,7 @@ public class JSONSignatureValidator {
}
}
}
}
}
}
CertificateUtil
.
validatePath
(
certs
,
anchors
);
return
anchors
;
}
// this is for computing a digest to check sanity
MessageDigest
sha1
=
MessageDigest
.
getInstance
(
"SHA1"
);
DigestOutputStream
dos
=
new
DigestOutputStream
(
new
NullOutputStream
(),
sha1
);
// this is for computing a signature
Signature
sig
=
Signature
.
getInstance
(
"SHA1withRSA"
);
sig
.
initVerify
(
certs
.
get
(
0
));
SignatureOutputStream
sos
=
new
SignatureOutputStream
(
sig
);
// until JENKINS-11110 fix, UC used to serve invalid digest (and therefore unverifiable signature)
// that only covers the earlier portion of the file. This was caused by the lack of close() call
// in the canonical writing, which apparently leave some bytes somewhere that's not flushed to
// the digest output stream. This affects Jenkins [1.424,1,431].
// Jenkins 1.432 shipped with the "fix" (1eb0c64abb3794edce29cbb1de50c93fa03a8229) that made it
// compute the correct digest, but it breaks all the existing UC json metadata out there. We then
// quickly discovered ourselves in the catch-22 situation. If we generate UC with the correct signature,
// it'll cut off [1.424,1.431] from the UC. But if we don't, we'll cut off [1.432,*).
//
// In 1.433, we revisited 1eb0c64abb3794edce29cbb1de50c93fa03a8229 so that the original "digest"/"signature"
// pair continues to be generated in a buggy form, while "correct_digest"/"correct_signature" are generated
// correctly.
//
// Jenkins should ignore "digest"/"signature" pair. Accepting it creates a vulnerability that allows
// the attacker to inject a fragment at the end of the json.
o
.
writeCanonical
(
new
OutputStreamWriter
(
new
TeeOutputStream
(
dos
,
sos
),
"UTF-8"
)).
close
();
// did the digest match? this is not a part of the signature validation, but if we have a bug in the c14n
// (which is more likely than someone tampering with update center), we can tell
String
computedDigest
=
new
String
(
Base64
.
encode
(
sha1
.
digest
()));
String
providedDigest
=
signature
.
optString
(
"correct_digest"
);
if
(
providedDigest
==
null
)
{
return
FormValidation
.
error
(
"No correct_digest parameter in "
+
name
+
". This metadata appears to be old."
);
}
if
(!
computedDigest
.
equalsIgnoreCase
(
providedDigest
))
{
String
msg
=
"Digest mismatch: computed="
+
computedDigest
+
" vs expected="
+
providedDigest
+
" in "
+
name
;
if
(
LOGGER
.
isLoggable
(
Level
.
SEVERE
))
{
LOGGER
.
severe
(
msg
);
LOGGER
.
severe
(
o
.
toString
(
2
));
}
return
FormValidation
.
error
(
msg
);
}
String
providedSignature
=
signature
.
getString
(
"correct_signature"
);
if
(!
sig
.
verify
(
Base64
.
decode
(
providedSignature
.
toCharArray
())))
{
return
FormValidation
.
error
(
"Signature in the update center doesn't match with the certificate in "
+
name
);
}
if
(
warning
!=
null
)
return
warning
;
return
FormValidation
.
ok
();
}
catch
(
GeneralSecurityException
e
)
{
return
FormValidation
.
error
(
e
,
"Signature verification failed in "
+
name
);
}
}
}
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
JSONSignatureValidator
.
class
.
getName
());
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
JSONSignatureValidator
.
class
.
getName
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录