Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
03647c7c
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
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,发现更多精彩内容 >>
提交
03647c7c
编写于
2月 28, 2015
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
差异文件
merged back the RC branch
上级
a29aef69
c49ab88a
变更
43
显示空白变更内容
内联
并排
Showing
43 changed file
with
7908 addition
and
58 deletion
+7908
-58
changelog.html
changelog.html
+4
-2
core/src/main/java/hudson/ClassicPluginStrategy.java
core/src/main/java/hudson/ClassicPluginStrategy.java
+17
-2
core/src/main/java/hudson/PluginManager.java
core/src/main/java/hudson/PluginManager.java
+9
-0
core/src/main/java/hudson/model/AbstractItem.java
core/src/main/java/hudson/model/AbstractItem.java
+12
-11
core/src/main/java/hudson/model/Api.java
core/src/main/java/hudson/model/Api.java
+9
-3
core/src/main/java/hudson/model/DownloadService.java
core/src/main/java/hudson/model/DownloadService.java
+27
-5
core/src/main/java/hudson/model/UpdateSite.java
core/src/main/java/hudson/model/UpdateSite.java
+1
-3
core/src/main/java/hudson/model/User.java
core/src/main/java/hudson/model/User.java
+40
-3
core/src/main/java/hudson/model/View.java
core/src/main/java/hudson/model/View.java
+10
-7
core/src/main/java/hudson/security/ACL.java
core/src/main/java/hudson/security/ACL.java
+15
-2
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
...main/java/hudson/security/HudsonPrivateSecurityRealm.java
+8
-0
core/src/main/java/jenkins/fun/Jenkins100K.java
core/src/main/java/jenkins/fun/Jenkins100K.java
+51
-0
core/src/main/java/jenkins/model/DownloadSettings.java
core/src/main/java/jenkins/model/DownloadSettings.java
+41
-1
core/src/main/java/jenkins/util/JSONSignatureValidator.java
core/src/main/java/jenkins/util/JSONSignatureValidator.java
+3
-0
core/src/main/java/jenkins/util/VirtualFile.java
core/src/main/java/jenkins/util/VirtualFile.java
+49
-5
core/src/main/java/jenkins/util/xml/FilteredFunctionContext.java
...c/main/java/jenkins/util/xml/FilteredFunctionContext.java
+77
-0
core/src/main/java/jenkins/util/xml/RestrictiveEntityResolver.java
...main/java/jenkins/util/xml/RestrictiveEntityResolver.java
+32
-0
core/src/main/java/jenkins/util/xml/XMLUtils.java
core/src/main/java/jenkins/util/xml/XMLUtils.java
+99
-0
core/src/main/resources/hudson/model/Messages.properties
core/src/main/resources/hudson/model/Messages.properties
+3
-0
core/src/main/resources/hudson/model/UpdateCenter/PageDecoratorImpl/footer.jelly
.../hudson/model/UpdateCenter/PageDecoratorImpl/footer.jelly
+2
-2
core/src/main/resources/jenkins/fun/Jenkins100K/index.jelly
core/src/main/resources/jenkins/fun/Jenkins100K/index.jelly
+72
-0
core/src/main/resources/jenkins/model/DownloadSettings/Warning/message.jelly
...rces/jenkins/model/DownloadSettings/Warning/message.jelly
+34
-0
core/src/main/resources/jenkins/model/DownloadSettings/Warning/message.properties
...jenkins/model/DownloadSettings/Warning/message.properties
+26
-0
core/src/main/resources/jenkins/model/DownloadSettings/config.groovy
...in/resources/jenkins/model/DownloadSettings/config.groovy
+3
-4
core/src/main/resources/jenkins/model/DownloadSettings/help-useBrowser.html
...urces/jenkins/model/DownloadSettings/help-useBrowser.html
+6
-2
core/src/test/java/hudson/PluginManagerTest.java
core/src/test/java/hudson/PluginManagerTest.java
+29
-2
core/src/test/java/jenkins/util/VirtualFileTest.java
core/src/test/java/jenkins/util/VirtualFileTest.java
+67
-0
core/src/test/java/jenkins/xml/XMLUtilsTest.java
core/src/test/java/jenkins/xml/XMLUtilsTest.java
+100
-0
debian/debian/changelog
debian/debian/changelog
+6
-0
pom.xml
pom.xml
+1
-0
test/pom.xml
test/pom.xml
+1
-1
test/src/test/java/hudson/model/AbstractItemSecurityTest.java
.../src/test/java/hudson/model/AbstractItemSecurityTest.java
+87
-0
test/src/test/java/hudson/model/ApiTest.java
test/src/test/java/hudson/model/ApiTest.java
+24
-1
test/src/test/java/hudson/model/DownloadService2Test.java
test/src/test/java/hudson/model/DownloadService2Test.java
+65
-0
test/src/test/java/hudson/model/DownloadServiceTest.java
test/src/test/java/hudson/model/DownloadServiceTest.java
+2
-0
test/src/test/java/hudson/model/UpdateCenter2Test.java
test/src/test/java/hudson/model/UpdateCenter2Test.java
+1
-1
test/src/test/java/hudson/security/HudsonPrivateSecurityRealm2Test.java
...java/hudson/security/HudsonPrivateSecurityRealm2Test.java
+118
-0
test/src/test/java/hudson/security/pages/SignupPage.java
test/src/test/java/hudson/security/pages/SignupPage.java
+65
-0
test/src/test/java/hudson/tasks/ArtifactArchiverTest.java
test/src/test/java/hudson/tasks/ArtifactArchiverTest.java
+29
-0
test/src/test/resources/hudson/model/hudson.tasks.Maven.MavenInstaller.json.html
.../hudson/model/hudson.tasks.Maven.MavenInstaller.json.html
+158
-0
test/src/test/resources/hudson/model/hudson.tools.JDKInstaller.json.html
...esources/hudson/model/hudson.tools.JDKInstaller.json.html
+6498
-0
war/pom.xml
war/pom.xml
+7
-1
war/src/main/webapp/images/100k.png
war/src/main/webapp/images/100k.png
+0
-0
未找到文件。
changelog.html
浏览文件 @
03647c7c
...
...
@@ -66,7 +66,10 @@ Upcoming changes</a>
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div
id=
"rc"
style=
"display:none;"
>
<!--=BEGIN=-->
<h3><a
name=
v1.600
>
What's new in 1.600
</a>
<!--=DATE=-->
</h3>
<h3><a
name=
v1.601
>
What's new in 1.601
</a>
<!--=DATE=-->
</h3>
<!--=RC-CHANGES=-->
</div>
<!--=END=-->
<h3><a
name=
v1.600
>
What's new in 1.600
</a>
(2015/02/28)
</h3>
<ul
class=
image
>
<li
class=
"rfe"
>
JDK auto-installer for Mac OSX
...
...
@@ -83,7 +86,6 @@ Upcoming changes</a>
Maven build step fail to launch mvn process when special chars are present in build variables.
(
<a
href=
"https://issues.jenkins-ci.org/browse/JENKINS-26684"
>
issue 26684
</a>
)
</ul>
</div>
<!--=END=-->
<h3><a
name=
v1.599
>
What's new in 1.599
</a>
(2015/02/16)
</h3>
<ul
class=
image
>
<li
class=
bug
>
...
...
core/src/main/java/hudson/ClassicPluginStrategy.java
浏览文件 @
03647c7c
...
...
@@ -66,6 +66,7 @@ import java.util.Collections;
import
java.util.Enumeration
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Vector
;
import
java.util.jar.Attributes
;
import
java.util.jar.JarFile
;
...
...
@@ -303,13 +304,19 @@ public class ClassicPluginStrategy implements PluginStrategy {
// don't fix the dependency for yourself, or else we'll have a cycle
String
yourName
=
atts
.
getValue
(
"Short-Name"
);
if
(
shortName
.
equals
(
yourName
))
return
;
if
(
BREAK_CYCLES
.
contains
(
yourName
+
'/'
+
shortName
))
{
LOGGER
.
log
(
Level
.
FINE
,
"skipping implicit dependency {0} → {1}"
,
new
Object
[]
{
yourName
,
shortName
});
return
;
}
// some earlier versions of maven-hpi-plugin apparently puts "null" as a literal in Hudson-Version. watch out for them.
String
jenkinsVersion
=
atts
.
getValue
(
"Jenkins-Version"
);
if
(
jenkinsVersion
==
null
)
jenkinsVersion
=
atts
.
getValue
(
"Hudson-Version"
);
if
(
jenkinsVersion
==
null
||
jenkinsVersion
.
equals
(
"null"
)
||
new
VersionNumber
(
jenkinsVersion
).
compareTo
(
splitWhen
)
<=
0
)
optionalDependencies
.
add
(
new
PluginWrapper
.
Dependency
(
shortName
+
':'
+
requireVersion
));
if
(
jenkinsVersion
==
null
||
jenkinsVersion
.
equals
(
"null"
)
||
new
VersionNumber
(
jenkinsVersion
).
compareTo
(
splitWhen
)
<=
0
)
{
optionalDependencies
.
add
(
new
PluginWrapper
.
Dependency
(
shortName
+
':'
+
requireVersion
));
LOGGER
.
log
(
Level
.
FINE
,
"adding implicit dependency {0} → {1} because of {2}"
,
new
Object
[]
{
yourName
,
shortName
,
jenkinsVersion
});
}
}
}
...
...
@@ -330,6 +337,14 @@ public class ClassicPluginStrategy implements PluginStrategy {
new
DetachedPlugin
(
"junit"
,
"1.577.*"
,
"1.0"
)
);
/** Implicit dependencies that are known to be unnecessary and which must be cut out to prevent a dependency cycle among bundled plugins. */
private
static
final
Set
<
String
>
BREAK_CYCLES
=
new
HashSet
<
String
>(
Arrays
.
asList
(
"script-security/matrix-auth"
,
"script-security/windows-slaves"
,
"script-security/antisamy-markup-formatter"
,
"script-security/matrix-project"
));
/**
* Computes the classloader that takes the class masking into account.
*
...
...
core/src/main/java/hudson/PluginManager.java
浏览文件 @
03647c7c
...
...
@@ -51,6 +51,8 @@ import jenkins.RestartRequiredException;
import
jenkins.YesNoMaybe
;
import
jenkins.model.Jenkins
;
import
jenkins.util.io.OnMaster
;
import
jenkins.util.xml.RestrictiveEntityResolver
;
import
net.sf.json.JSONArray
;
import
net.sf.json.JSONObject
;
import
org.apache.commons.fileupload.FileItem
;
...
...
@@ -109,6 +111,7 @@ import java.util.jar.Manifest;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
org.xml.sax.Attributes
;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
org.xml.sax.helpers.DefaultHandler
;
...
...
@@ -1045,6 +1048,12 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
requestedPlugins
.
put
(
shortName
,
requested
);
}
}
@Override
public
InputSource
resolveEntity
(
String
publicId
,
String
systemId
)
throws
IOException
,
SAXException
{
return
RestrictiveEntityResolver
.
INSTANCE
.
resolveEntity
(
publicId
,
systemId
);
}
});
}
catch
(
SAXException
x
)
{
throw
new
IOException
(
"Failed to parse XML"
,
x
);
...
...
core/src/main/java/hudson/model/AbstractItem.java
浏览文件 @
03647c7c
...
...
@@ -45,6 +45,8 @@ import jenkins.model.DirectlyModifiableTopLevelItemGroup;
import
jenkins.model.Jenkins
;
import
jenkins.security.NotReallyRoleSensitiveCallable
;
import
org.acegisecurity.Authentication
;
import
jenkins.util.xml.XMLUtils
;
import
org.apache.tools.ant.taskdefs.Copy
;
import
org.apache.tools.ant.types.FileSet
;
import
org.kohsuke.stapler.WebMethod
;
...
...
@@ -67,12 +69,11 @@ import org.kohsuke.stapler.HttpDeletable;
import
org.kohsuke.args4j.Argument
;
import
org.kohsuke.args4j.CmdLineException
;
import
org.kohsuke.stapler.interceptor.RequirePOST
;
import
org.xml.sax.SAXException
;
import
javax.servlet.ServletException
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.Transformer
;
import
javax.xml.transform.TransformerException
;
import
javax.xml.transform.TransformerFactory
;
import
javax.xml.transform.stream.StreamResult
;
import
javax.xml.transform.stream.StreamSource
;
...
...
@@ -627,25 +628,24 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
}
/**
* Updates Job by its XML definition.
* Updates an Item by its XML definition.
* @param source source of the Item's new definition.
* The source should be either a <code>StreamSource</code> or a <code>SAXSource</code>, other
* sources may not be handled.
* @since 1.473
*/
public
void
updateByXml
(
Source
source
)
throws
IOException
{
checkPermission
(
CONFIGURE
);
XmlFile
configXmlFile
=
getConfigFile
();
AtomicFileWriter
out
=
new
AtomicFileWriter
(
configXmlFile
.
getFile
());
final
AtomicFileWriter
out
=
new
AtomicFileWriter
(
configXmlFile
.
getFile
());
try
{
try
{
// this allows us to use UTF-8 for storing data,
// plus it checks any well-formedness issue in the submitted
// data
Transformer
t
=
TransformerFactory
.
newInstance
()
.
newTransformer
();
t
.
transform
(
source
,
new
StreamResult
(
out
));
XMLUtils
.
safeTransform
(
source
,
new
StreamResult
(
out
));
out
.
close
();
}
catch
(
TransformerException
e
)
{
throw
new
IOException
(
"Failed to persist config.xml"
,
e
);
}
catch
(
SAXException
e
)
{
throw
new
IOException
(
"Failed to persist config.xml"
,
e
);
}
// try to reflect the changes by reloading
...
...
@@ -667,6 +667,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
// if everything went well, commit this new version
out
.
commit
();
SaveableListener
.
fireOnChange
(
this
,
getConfigFile
());
}
finally
{
out
.
abort
();
// don't leave anything behind
}
...
...
core/src/main/java/hudson/model/Api.java
浏览文件 @
03647c7c
...
...
@@ -24,6 +24,7 @@
package
hudson.model
;
import
hudson.ExtensionList
;
import
jenkins.util.xml.FilteredFunctionContext
;
import
jenkins.model.Jenkins
;
import
jenkins.security.SecureRequester
;
...
...
@@ -32,6 +33,7 @@ import org.dom4j.Document;
import
org.dom4j.DocumentException
;
import
org.dom4j.DocumentFactory
;
import
org.dom4j.Element
;
import
org.dom4j.XPath
;
import
org.dom4j.io.SAXReader
;
import
org.dom4j.io.XMLWriter
;
import
org.kohsuke.stapler.QueryParameter
;
...
...
@@ -107,14 +109,16 @@ public class Api extends AbstractModelObject {
p
.
writeTo
(
bean
,
pruner
,
Flavor
.
XML
.
createDataWriter
(
bean
,
sw
));
// apply XPath
FilteredFunctionContext
functionContext
=
new
FilteredFunctionContext
();
Object
result
;
try
{
Document
dom
=
new
SAXReader
().
read
(
new
StringReader
(
sw
.
toString
()));
// apply exclusions
if
(
excludes
!=
null
)
{
for
(
String
exclude
:
excludes
)
{
List
<
org
.
dom4j
.
Node
>
list
=
(
List
<
org
.
dom4j
.
Node
>)
dom
.
selectNodes
(
exclude
);
XPath
xExclude
=
dom
.
createXPath
(
exclude
);
xExclude
.
setFunctionContext
(
functionContext
);
List
<
org
.
dom4j
.
Node
>
list
=
(
List
<
org
.
dom4j
.
Node
>)
xExclude
.
selectNodes
(
dom
);
for
(
org
.
dom4j
.
Node
n
:
list
)
{
Element
parent
=
n
.
getParent
();
if
(
parent
!=
null
)
...
...
@@ -126,7 +130,9 @@ public class Api extends AbstractModelObject {
if
(
xpath
==
null
)
{
result
=
dom
;
}
else
{
List
list
=
dom
.
selectNodes
(
xpath
);
XPath
comp
=
dom
.
createXPath
(
xpath
);
comp
.
setFunctionContext
(
functionContext
);
List
list
=
comp
.
selectNodes
(
dom
);
if
(
wrapper
!=
null
)
{
Element
root
=
DocumentFactory
.
getInstance
().
createElement
(
wrapper
);
for
(
Object
o
:
list
)
{
...
...
core/src/main/java/hudson/model/DownloadService.java
浏览文件 @
03647c7c
...
...
@@ -66,7 +66,7 @@ public class DownloadService extends PageDecorator {
* Builds up an HTML fragment that starts all the download jobs.
*/
public
String
generateFragment
()
{
if
(!
DownloadSettings
.
get
().
isUseBrowser
())
{
if
(!
DownloadSettings
.
usePostBack
())
{
return
""
;
}
if
(
neverUpdate
)
return
""
;
...
...
@@ -170,6 +170,30 @@ public class DownloadService extends PageDecorator {
}
}
/**
* Loads JSON from a JSON-with-{@code postMessage} URL.
* @param src a URL to a JSON HTML file (typically including {@code id} and {@code version} query parameters)
* @return the embedded JSON text
* @throws IOException if either downloading or processing failed
*/
@Restricted
(
NoExternalUse
.
class
)
public
static
String
loadJSONHTML
(
URL
src
)
throws
IOException
{
InputStream
is
=
ProxyConfiguration
.
open
(
src
).
getInputStream
();
try
{
String
jsonp
=
IOUtils
.
toString
(
is
,
"UTF-8"
);
String
preamble
=
"window.parent.postMessage(JSON.stringify("
;
int
start
=
jsonp
.
indexOf
(
preamble
);
int
end
=
jsonp
.
lastIndexOf
(
"),'*');"
);
if
(
start
>=
0
&&
end
>
start
)
{
return
jsonp
.
substring
(
start
+
preamble
.
length
(),
end
).
trim
();
}
else
{
throw
new
IOException
(
"Could not find JSON in "
+
src
);
}
}
finally
{
is
.
close
();
}
}
/**
* Represents a periodically updated JSON data file obtained from a remote URL.
*
...
...
@@ -283,9 +307,7 @@ public class DownloadService extends PageDecorator {
* This is where the browser sends us the data.
*/
public
void
doPostBack
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
{
if
(!
DownloadSettings
.
get
().
isUseBrowser
())
{
throw
new
IOException
(
"not allowed"
);
}
DownloadSettings
.
checkPostBackAccess
();
long
dataTimestamp
=
System
.
currentTimeMillis
();
due
=
dataTimestamp
+
getInterval
();
// success or fail, don't try too often
...
...
@@ -317,7 +339,7 @@ public class DownloadService extends PageDecorator {
@Restricted
(
NoExternalUse
.
class
)
public
FormValidation
updateNow
()
throws
IOException
{
return
load
(
loadJSON
(
new
URL
(
getUrl
()
+
"
?id="
+
URLEncoder
.
encode
(
getId
(),
"UTF-8"
)
+
"&version="
+
URLEncoder
.
encode
(
Jenkins
.
VERSION
,
"UTF-8"
))),
System
.
currentTimeMillis
());
return
load
(
loadJSON
HTML
(
new
URL
(
getUrl
()
+
".html
?id="
+
URLEncoder
.
encode
(
getId
(),
"UTF-8"
)
+
"&version="
+
URLEncoder
.
encode
(
Jenkins
.
VERSION
,
"UTF-8"
))),
System
.
currentTimeMillis
());
}
/**
...
...
core/src/main/java/hudson/model/UpdateSite.java
浏览文件 @
03647c7c
...
...
@@ -174,9 +174,7 @@ public class UpdateSite {
* This is the endpoint that receives the update center data file from the browser.
*/
public
FormValidation
doPostBack
(
StaplerRequest
req
)
throws
IOException
,
GeneralSecurityException
{
if
(!
DownloadSettings
.
get
().
isUseBrowser
())
{
throw
new
IOException
(
"not allowed"
);
}
DownloadSettings
.
checkPostBackAccess
();
return
updateData
(
IOUtils
.
toString
(
req
.
getInputStream
(),
"UTF-8"
),
true
);
}
...
...
core/src/main/java/hudson/model/User.java
浏览文件 @
03647c7c
...
...
@@ -35,6 +35,7 @@ import hudson.security.Permission;
import
hudson.security.SecurityRealm
;
import
hudson.security.UserMayOrMayNotExistException
;
import
hudson.util.FormApply
;
import
hudson.util.FormValidation
;
import
hudson.util.RunList
;
import
hudson.util.XStream2
;
import
jenkins.model.IdStrategy
;
...
...
@@ -110,6 +111,17 @@ import javax.annotation.Nullable;
@ExportedBean
public
class
User
extends
AbstractModelObject
implements
AccessControlled
,
DescriptorByNameOwner
,
Saveable
,
Comparable
<
User
>,
ModelObjectWithContextMenu
{
/**
* The username of the 'unknown' user used to avoid null user references.
*/
private
static
final
String
UKNOWN_USERNAME
=
"unknown"
;
/**
* These usernames should not be used by real users logging into Jenkins. Therefore, we prevent
* users with these names from being saved.
*/
private
static
final
String
[]
ILLEGAL_PERSISTED_USERNAMES
=
new
String
[]{
ACL
.
ANONYMOUS_USERNAME
,
ACL
.
SYSTEM_USERNAME
,
UKNOWN_USERNAME
};
private
transient
final
String
id
;
private
volatile
String
fullName
;
...
...
@@ -320,7 +332,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
* This is used to avoid null {@link User} instance.
*/
public
static
@Nonnull
User
getUnknown
()
{
return
get
(
"unknown"
);
return
get
(
UKNOWN_USERNAME
);
}
/**
...
...
@@ -642,10 +654,35 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
return
new
File
(
Jenkins
.
getInstance
().
getRootDir
(),
"users"
);
}
/**
* Is the ID allowed? Some are prohibited for security reasons. See SECURITY-166.
* <p/>
* Note that this is only enforced when saving. These users are often created
* via the constructor (and even listed on /asynchPeople), but our goal is to
* prevent anyone from logging in as these users. Therefore, we prevent
* saving a User with one of these ids.
*
* @return true if the username or fullname is valid
* @since 1.600
*/
public
static
boolean
isIdOrFullnameAllowed
(
String
id
)
{
for
(
String
invalidId
:
ILLEGAL_PERSISTED_USERNAMES
)
{
if
(
id
.
equalsIgnoreCase
(
invalidId
))
return
false
;
}
return
true
;
}
/**
* Save the settings to a file.
*/
public
synchronized
void
save
()
throws
IOException
{
public
synchronized
void
save
()
throws
IOException
,
FormValidation
{
if
(!
isIdOrFullnameAllowed
(
id
))
{
throw
FormValidation
.
error
(
Messages
.
User_IllegalUsername
(
id
));
}
if
(!
isIdOrFullnameAllowed
(
fullName
))
{
throw
FormValidation
.
error
(
Messages
.
User_IllegalFullname
(
fullName
));
}
if
(
BulkChange
.
contains
(
this
))
return
;
getConfigFile
().
write
(
this
);
SaveableListener
.
fireOnChange
(
this
,
getConfigFile
());
...
...
core/src/main/java/hudson/model/View.java
浏览文件 @
03647c7c
...
...
@@ -58,6 +58,8 @@ import hudson.widgets.Widget;
import
jenkins.model.Jenkins
;
import
jenkins.model.ModelObjectWithChildren
;
import
jenkins.util.ProgressiveRendering
;
import
jenkins.util.xml.XMLUtils
;
import
net.sf.json.JSON
;
import
net.sf.json.JSONArray
;
import
net.sf.json.JSONObject
;
...
...
@@ -75,9 +77,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.Transformer
;
import
javax.xml.transform.TransformerException
;
import
javax.xml.transform.TransformerFactory
;
import
javax.xml.transform.stream.StreamResult
;
import
javax.xml.transform.stream.StreamSource
;
import
java.io.BufferedInputStream
;
...
...
@@ -106,6 +106,7 @@ import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import
static
jenkins
.
model
.
Jenkins
.*;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.xml.sax.SAXException
;
/**
* Encapsulates the rendering of the list of {@link TopLevelItem}s
...
...
@@ -1063,7 +1064,10 @@ public abstract class View extends AbstractModelObject implements AccessControll
}
/**
* Updates Job by its XML definition.
* Updates the View with the new XML definition.
* @param source source of the Item's new definition.
* The source should be either a <code>StreamSource</code> or <code>SAXSource</code>, other sources
* may not be handled.
*/
public
void
updateByXml
(
Source
source
)
throws
IOException
{
checkPermission
(
CONFIGURE
);
...
...
@@ -1072,13 +1076,12 @@ public abstract class View extends AbstractModelObject implements AccessControll
// this allows us to use UTF-8 for storing data,
// plus it checks any well-formedness issue in the submitted
// data
Transformer
t
=
TransformerFactory
.
newInstance
()
.
newTransformer
();
t
.
transform
(
source
,
new
StreamResult
(
out
));
XMLUtils
.
safeTransform
(
source
,
new
StreamResult
(
out
));
out
.
close
();
}
catch
(
TransformerException
e
)
{
throw
new
IOException
(
"Failed to persist configuration.xml"
,
e
);
}
catch
(
SAXException
e
)
{
throw
new
IOException
(
"Failed to persist configuration.xml"
,
e
);
}
// try to reflect the changes by reloading
...
...
core/src/main/java/hudson/security/ACL.java
浏览文件 @
03647c7c
...
...
@@ -35,6 +35,8 @@ import org.acegisecurity.context.SecurityContextHolder;
import
org.acegisecurity.providers.UsernamePasswordAuthenticationToken
;
import
org.acegisecurity.acls.sid.PrincipalSid
;
import
org.acegisecurity.acls.sid.Sid
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
/**
* Gate-keeper that controls access to Hudson's model objects.
...
...
@@ -95,23 +97,34 @@ public abstract class ACL {
}
};
/**
* The username for the anonymous user
*/
@Restricted
(
NoExternalUse
.
class
)
public
static
final
String
ANONYMOUS_USERNAME
=
"anonymous"
;
/**
* {@link Sid} that represents the anonymous unauthenticated users.
* <p>
* {@link HudsonFilter} sets this up, so this sid remains the same
* regardless of the current {@link SecurityRealm} in use.
*/
public
static
final
Sid
ANONYMOUS
=
new
PrincipalSid
(
"anonymous"
);
public
static
final
Sid
ANONYMOUS
=
new
PrincipalSid
(
ANONYMOUS_USERNAME
);
protected
static
final
Sid
[]
AUTOMATIC_SIDS
=
new
Sid
[]{
EVERYONE
,
ANONYMOUS
};
/**
* The username for the system user
*/
@Restricted
(
NoExternalUse
.
class
)
public
static
final
String
SYSTEM_USERNAME
=
"SYSTEM"
;
/**
* {@link Sid} that represents the Hudson itself.
* <p>
* This is used when Hudson is performing computation for itself, instead
* of acting on behalf of an user, such as doing builds.
*/
public
static
final
Authentication
SYSTEM
=
new
UsernamePasswordAuthenticationToken
(
"SYSTEM"
,
"SYSTEM"
);
public
static
final
Authentication
SYSTEM
=
new
UsernamePasswordAuthenticationToken
(
SYSTEM_USERNAME
,
"SYSTEM"
);
/**
* Changes the {@link Authentication} associated with the current thread
...
...
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
浏览文件 @
03647c7c
...
...
@@ -337,6 +337,14 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
if
(
si
.
email
==
null
||
!
si
.
email
.
contains
(
"@"
))
si
.
errorMessage
=
Messages
.
HudsonPrivateSecurityRealm_CreateAccount_InvalidEmailAddress
();
if
(!
User
.
isIdOrFullnameAllowed
(
si
.
username
))
{
si
.
errorMessage
=
hudson
.
model
.
Messages
.
User_IllegalUsername
(
si
.
username
);
}
if
(!
User
.
isIdOrFullnameAllowed
(
si
.
fullname
))
{
si
.
errorMessage
=
hudson
.
model
.
Messages
.
User_IllegalFullname
(
si
.
fullname
);
}
if
(
si
.
errorMessage
!=
null
)
{
// failed. ask the user to try again.
req
.
setAttribute
(
"data"
,
si
);
...
...
core/src/main/java/jenkins/fun/Jenkins100K.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.fun
;
import
hudson.Extension
;
import
hudson.model.UnprotectedRootAction
;
/**
* Easter egg for Jenkins 100K certificate.
*
* @author Kohsuke Kawaguchi
* @since 1.600
*/
@Extension
(
ordinal
=-
100
)
public
class
Jenkins100K
implements
UnprotectedRootAction
{
@Override
public
String
getIconFileName
()
{
return
"/images/headshot.png"
;
}
@Override
public
String
getDisplayName
()
{
return
"Jenkins 100K"
;
}
@Override
public
String
getUrlName
()
{
return
"jenkins100k"
;
}
}
core/src/main/java/jenkins/model/DownloadSettings.java
浏览文件 @
03647c7c
...
...
@@ -25,6 +25,8 @@
package
jenkins.model
;
import
hudson.Extension
;
import
hudson.Main
;
import
hudson.model.AdministrativeMonitor
;
import
hudson.model.AsyncPeriodicWork
;
import
hudson.model.DownloadService
;
import
hudson.model.TaskListener
;
...
...
@@ -32,6 +34,7 @@ import hudson.model.UpdateSite;
import
hudson.util.FormValidation
;
import
java.io.IOException
;
import
net.sf.json.JSONObject
;
import
org.acegisecurity.AccessDeniedException
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.kohsuke.stapler.HttpResponse
;
...
...
@@ -49,7 +52,7 @@ import org.kohsuke.stapler.StaplerRequest;
return
Jenkins
.
getInstance
().
getInjector
().
getInstance
(
DownloadSettings
.
class
);
}
private
boolean
useBrowser
=
true
;
// historical default, not necessarily recommended
private
boolean
useBrowser
=
false
;
public
DownloadSettings
()
{
load
();
...
...
@@ -69,6 +72,21 @@ import org.kohsuke.stapler.StaplerRequest;
save
();
}
@Override
public
GlobalConfigurationCategory
getCategory
()
{
return
GlobalConfigurationCategory
.
get
(
GlobalConfigurationCategory
.
Security
.
class
);
}
public
static
boolean
usePostBack
()
{
return
get
().
isUseBrowser
()
&&
Jenkins
.
getInstance
().
hasPermission
(
Jenkins
.
ADMINISTER
);
}
public
static
void
checkPostBackAccess
()
throws
AccessDeniedException
{
if
(!
get
().
isUseBrowser
())
{
throw
new
AccessDeniedException
(
"browser-based download disabled"
);
}
Jenkins
.
getInstance
().
checkPermission
(
Jenkins
.
ADMINISTER
);
}
@Extension
public
static
final
class
DailyCheck
extends
AsyncPeriodicWork
{
public
DailyCheck
()
{
...
...
@@ -79,10 +97,24 @@ import org.kohsuke.stapler.StaplerRequest;
return
DAY
;
}
@Override
public
long
getInitialDelay
()
{
return
Main
.
isUnitTest
?
DAY
:
0
;
}
@Override
protected
void
execute
(
TaskListener
listener
)
throws
IOException
,
InterruptedException
{
if
(
get
().
isUseBrowser
())
{
return
;
}
boolean
due
=
false
;
for
(
UpdateSite
site
:
Jenkins
.
getInstance
().
getUpdateCenter
().
getSites
())
{
if
(
site
.
isDue
())
{
due
=
true
;
break
;
}
}
if
(!
due
)
{
return
;
}
HttpResponse
rsp
=
Jenkins
.
getInstance
().
getPluginManager
().
doCheckUpdatesServer
();
if
(
rsp
instanceof
FormValidation
)
{
listener
.
error
(((
FormValidation
)
rsp
).
renderHtml
());
...
...
@@ -91,4 +123,12 @@ import org.kohsuke.stapler.StaplerRequest;
}
@Extension
public
static
final
class
Warning
extends
AdministrativeMonitor
{
@Override
public
boolean
isActivated
()
{
return
DownloadSettings
.
get
().
isUseBrowser
();
}
}
}
core/src/main/java/jenkins/util/JSONSignatureValidator.java
浏览文件 @
03647c7c
...
...
@@ -135,6 +135,9 @@ public class JSONSignatureValidator {
// which isn't useful at all
Set
<
TrustAnchor
>
anchors
=
new
HashSet
<
TrustAnchor
>();
// CertificateUtil.getDefaultRootCAs();
Jenkins
j
=
Jenkins
.
getInstance
();
if
(
j
==
null
)
{
return
anchors
;
}
for
(
String
cert
:
(
Set
<
String
>)
j
.
servletContext
.
getResourcePaths
(
"/WEB-INF/update-center-rootCAs"
))
{
if
(
cert
.
endsWith
(
"/"
)
||
cert
.
endsWith
(
".txt"
))
{
continue
;
// skip directories also any text files that are meant to be documentation
...
...
core/src/main/java/jenkins/util/VirtualFile.java
浏览文件 @
03647c7c
...
...
@@ -33,12 +33,15 @@ import hudson.util.DirScanner;
import
hudson.util.FileVisitor
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Serializable
;
import
java.net.URI
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
javax.annotation.Nonnull
;
import
jenkins.MasterToSlaveFileCallable
;
...
...
@@ -209,12 +212,14 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
* @return a wrapper
*/
public
static
VirtualFile
forFile
(
final
File
f
)
{
return
new
FileVF
(
f
);
return
new
FileVF
(
f
,
f
);
}
private
static
final
class
FileVF
extends
VirtualFile
{
private
final
File
f
;
FileVF
(
File
f
)
{
private
final
File
root
;
FileVF
(
File
f
,
File
root
)
{
this
.
f
=
f
;
this
.
root
=
root
;
}
@Override
public
String
getName
()
{
return
f
.
getName
();
...
...
@@ -223,46 +228,85 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
return
f
.
toURI
();
}
@Override
public
VirtualFile
getParent
()
{
return
forFile
(
f
.
getParentFile
()
);
return
new
FileVF
(
f
.
getParentFile
(),
root
);
}
@Override
public
boolean
isDirectory
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
false
;
}
return
f
.
isDirectory
();
}
@Override
public
boolean
isFile
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
false
;
}
return
f
.
isFile
();
}
@Override
public
boolean
exists
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
false
;
}
return
f
.
exists
();
}
@Override
public
VirtualFile
[]
list
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
new
VirtualFile
[
0
];
}
File
[]
kids
=
f
.
listFiles
();
if
(
kids
==
null
)
{
return
new
VirtualFile
[
0
];
}
VirtualFile
[]
vfs
=
new
VirtualFile
[
kids
.
length
];
for
(
int
i
=
0
;
i
<
kids
.
length
;
i
++)
{
vfs
[
i
]
=
forFile
(
kids
[
i
]
);
vfs
[
i
]
=
new
FileVF
(
kids
[
i
],
root
);
}
return
vfs
;
}
@Override
public
String
[]
list
(
String
glob
)
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
new
String
[
0
];
}
return
new
Scanner
(
glob
).
invoke
(
f
,
null
);
}
@Override
public
VirtualFile
child
(
String
name
)
{
return
forFile
(
new
File
(
f
,
name
)
);
return
new
FileVF
(
new
File
(
f
,
name
),
root
);
}
@Override
public
long
length
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
0
;
}
return
f
.
length
();
}
@Override
public
long
lastModified
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
0
;
}
return
f
.
lastModified
();
}
@Override
public
boolean
canRead
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
return
false
;
}
return
f
.
canRead
();
}
@Override
public
InputStream
open
()
throws
IOException
{
if
(
isIllegalSymlink
())
{
throw
new
FileNotFoundException
(
f
.
getPath
());
}
return
new
FileInputStream
(
f
);
}
private
boolean
isIllegalSymlink
()
{
// TODO JENKINS-26838
try
{
String
myPath
=
f
.
getCanonicalPath
();
String
rootPath
=
root
.
getCanonicalPath
();
if
(!
myPath
.
equals
(
rootPath
)
&&
!
myPath
.
startsWith
(
rootPath
+
File
.
separatorChar
))
{
return
true
;
}
}
catch
(
IOException
x
)
{
Logger
.
getLogger
(
VirtualFile
.
class
.
getName
()).
log
(
Level
.
FINE
,
"could not determine symlink status of "
+
f
,
x
);
}
return
false
;
}
}
/**
...
...
core/src/main/java/jenkins/util/xml/FilteredFunctionContext.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.util.xml
;
import
org.jaxen.Function
;
import
org.jaxen.FunctionContext
;
import
org.jaxen.UnresolvableException
;
import
org.jaxen.XPathFunctionContext
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.Locale
;
import
java.util.Set
;
/**
* {@link org.jaxen.FunctionContext} that removes some {@link org.dom4j.XPath}
* function names that are deemed bad as user input.
*
* @author Robert Sandell <rsandell@cloudbees.com>.
* @see org.jaxen.FunctionContext
* @see org.dom4j.XPath
* @see hudson.model.Api
*/
@Restricted
(
NoExternalUse
.
class
)
public
class
FilteredFunctionContext
implements
FunctionContext
{
/**
* Default set of "bad" function names.
*/
private
static
final
Set
<
String
>
DEFAULT_ILLEGAL_FUNCTIONS
=
Collections
.
unmodifiableSet
(
new
HashSet
<
String
>(
Arrays
.
asList
(
"document"
)
));
private
final
FunctionContext
base
;
private
final
Set
<
String
>
illegalFunctions
;
public
FilteredFunctionContext
(
Set
<
String
>
illegalFunctions
)
{
this
.
illegalFunctions
=
illegalFunctions
;
base
=
XPathFunctionContext
.
getInstance
();
}
public
FilteredFunctionContext
()
{
this
(
DEFAULT_ILLEGAL_FUNCTIONS
);
}
@Override
public
Function
getFunction
(
String
namespaceURI
,
String
prefix
,
String
localName
)
throws
UnresolvableException
{
if
(
localName
!=
null
&&
illegalFunctions
.
contains
(
localName
.
toLowerCase
(
Locale
.
ENGLISH
)))
{
throw
new
UnresolvableException
(
"Illegal function: "
+
localName
);
}
return
base
.
getFunction
(
namespaceURI
,
prefix
,
localName
);
}
}
core/src/main/java/jenkins/util/xml/RestrictiveEntityResolver.java
0 → 100644
浏览文件 @
03647c7c
package
jenkins.util.xml
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.xml.sax.EntityResolver
;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
java.io.IOException
;
/**
* An EntityResolver that will fail to resolve any entities.
* Useful in preventing External XML Entity injection attacks.
*/
@Restricted
(
NoExternalUse
.
class
)
public
final
class
RestrictiveEntityResolver
implements
EntityResolver
{
public
final
static
RestrictiveEntityResolver
INSTANCE
=
new
RestrictiveEntityResolver
();
private
RestrictiveEntityResolver
()
{
// prevent multiple instantiation.
super
();
}
/**
* Throws a SAXException if this tried to resolve any entity.
*/
@Override
public
InputSource
resolveEntity
(
String
publicId
,
String
systemId
)
throws
SAXException
,
IOException
{
throw
new
SAXException
(
"Refusing to resolve entity with publicId("
+
publicId
+
") and systemId ("
+
systemId
+
")"
);
}
}
core/src/main/java/jenkins/util/xml/XMLUtils.java
0 → 100644
浏览文件 @
03647c7c
package
jenkins.util.xml
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
org.xml.sax.XMLReader
;
import
org.xml.sax.helpers.XMLReaderFactory
;
import
java.util.logging.Level
;
import
java.util.logging.LogManager
;
import
java.util.logging.Logger
;
import
javax.annotation.Nonnull
;
import
javax.xml.XMLConstants
;
import
javax.xml.transform.Result
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.Transformer
;
import
javax.xml.transform.TransformerException
;
import
javax.xml.transform.TransformerFactory
;
import
javax.xml.transform.sax.SAXSource
;
import
javax.xml.transform.sax.SAXTransformerFactory
;
/**
* Utilities useful when working with various XML types.
*/
@Restricted
(
NoExternalUse
.
class
)
public
final
class
XMLUtils
{
private
final
static
Logger
LOGGER
=
LogManager
.
getLogManager
().
getLogger
(
XMLUtils
.
class
.
getName
());
private
final
static
String
DISABLED_PROPERTY_NAME
=
XMLUtils
.
class
.
getName
()
+
".disableXXEPrevention"
;
/**
* Transform the source to the output in a manner that is protected against XXE attacks.
* If the transform can not be completed safely then an IOException is thrown.
* Note - to turn off safety set the system property <code>disableXXEPrevention</code> to <code>true</code>.
* @param source The XML input to transform. - This should be a <code>StreamSource</code> or a
* <code>SAXSource</code> in order to be able to prevent XXE attacks.
* @param out The Result of transforming the <code>source</code>.
*/
public
static
void
safeTransform
(
@Nonnull
Source
source
,
@Nonnull
Result
out
)
throws
TransformerException
,
SAXException
{
InputSource
src
=
SAXSource
.
sourceToInputSource
(
source
);
if
(
src
!=
null
)
{
SAXTransformerFactory
stFactory
=
(
SAXTransformerFactory
)
TransformerFactory
.
newInstance
();
stFactory
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
true
);
XMLReader
xmlReader
=
XMLReaderFactory
.
createXMLReader
();
try
{
xmlReader
.
setFeature
(
"http://xml.org/sax/features/external-general-entities"
,
false
);
}
catch
(
SAXException
ignored
)
{
/* ignored */
}
try
{
xmlReader
.
setFeature
(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
}
catch
(
SAXException
ignored
)
{
/* ignored */
}
// defend against XXE
// the above features should strip out entities - however the feature may not be supported depending
// on the xml implementation used and this is out of our control.
// So add a fallback plan if all else fails.
xmlReader
.
setEntityResolver
(
RestrictiveEntityResolver
.
INSTANCE
);
SAXSource
saxSource
=
new
SAXSource
(
xmlReader
,
src
);
_transform
(
saxSource
,
out
);
}
else
{
// for some reason we could not convert source
// this applies to DOMSource and StAXSource - and possibly 3rd party implementations...
// a DOMSource can already be compromised as it is parsed by the time it gets to us.
if
(
Boolean
.
getBoolean
(
DISABLED_PROPERTY_NAME
))
{
LOGGER
.
log
(
Level
.
WARNING
,
"XML external entity (XXE) prevention has been disabled by the system "
+
"property {0}=true Your system may be vulnerable to XXE attacks."
,
DISABLED_PROPERTY_NAME
);
if
(
LOGGER
.
isLoggable
(
Level
.
FINE
))
{
LOGGER
.
log
(
Level
.
FINE
,
"Caller stack trace: "
,
new
Exception
(
"XXE Prevention caller history"
));
}
_transform
(
source
,
out
);
}
else
{
throw
new
TransformerException
(
"Could not convert source of type "
+
source
.
getClass
()
+
" and "
+
"XXEPrevention is enabled."
);
}
}
}
/**
* potentially unsafe XML transformation.
* @param source The XML input to transform.
* @param out The Result of transforming the <code>source</code>.
*/
private
static
void
_transform
(
Source
source
,
Result
out
)
throws
TransformerException
{
TransformerFactory
factory
=
TransformerFactory
.
newInstance
();
factory
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
true
);
// this allows us to use UTF-8 for storing data,
// plus it checks any well-formedness issue in the submitted data.
Transformer
t
=
factory
.
newTransformer
();
t
.
transform
(
source
,
out
);
}
}
core/src/main/resources/hudson/model/Messages.properties
浏览文件 @
03647c7c
...
...
@@ -356,3 +356,6 @@ Jenkins.CheckDisplayName.DisplayNameNotUniqueWarning=The display name, "{0}", is
Jenkins.NotAllowedName
=
"{0}"
is not allowed name
Jenkins.IsRestarting
=
Jenkins is restarting
User.IllegalUsername
=
"{0}"
is prohibited as a username for security reasons.
User.IllegalFullname
=
"{0}"
is prohibited as a full name for security reasons.
core/src/main/resources/hudson/model/UpdateCenter/PageDecoratorImpl/footer.jelly
浏览文件 @
03647c7c
...
...
@@ -31,8 +31,8 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<j:invokeStatic var="
ds" className="jenkins.model.DownloadSettings" method="get
"/>
<j:if test="${
ds.useBrowser
}">
<j:invokeStatic var="
enabled" className="jenkins.model.DownloadSettings" method="usePostBack
"/>
<j:if test="${
enabled
}">
<j:forEach var="site" items="${app.updateCenter.sites}">
<j:if test="${site.due or forcedUpdateCheck}">
<script>
...
...
core/src/main/resources/jenkins/fun/Jenkins100K/index.jelly
0 → 100644
浏览文件 @
03647c7c
<!--
The MIT License
Copyright (c) 2015, CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout title="Jenkins">
<l:main-panel>
<div align="center" id="certificate">
<style>
#side-panel { display: none; }
#main-panel { padding-left: 0px !important; }
#certificate {
opacity: 0;
-webkit-transition: opacity 2s ease-in;
-moz-transition: opacity 2s ease-in;
-ms-transition: opacity 2s ease-in;
-o-transition: opacity 2s ease-in;
transition: opacity 2s ease-in;
}
#certificate.load {
opacity: 1;
}
</style>
<div style="margin:2em"><a href="http://jenkins-ci.org/100k">
<img src="${imagesURL}/100k.png"/>
</a></div>
<div style="margin:2em">
In Feb 2015, Jenkins project counted that the active installations it tracks around the world went over the 100,000 instances.
</div>
<a class="twitter-share-button" href="https://twitter.com/share"
data-related="jenkinsci"
data-size="large"
data-text="I helped @JenkinsCI to grow to 100K! #Jenkins100K"
data-url="http://jenkins-ci.org/content/jenkins-celebration-day-february-26"
data-count="right">
Tweet
</a>
<script>
window.twttr=(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);t._e=[];t.ready=function(f){t._e.push(f);};return t;}(document,"script","twitter-wjs"));
Behaviour.addLoadEvent(function() {
$('certificate').addClassName('load');
});
</script>
</div>
</l:main-panel>
</l:layout>
</j:jelly>
core/src/main/resources/jenkins/model/DownloadSettings/Warning/message.jelly
0 → 100644
浏览文件 @
03647c7c
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright 2015 Jesse Glick.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly
xmlns:j=
"jelly:core"
xmlns:f=
"/lib/form"
>
<div
class=
"warning"
>
<form
method=
"post"
action=
"${rootURL}/${it.url}/disable"
>
<j:out
value=
"${%blurb(rootURL)}"
/>
<f:submit
value=
"${%Dismiss}"
/>
</form>
</div>
</j:jelly>
core/src/main/resources/jenkins/model/DownloadSettings/Warning/message.properties
0 → 100644
浏览文件 @
03647c7c
# The MIT License
#
# Copyright 2015 Jesse Glick.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
blurb
=
\
You currently are using browser-based download to retrieve metadata for Jenkins plugins and tools.
\
This has reliability issues and is not considered fully secure.
\
Consider <a href="{0}/configureSecurity">switching to server-based download</a>.
core/src/main/resources/jenkins/model/DownloadSettings/config.groovy
浏览文件 @
03647c7c
...
...
@@ -2,8 +2,7 @@ package jenkins.security.DownloadSettings
def
f
=
namespace
(
lib
.
FormTagLib
)
f
.
section
(
title:
_
(
"Download Preferences"
))
{
f
.
entry
(
title:
_
(
"Use Browser"
),
field:
"useBrowser"
)
{
f
.
checkbox
()
}
// TODO avoid indentation somehow
f
.
entry
(
field:
"useBrowser"
)
{
f
.
checkbox
(
title:
_
(
"Use browser for metadata download"
))
}
core/src/main/resources/jenkins/model/DownloadSettings/help-useBrowser.html
浏览文件 @
03647c7c
<
div
>
<
p
>
Check to force the user’s browser to download metadata (lists of available plugins, tools etc.)
rather than Jenkins itself doing it.
Actual file downloads (plugins, tools) will still happen from Jenkins itself,
but this can be used to at least
<em>
see
</em>
new metadata when Jenkins cannot access the Internet
(but your own browser can, perhaps using some special proxy that Jenkins is not configured to use).
</div>
</p>
<p>
Use of browser mode is discouraged.
It has robustness problems and has been limited to users with Overall/Administer.
</p>
core/src/test/java/hudson/PluginManagerTest.java
浏览文件 @
03647c7c
...
...
@@ -26,11 +26,14 @@ package hudson;
import
org.apache.tools.ant.filters.StringInputStream
;
import
org.junit.Test
;
import
org.xml.sax.SAXException
;
import
java.io.IOException
;
import
static
org
.
hamcrest
.
core
.
IsInstanceOf
.
instanceOf
;
import
static
org
.
hamcrest
.
core
.
StringContains
.
containsString
;
import
static
org
.
junit
.
Assert
.*;
import
org.junit.Rule
;
import
org.junit.rules.TemporaryFolder
;
import
org.jvnet.hudson.test.Issue
;
public
class
PluginManagerTest
{
...
...
@@ -41,4 +44,28 @@ public class PluginManagerTest {
.
parseRequestedPlugins
(
new
StringInputStream
(
"<root><stuff plugin='stuff@1.0'><more plugin='other@2.0'><things plugin='stuff@1.2'/></more></stuff></root>"
)).
toString
());
}
@Issue
(
"SECURITY-167"
)
@Test
public
void
parseInvalidRequestedPlugins
()
throws
Exception
{
String
evilXML
=
"<?xml version='1.0' encoding='UTF-8'?>\n"
+
"<!DOCTYPE project[<!ENTITY foo SYSTEM \"file:///\">]>\n"
+
"<root>\n"
+
" <stuff plugin='stuff@1.0'>\n"
+
"&foo;"
+
" <more plugin='other@2.0'>\n"
+
" <things plugin='stuff@1.2'/>\n"
+
" </more>\n"
+
" </stuff>\n"
+
"</root>\n"
;
PluginManager
pluginManager
=
new
LocalPluginManager
(
Util
.
createTempDir
());
try
{
pluginManager
.
parseRequestedPlugins
(
new
StringInputStream
(
evilXML
));
fail
(
"XML contains an external entity, but no exception was thrown."
);
}
catch
(
IOException
ex
)
{
assertThat
(
ex
.
getCause
(),
instanceOf
(
SAXException
.
class
));
assertThat
(
ex
.
getCause
().
getMessage
(),
containsString
(
"Refusing to resolve entity with publicId(null) and systemId (file:///)"
));
}
}
}
core/src/test/java/jenkins/util/VirtualFileTest.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright 2015 Jesse Glick.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.util
;
import
hudson.Util
;
import
hudson.model.TaskListener
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
org.apache.commons.io.FileUtils
;
import
org.apache.commons.io.IOUtils
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
import
org.junit.Rule
;
import
org.junit.rules.TemporaryFolder
;
import
org.jvnet.hudson.test.Issue
;
public
class
VirtualFileTest
{
@Rule
public
TemporaryFolder
tmp
=
new
TemporaryFolder
();
@Issue
(
"SECURITY-162"
)
@Test
public
void
outsideSymlinks
()
throws
Exception
{
File
ws
=
tmp
.
newFolder
(
"ws"
);
FileUtils
.
write
(
new
File
(
ws
,
"safe"
),
"safe"
);
Util
.
createSymlink
(
ws
,
"safe"
,
"supported"
,
TaskListener
.
NULL
);
File
other
=
tmp
.
newFolder
(
"other"
);
FileUtils
.
write
(
new
File
(
other
,
"secret"
),
"s3cr3t"
);
Util
.
createSymlink
(
ws
,
"../other/secret"
,
"hack"
,
TaskListener
.
NULL
);
VirtualFile
root
=
VirtualFile
.
forFile
(
ws
);
VirtualFile
supported
=
root
.
child
(
"supported"
);
assertTrue
(
supported
.
isFile
());
assertTrue
(
supported
.
exists
());
assertEquals
(
"safe"
,
IOUtils
.
toString
(
supported
.
open
(),
(
String
)
null
));
VirtualFile
hack
=
root
.
child
(
"hack"
);
assertFalse
(
hack
.
isFile
());
assertFalse
(
hack
.
exists
());
try
{
hack
.
open
();
fail
();
}
catch
(
FileNotFoundException
x
)
{
// OK
}
}
}
\ No newline at end of file
core/src/test/java/jenkins/xml/XMLUtilsTest.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright 2015 James Nord.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.xml
;
import
jenkins.util.xml.XMLUtils
;
import
org.junit.Test
;
import
java.io.StringReader
;
import
java.io.StringWriter
;
import
javax.xml.transform.TransformerException
;
import
javax.xml.transform.stream.StreamResult
;
import
javax.xml.transform.stream.StreamSource
;
import
static
org
.
hamcrest
.
core
.
StringContains
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
org.jvnet.hudson.test.Issue
;
public
class
XMLUtilsTest
{
@Issue
(
"SECURITY-167"
)
@Test
()
public
void
testSafeTransformDoesNotProcessForeignResources
()
throws
Exception
{
final
String
xml
=
"<?xml version='1.0' encoding='UTF-8'?>\n"
+
"<!DOCTYPE project[\n"
+
" <!ENTITY foo SYSTEM \"file:///\">\n"
+
"]>\n"
+
"<project>\n"
+
" <actions/>\n"
+
" <description>&foo;</description>\n"
+
" <keepDependencies>false</keepDependencies>\n"
+
" <properties/>\n"
+
" <scm class=\"hudson.scm.NullSCM\"/>\n"
+
" <canRoam>true</canRoam>\n"
+
" <triggers/>\n"
+
" <builders/>\n"
+
" <publishers/>\n"
+
" <buildWrappers/>\n"
+
"</project>"
;
StringWriter
stringWriter
=
new
StringWriter
();
try
{
XMLUtils
.
safeTransform
(
new
StreamSource
(
new
StringReader
(
xml
)),
new
StreamResult
(
stringWriter
));
// if no exception then JAXP is swallowing these - so there should be no entity in the description.
assertThat
(
stringWriter
.
toString
(),
containsString
(
"<description/>"
));
}
catch
(
TransformerException
ex
)
{
assertThat
(
ex
.
getMessage
(),
containsString
(
"Refusing to resolve entity"
));
}
}
@Issue
(
"SECURITY-167"
)
@Test
()
public
void
testUpdateByXmlIDoesNotFail
()
throws
Exception
{
final
String
xml
=
"<?xml version='1.0' encoding='UTF-8'?>\n"
+
"<project>\n"
+
" <actions/>\n"
+
" <description>&</description>\n"
+
" <keepDependencies>false</keepDependencies>\n"
+
" <properties/>\n"
+
" <scm class=\"hudson.scm.NullSCM\"/>\n"
+
" <canRoam>true</canRoam>\n"
+
" <triggers/>\n"
+
" <builders/>\n"
+
" <publishers/>\n"
+
" <buildWrappers/>\n"
+
"</project>"
;
StringWriter
stringWriter
=
new
StringWriter
();
XMLUtils
.
safeTransform
(
new
StreamSource
(
new
StringReader
(
xml
)),
new
StreamResult
(
stringWriter
));
// make sure that normal entities are retained.
assertThat
(
stringWriter
.
toString
(),
containsString
(
"<description>&</description>"
));
}
}
debian/debian/changelog
浏览文件 @
03647c7c
jenkins (1.600) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
-- Kohsuke Kawaguchi <kk@kohsuke.org> Sat, 28 Feb 2015 09:47:38 -0800
jenkins (1.599) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
...
...
pom.xml
浏览文件 @
03647c7c
...
...
@@ -98,6 +98,7 @@ THE SOFTWARE.
<slf4jVersion>
1.7.7
</slf4jVersion>
<!-- < 1.6.x version didn't specify the license (MIT) -->
<maven-plugin.version>
2.7.1
</maven-plugin.version>
<matrix-project.version>
1.4.1
</matrix-project.version>
<animal.sniffer.skip>
${skipTests}
</animal.sniffer.skip>
<java.level>
6
</java.level>
...
...
test/pom.xml
浏览文件 @
03647c7c
...
...
@@ -93,7 +93,7 @@ THE SOFTWARE.
<dependency>
<groupId>
org.jenkins-ci.plugins
</groupId>
<artifactId>
matrix-project
</artifactId>
<version>
1.0-beta-1
</version>
<version>
${matrix-project.version}
</version>
</dependency>
<dependency>
<groupId>
org.jenkins-ci.plugins
</groupId>
...
...
test/src/test/java/hudson/model/AbstractItemSecurityTest.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright 2015 James Nord.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
hudson.model
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
javax.xml.transform.stream.StreamSource
;
import
java.io.IOException
;
import
java.io.StringReader
;
import
static
org
.
hamcrest
.
core
.
Is
.
is
;
import
static
org
.
hamcrest
.
core
.
IsNot
.
not
;
import
static
org
.
hamcrest
.
core
.
IsNull
.
nullValue
;
import
static
org
.
hamcrest
.
core
.
StringContains
.
containsString
;
import
static
org
.
hamcrest
.
text
.
IsEmptyString
.
isEmptyOrNullString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
org.jvnet.hudson.test.Issue
;
public
class
AbstractItemSecurityTest
{
@Rule
public
JenkinsRule
jenkinsRule
=
new
JenkinsRule
();
@Issue
(
"SECURITY-167"
)
@Test
()
public
void
testUpdateByXmlDoesNotProcessForeignResources
()
throws
Exception
{
final
String
xml
=
"<?xml version='1.0' encoding='UTF-8'?>\n"
+
"<!DOCTYPE project[\n"
+
" <!ENTITY foo SYSTEM \"file:///\">\n"
+
"]>\n"
+
"<project>\n"
+
" <description>&foo;</description>\n"
+
" <scm class=\"hudson.scm.NullSCM\"/>\n"
+
"</project>"
;
FreeStyleProject
project
=
jenkinsRule
.
createFreeStyleProject
(
"security-167"
);
project
.
setDescription
(
"Wibble"
);
try
{
project
.
updateByXml
(
new
StreamSource
(
new
StringReader
(
xml
)));
// if we didn't fail JAXP has thrown away the entity.
assertThat
(
project
.
getDescription
(),
isEmptyOrNullString
());
}
catch
(
IOException
ex
)
{
assertThat
(
ex
.
getCause
(),
not
(
nullValue
()));
assertThat
(
ex
.
getCause
().
getMessage
(),
containsString
(
"Refusing to resolve entity"
));
}
}
@Issue
(
"SECURITY-167"
)
@Test
()
public
void
testUpdateByXmlDoesNotFail
()
throws
Exception
{
final
String
xml
=
"<?xml version='1.0' encoding='UTF-8'?>\n"
+
"<project>\n"
+
" <description>&</description>\n"
+
" <scm class=\"hudson.scm.NullSCM\"/>\n"
+
"</project>"
;
FreeStyleProject
project
=
jenkinsRule
.
createFreeStyleProject
(
"security-167"
);
project
.
updateByXml
((
StreamSource
)
new
StreamSource
(
new
StringReader
(
xml
)));
assertThat
(
project
.
getDescription
(),
is
(
"&"
));
// the entity is transformed
}
}
test/src/test/java/hudson/model/ApiTest.java
浏览文件 @
03647c7c
...
...
@@ -23,9 +23,11 @@
*/
package
hudson.model
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
*
;
import
com.gargoylesoftware.htmlunit.Page
;
import
java.io.File
;
import
java.net.HttpURLConnection
;
import
org.junit.Rule
;
...
...
@@ -54,6 +56,27 @@ public class ApiTest {
assertEquals
(
"<root/>"
,
page
.
getWebResponse
().
getContentAsString
());
}
/**
* Test that calling the XML API with the XPath <code>document</code> function fails.
*
* @throws Exception if so
*/
@Issue
(
"SECURITY-165"
)
@Test
public
void
xPathDocumentFunction
()
throws
Exception
{
File
f
=
new
File
(
j
.
jenkins
.
getRootDir
(),
"queue.xml"
);
JenkinsRule
.
WebClient
client
=
j
.
createWebClient
();
try
{
client
.
goTo
(
"api/xml?xpath=document(\""
+
f
.
getAbsolutePath
()
+
"\")"
,
"application/xml"
);
fail
(
"Should become 500 error"
);
}
catch
(
com
.
gargoylesoftware
.
htmlunit
.
FailingHttpStatusCodeException
e
)
{
String
contentAsString
=
e
.
getResponse
().
getContentAsString
();
j
.
assertStringContains
(
contentAsString
,
"Illegal function: document"
);
}
}
@Test
@Issue
(
"JENKINS-3267"
)
public
void
wrappedOneItem
()
throws
Exception
{
...
...
test/src/test/java/hudson/model/DownloadService2Test.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright 2015 Jesse Glick.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
hudson.model
;
import
hudson.util.FormValidation
;
import
java.net.URL
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
net.sf.json.JSONObject
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
import
org.junit.Rule
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.WithoutJenkins
;
@Issue
(
"SECURITY-163"
)
public
class
DownloadService2Test
{
@Rule
public
JenkinsRule
r
=
new
JenkinsRule
();
@Test
public
void
updateNow
()
throws
Exception
{
for
(
DownloadService
.
Downloadable
d
:
DownloadService
.
Downloadable
.
all
())
{
FormValidation
v
=
d
.
updateNow
();
assertEquals
(
v
.
toString
(),
FormValidation
.
Kind
.
OK
,
v
.
kind
);
}
}
@WithoutJenkins
@Test
public
void
loadJSONHTML
()
throws
Exception
{
assertRoots
(
"[list, signature]"
,
"hudson.tasks.Maven.MavenInstaller.json.html"
);
// format used by most tools
assertRoots
(
"[data, signature, version]"
,
"hudson.tools.JDKInstaller.json.html"
);
// anomalous format
}
private
static
void
assertRoots
(
String
expected
,
String
file
)
throws
Exception
{
URL
resource
=
DownloadService2Test
.
class
.
getResource
(
file
);
assertNotNull
(
file
,
resource
);
JSONObject
json
=
JSONObject
.
fromObject
(
DownloadService
.
loadJSONHTML
(
resource
));
@SuppressWarnings
(
"unchecked"
)
Set
<
String
>
keySet
=
json
.
keySet
();
assertEquals
(
expected
,
new
TreeSet
<
String
>(
keySet
).
toString
());
}
}
test/src/test/java/hudson/model/DownloadServiceTest.java
浏览文件 @
03647c7c
...
...
@@ -5,6 +5,7 @@ import java.io.IOException;
import
java.net.URL
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
jenkins.model.DownloadSettings
;
import
net.sf.json.JSONObject
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.HudsonTestCase
;
...
...
@@ -30,6 +31,7 @@ public class DownloadServiceTest extends HudsonTestCase {
// to bypass the URL restriction, we'll trigger downloadService.download ourselves
job
=
new
Downloadable
(
"test"
,
"UNUSED"
);
Downloadable
.
all
().
add
(
job
);
DownloadSettings
.
get
().
setUseBrowser
(
true
);
}
@Issue
(
"JENKINS-5536"
)
...
...
test/src/test/java/hudson/model/UpdateCenter2Test.java
浏览文件 @
03647c7c
...
...
@@ -46,7 +46,7 @@ public class UpdateCenter2Test {
@RandomlyFails
(
"SocketTimeoutException from goTo due to GET http://localhost:…/update-center.json?…"
)
@Test
public
void
install
()
throws
Exception
{
UpdateSite
.
neverUpdate
=
false
;
j
.
createWebClient
().
goTo
(
""
);
// load the metadata
j
.
jenkins
.
pluginManager
.
doCheckUpdatesServer
(
);
// load the metadata
DownloadJob
job
=
(
DownloadJob
)
j
.
jenkins
.
getUpdateCenter
().
getPlugin
(
"changelog-history"
).
deploy
().
get
();
// this seems like one of the smallest plugin
System
.
out
.
println
(
job
.
status
);
assertTrue
(
job
.
status
instanceof
Success
);
...
...
test/src/test/java/hudson/security/HudsonPrivateSecurityRealm2Test.java
0 → 100644
浏览文件 @
03647c7c
/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
hudson.security
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
hudson.model.User
;
import
hudson.security.pages.SignupPage
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
java.util.Collections
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
junit
.
Assert
.*;
import
org.jvnet.hudson.test.Issue
;
/**
* Tests the signup page of {@link hudson.security.HudsonPrivateSecurityRealm}
* TODO: Add to {@link hudson.security.HudsonPrivateSecurityRealmTest} going forward
*/
public
class
HudsonPrivateSecurityRealm2Test
{
@Rule
public
JenkinsRule
rule
=
new
JenkinsRule
();
@Test
public
void
signup
()
throws
Exception
{
HudsonPrivateSecurityRealm
securityRealm
=
new
HudsonPrivateSecurityRealm
(
true
,
false
,
null
);
rule
.
jenkins
.
setSecurityRealm
(
securityRealm
);
JenkinsRule
.
WebClient
wc
=
rule
.
createWebClient
();
SignupPage
signup
=
new
SignupPage
(
wc
.
goTo
(
"signup"
));
signup
.
enterUsername
(
"alice"
);
signup
.
enterPassword
(
"alice"
);
signup
.
enterFullName
(
"Alice User"
);
signup
.
enterEmail
(
"alice@nowhere.com"
);
HtmlPage
success
=
signup
.
submit
(
rule
);
assertThat
(
success
.
getElementById
(
"main-panel"
).
getTextContent
(),
containsString
(
"Success"
));
assertThat
(
success
.
getAnchorByHref
(
"/jenkins/user/alice"
).
getTextContent
(),
containsString
(
"Alice User"
));
assertEquals
(
"Alice User"
,
securityRealm
.
getUser
(
"alice"
).
getDisplayName
());
}
@Issue
(
"SECURITY-166"
)
@Test
public
void
anonymousCantSignup
()
throws
Exception
{
HudsonPrivateSecurityRealm
securityRealm
=
new
HudsonPrivateSecurityRealm
(
true
,
false
,
null
);
rule
.
jenkins
.
setSecurityRealm
(
securityRealm
);
JenkinsRule
.
WebClient
wc
=
rule
.
createWebClient
();
SignupPage
signup
=
new
SignupPage
(
wc
.
goTo
(
"signup"
));
signup
.
enterUsername
(
"anonymous"
);
signup
.
enterFullName
(
"Bob"
);
signup
.
enterPassword
(
"nothing"
);
signup
.
enterEmail
(
"noone@nowhere.com"
);
signup
=
new
SignupPage
(
signup
.
submit
(
rule
));
signup
.
assertErrorContains
(
"prohibited as a username"
);
assertNull
(
User
.
get
(
"anonymous"
,
false
,
Collections
.
emptyMap
()));
}
@Issue
(
"SECURITY-166"
)
@Test
public
void
systemCantSignup
()
throws
Exception
{
HudsonPrivateSecurityRealm
securityRealm
=
new
HudsonPrivateSecurityRealm
(
true
,
false
,
null
);
rule
.
jenkins
.
setSecurityRealm
(
securityRealm
);
JenkinsRule
.
WebClient
wc
=
rule
.
createWebClient
();
SignupPage
signup
=
new
SignupPage
(
wc
.
goTo
(
"signup"
));
signup
.
enterUsername
(
"system"
);
signup
.
enterFullName
(
"Bob"
);
signup
.
enterPassword
(
"nothing"
);
signup
.
enterEmail
(
"noone@nowhere.com"
);
signup
=
new
SignupPage
(
signup
.
submit
(
rule
));
signup
.
assertErrorContains
(
"prohibited as a username"
);
assertNull
(
User
.
get
(
"system"
,
false
,
Collections
.
emptyMap
()));
}
/**
* We don't allow prohibited fullnames since this may encumber auditing.
*/
@Issue
(
"SECURITY-166"
)
@Test
public
void
fullNameOfUnknownCantSignup
()
throws
Exception
{
HudsonPrivateSecurityRealm
securityRealm
=
new
HudsonPrivateSecurityRealm
(
true
,
false
,
null
);
rule
.
jenkins
.
setSecurityRealm
(
securityRealm
);
JenkinsRule
.
WebClient
wc
=
rule
.
createWebClient
();
SignupPage
signup
=
new
SignupPage
(
wc
.
goTo
(
"signup"
));
signup
.
enterUsername
(
"unknown2"
);
signup
.
enterPassword
(
"unknown2"
);
signup
.
enterFullName
(
"unknown"
);
signup
.
enterEmail
(
"noone@nowhere.com"
);
signup
=
new
SignupPage
(
signup
.
submit
(
rule
));
signup
.
assertErrorContains
(
"prohibited as a full name"
);
assertNull
(
User
.
get
(
"unknown2"
,
false
,
Collections
.
emptyMap
()));
}
}
test/src/test/java/hudson/security/pages/SignupPage.java
0 → 100644
浏览文件 @
03647c7c
package
hudson.security.pages
;
import
com.gargoylesoftware.htmlunit.html.HtmlForm
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
junit
.
Assert
.*;
/**
* The the signup page for {@link hudson.security.HudsonPrivateSecurityRealm}
*/
public
class
SignupPage
{
public
HtmlForm
signupForm
;
public
final
HtmlPage
signupPage
;
public
SignupPage
(
HtmlPage
signupPage
)
{
this
.
signupPage
=
signupPage
;
assertNotNull
(
"The sign up page has a username field."
,
this
.
signupPage
.
getElementById
(
"username"
));
for
(
HtmlForm
signupForm
:
this
.
signupPage
.
getForms
())
{
if
(
signupForm
.
getInputsByName
(
"username"
).
size
()
==
0
)
continue
;
this
.
signupForm
=
signupForm
;
}
}
public
void
enterUsername
(
String
username
)
{
signupForm
.
getInputByName
(
"username"
).
setValueAttribute
(
username
);
}
/**
* Enters the password in password1 and password2.
* You can then call {@link #enterPassword2(String)} if you want them to be different.
* @param password
*/
public
void
enterPassword
(
String
password
)
{
signupForm
.
getInputByName
(
"password1"
).
setValueAttribute
(
password
);
signupForm
.
getInputByName
(
"password2"
).
setValueAttribute
(
password
);
}
public
void
enterPassword2
(
String
password2
)
{
signupForm
.
getInputByName
(
"password2"
).
setValueAttribute
(
password2
);
}
public
void
enterFullName
(
String
fullName
)
{
signupForm
.
getInputByName
(
"fullname"
).
setValueAttribute
(
fullName
);
}
public
void
enterEmail
(
String
email
)
{
signupForm
.
getInputByName
(
"email"
).
setValueAttribute
(
email
);
}
public
HtmlPage
submit
(
JenkinsRule
rule
)
throws
Exception
{
return
rule
.
submit
(
signupForm
);
}
public
void
assertErrorContains
(
String
msg
)
{
assertThat
(
signupForm
.
getElementById
(
"main-panel"
).
getTextContent
(),
containsString
(
msg
));
}
}
test/src/test/java/hudson/tasks/ArtifactArchiverTest.java
浏览文件 @
03647c7c
...
...
@@ -36,6 +36,7 @@ import hudson.model.Result;
import
static
hudson
.
tasks
.
LogRotatorTest
.
build
;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.HttpURLConnection
;
import
java.util.Collections
;
import
java.util.List
;
import
jenkins.util.VirtualFile
;
...
...
@@ -127,6 +128,34 @@ public class ArtifactArchiverTest {
// do not check that it .exists() since its target has not been archived
}
@Issue
(
"SECURITY-162"
)
@Test
public
void
outsideSymlinks
()
throws
Exception
{
final
FreeStyleProject
p
=
j
.
createFreeStyleProject
();
p
.
getBuildersList
().
add
(
new
TestBuilder
()
{
@Override
public
boolean
perform
(
AbstractBuild
<?,?>
build
,
Launcher
launcher
,
BuildListener
listener
)
throws
InterruptedException
,
IOException
{
FilePath
ws
=
build
.
getWorkspace
();
if
(
ws
==
null
)
{
return
false
;
}
ws
.
child
(
"hack"
).
symlinkTo
(
p
.
getConfigFile
().
getFile
().
getAbsolutePath
(),
listener
);
return
true
;
}
});
p
.
getPublishersList
().
add
(
new
ArtifactArchiver
(
"hack"
,
""
,
false
,
true
));
FreeStyleBuild
b
=
j
.
assertBuildStatusSuccess
(
p
.
scheduleBuild2
(
0
));
List
<
FreeStyleBuild
.
Artifact
>
artifacts
=
b
.
getArtifacts
();
assertEquals
(
1
,
artifacts
.
size
());
FreeStyleBuild
.
Artifact
artifact
=
artifacts
.
get
(
0
);
assertEquals
(
"hack"
,
artifact
.
relativePath
);
VirtualFile
[]
kids
=
b
.
getArtifactManager
().
root
().
list
();
assertEquals
(
1
,
kids
.
length
);
assertEquals
(
"hack"
,
kids
[
0
].
getName
());
assertFalse
(
kids
[
0
].
isDirectory
());
assertFalse
(
kids
[
0
].
isFile
());
assertFalse
(
kids
[
0
].
exists
());
j
.
createWebClient
().
assertFails
(
b
.
getUrl
()
+
"artifact/hack"
,
HttpURLConnection
.
HTTP_NOT_FOUND
);
}
private
void
runNewBuildAndStartUnitlIsCreated
(
AbstractProject
project
)
throws
InterruptedException
{
int
buildNumber
=
project
.
getNextBuildNumber
();
project
.
scheduleBuild2
(
0
);
...
...
test/src/test/resources/hudson/model/hudson.tasks.Maven.MavenInstaller.json.html
0 → 100644
浏览文件 @
03647c7c
<!DOCTYPE html>
<html><head><meta
http-equiv=
'Content-Type'
content=
'text/html;charset=UTF-8'
/></head><body><script>
window
.
onload
=
function
()
{
window
.
parent
.
postMessage
(
JSON
.
stringify
(
{
"
list
"
:
[
{
"
id
"
:
"
3.2.2
"
,
"
name
"
:
"
3.2.2
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.2.2-bin.zip
"
},
{
"
id
"
:
"
3.2.1
"
,
"
name
"
:
"
3.2.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.2.1-bin.zip
"
},
{
"
id
"
:
"
3.1.1
"
,
"
name
"
:
"
3.1.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.1.1-bin.zip
"
},
{
"
id
"
:
"
3.1.0
"
,
"
name
"
:
"
3.1.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.1.0-bin.zip
"
},
{
"
id
"
:
"
3.0.5
"
,
"
name
"
:
"
3.0.5
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0.5-bin.zip
"
},
{
"
id
"
:
"
3.0.4
"
,
"
name
"
:
"
3.0.4
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0.4-bin.zip
"
},
{
"
id
"
:
"
3.0.3
"
,
"
name
"
:
"
3.0.3
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0.3-bin.zip
"
},
{
"
id
"
:
"
3.0.2
"
,
"
name
"
:
"
3.0.2
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0.2-bin.zip
"
},
{
"
id
"
:
"
3.0.1
"
,
"
name
"
:
"
3.0.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0.1-bin.zip
"
},
{
"
id
"
:
"
3.0
"
,
"
name
"
:
"
3.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-3.0-bin.zip
"
},
{
"
id
"
:
"
2.2.1
"
,
"
name
"
:
"
2.2.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.2.1-bin.zip
"
},
{
"
id
"
:
"
2.2.0
"
,
"
name
"
:
"
2.2.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.2.0-bin.zip
"
},
{
"
id
"
:
"
2.1.0
"
,
"
name
"
:
"
2.1.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.1.0-bin.zip
"
},
{
"
id
"
:
"
2.0.11
"
,
"
name
"
:
"
2.0.11
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.0.11-bin.zip
"
},
{
"
id
"
:
"
2.0.10
"
,
"
name
"
:
"
2.0.10
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.0.10-bin.zip
"
},
{
"
id
"
:
"
2.0.9
"
,
"
name
"
:
"
2.0.9
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.0.9-bin.zip
"
},
{
"
id
"
:
"
2.0.8
"
,
"
name
"
:
"
2.0.8
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/apache-maven-2.0.8-bin.zip
"
},
{
"
id
"
:
"
2.0.7
"
,
"
name
"
:
"
2.0.7
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.7-bin.zip
"
},
{
"
id
"
:
"
2.0.6
"
,
"
name
"
:
"
2.0.6
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.6-bin.zip
"
},
{
"
id
"
:
"
2.0.5
"
,
"
name
"
:
"
2.0.5
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.5-bin.zip
"
},
{
"
id
"
:
"
2.0.4
"
,
"
name
"
:
"
2.0.4
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.4-bin.zip
"
},
{
"
id
"
:
"
2.0.3
"
,
"
name
"
:
"
2.0.3
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.3-bin.zip
"
},
{
"
id
"
:
"
2.0.2
"
,
"
name
"
:
"
2.0.2
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.2-bin.zip
"
},
{
"
id
"
:
"
2.0.1
"
,
"
name
"
:
"
2.0.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0.1-bin.zip
"
},
{
"
id
"
:
"
2.0
"
,
"
name
"
:
"
2.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-2.0-bin.zip
"
},
{
"
id
"
:
"
1.1
"
,
"
name
"
:
"
1.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-1.1.zip
"
},
{
"
id
"
:
"
1.0.2
"
,
"
name
"
:
"
1.0.2
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-1.0.2.zip
"
},
{
"
id
"
:
"
1.0.1
"
,
"
name
"
:
"
1.0.1
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-1.0.1.zip
"
},
{
"
id
"
:
"
1.0
"
,
"
name
"
:
"
1.0
"
,
"
url
"
:
"
http://archive.apache.org/dist/maven/binaries/maven-1.0.zip
"
}
],
"
signature
"
:
{
"
certificates
"
:
[
"
MIICmTCCAYECBQDerb70MA0GCSqGSIb3DQEBBAUAMIGKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2UxGDAWBgNVBAoTD0plbmtpbnMgUHJvamVjdDEaMBgGA1UEAxMRS29oc3VrZSBLYXdhZ3VjaGkxHTAbBgkqhkiG9w0BCQEWDmtrQGtvaHN1a2Uub3JnMB4XDTE0MDEyNzIxMDQwN1oXDTE1MDEyNzIxMDQwN1owXjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExGDAWBgNVBAoTD0plbmtpbnMgUHJvamVjdDEgMB4GA1UEAxMXQ29tbXVuaXR5IFVwZGF0ZSBDZW50ZXIwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAvAYxdnnMyREVQkfsMmGNXj2mFMgur+jjavJx5Wjc6Mfiq1x33Ps7qprhaklHmCg720Xe30E2+I/5R00XcUA+CwIDAQABMA0GCSqGSIb3DQEBBAUAA4IBAQCv9qYtq4miozdu/uzCvj2Dfj8Ms39ATivtuPiHCWagcOiR1SAjKI4DTdbz9WfNHH67TQrSSOwt7+HBjBVVh8WP1bI+OuJwgqmjcTuy14tByA3I5QZqM05SvZnVYY9ce5uXXNxe+FMwTRvnywbGPOPGG9xnfEsfN7NUjpAYbgM6fIkBMepOeL38IPUJb5pbDvM+F1zPaEJxnhGxnj3CuLu0XsI0h2wKCak1cJaLACJ+YSwPZju5/xNjQSibxAeoWh4u3JDQdgMSIOVGZWndypvr/xhLT2mVdXHSU7kpNB8Ojz9nC62g7qrC22bgUa1cGVIlljIi2Sf/xlXLu9Csksf+
"
],
"
correct_digest
"
:
"
NCZ9Z7HAwOMg7MnVrEVUsR5b+UA=
"
,
"
correct_signature
"
:
"
ne6nBPs70d9Hh1gOMiKlVhj+zLbNjbMMVpn0Wn7MwF14MpVlCenkJouOw9b1Bq6Ay5L6bJ4iVvoCbvFhJyRrcg==
"
,
"
digest
"
:
"
2jmj7l5rSw0yVb/vlWAYkK/YBwk=
"
,
"
signature
"
:
"
PzSbGGnXzyOz2elTuaHwshl0uz/BZ50XcsuD/dyKq8fAyfqT27n2ghZETXAUKia4lFpTlqtuIm9+NySEbxYuTQ==
"
}
}
),
'
*
'
);
};
</script></body></html>
\ No newline at end of file
test/src/test/resources/hudson/model/hudson.tools.JDKInstaller.json.html
0 → 100644
浏览文件 @
03647c7c
因为 它太大了无法显示 source diff 。你可以改为
查看blob
。
war/pom.xml
浏览文件 @
03647c7c
...
...
@@ -358,7 +358,13 @@ THE SOFTWARE.
<artifactItem>
<groupId>
org.jenkins-ci.plugins
</groupId>
<artifactId>
matrix-project
</artifactId>
<version>
1.3
</version>
<version>
${matrix-project.version}
</version>
<type>
hpi
</type>
</artifactItem>
<artifactItem>
<groupId>
org.jenkins-ci.plugins
</groupId>
<artifactId>
script-security
</artifactId>
<version>
1.13
</version>
<type>
hpi
</type>
</artifactItem>
<artifactItem>
...
...
war/src/main/webapp/images/100k.png
0 → 100644
浏览文件 @
03647c7c
此差异由.gitattributes 抑制。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录