Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
c3692651
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c3692651
编写于
12月 26, 2012
作者:
M
mullan
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8005117: Eliminate dependency from ConfigSpiFile to com.sun.security.auth.login.ConfigFile
Reviewed-by: alanb, mchung, weijun
上级
2f5cc953
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
669 addition
and
614 deletion
+669
-614
src/share/classes/com/sun/security/auth/login/ConfigFile.java
...share/classes/com/sun/security/auth/login/ConfigFile.java
+41
-573
src/share/classes/sun/security/provider/ConfigSpiFile.java
src/share/classes/sun/security/provider/ConfigSpiFile.java
+628
-41
未找到文件。
src/share/classes/com/sun/security/auth/login/ConfigFile.java
浏览文件 @
c3692651
...
...
@@ -25,41 +25,39 @@
package
com.sun.security.auth.login
;
import
javax.security.auth.AuthPermission
;
import
javax.security.auth.login.AppConfigurationEntry
;
import
java.io.*
;
import
java.util.*
;
import
javax.security.auth.login.Configuration
;
import
java.net.URI
;
import
java.net.URL
;
import
java.net.MalformedURLException
;
import
java.text.MessageFormat
;
import
sun.security.util.Debug
;
import
sun.security.util.ResourcesMgr
;
import
sun.security.util.PropertyExpander
;
// NOTE: As of JDK 8, this class instantiates
// sun.security.provider.ConfigSpiFile and forwards all methods to that
// implementation. All implementation fixes and enhancements should be made to
// sun.security.provider.ConfigSpiFile and not this class.
// See JDK-8005117 for more information.
/**
* This class represents a default implementation for
*
<code>javax.security.auth.login.Configuration</code>
.
*
{@code javax.security.auth.login.Configuration}
.
*
* <p> This object stores the runtime login configuration representation,
* and is the amalgamation of multiple static login
* configurations that resides in files.
* The algorithm for locating the login configuration file(s) and reading their
* information into this
<code>Configuration</code>
object is:
* information into this
{@code Configuration}
object is:
*
* <ol>
* <li>
* Loop through the security properties,
* <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
* <i>login.config.url.X</i>.
* Each property value specifies a
<code>URL</code>
pointing to a
* Each property value specifies a
{@code URL}
pointing to a
* login configuration file to be loaded. Read in and load
* each configuration.
*
* <li>
* The
<code>java.lang.System</code>
property
* The
{@code java.lang.System}
property
* <i>java.security.auth.login.config</i>
* may also be set to a
<code>URL</code>
pointing to another
* may also be set to a
{@code URL}
pointing to another
* login configuration file
* (which is the case when a user uses the -D switch at runtime).
* If this property is defined, and its use is allowed by the
...
...
@@ -80,593 +78,63 @@ import sun.security.util.PropertyExpander;
*
* <p> The configuration syntax supported by this implementation
* is exactly that syntax specified in the
*
<code>javax.security.auth.login.Configuration</code>
class.
*
{@code javax.security.auth.login.Configuration}
class.
*
* @see javax.security.auth.login.LoginContext
* @see java.security.Security security properties
*/
public
class
ConfigFile
extends
javax
.
security
.
auth
.
login
.
Configuration
{
private
StreamTokenizer
st
;
private
int
lookahead
;
private
int
linenum
;
private
HashMap
<
String
,
LinkedList
<
AppConfigurationEntry
>>
configuration
;
private
boolean
expandProp
=
true
;
private
URL
url
;
public
class
ConfigFile
extends
Configuration
{
private
static
Debug
debugConfig
=
Debug
.
getInstance
(
"configfile"
);
private
static
Debug
debugParser
=
Debug
.
getInstance
(
"configparser"
);
private
sun
.
security
.
provider
.
ConfigSpiFile
configFile
;
/**
* Create a new <code>Configuration</code> object.
* Create a new {@code Configuration} object.
*
* @throws SecurityException if the {@code Configuration} can not be
* initialized
*/
public
ConfigFile
()
{
try
{
init
(
url
);
}
catch
(
IOException
ioe
)
{
throw
(
SecurityException
)
new
SecurityException
(
ioe
.
getMessage
()).
initCause
(
ioe
);
}
configFile
=
new
sun
.
security
.
provider
.
ConfigSpiFile
();
}
/**
* Create a new
<code>Configuration</code> object from the specified URI
.
* Create a new
{@code Configuration} object from the specified {@code URI}
.
*
* @param uri Create a new Configuration object from this URI.
* @param uri the {@code URI}
* @throws SecurityException if the {@code Configuration} can not be
* initialized
* @throws NullPointerException if {@code uri} is null
*/
public
ConfigFile
(
URI
uri
)
{
// only load config from the specified URI
try
{
url
=
uri
.
toURL
();
init
(
url
);
}
catch
(
MalformedURLException
mue
)
{
throw
(
SecurityException
)
new
SecurityException
(
mue
.
getMessage
()).
initCause
(
mue
);
}
catch
(
IOException
ioe
)
{
throw
(
SecurityException
)
new
SecurityException
(
ioe
.
getMessage
()).
initCause
(
ioe
);
}
configFile
=
new
sun
.
security
.
provider
.
ConfigSpiFile
(
uri
);
}
/**
* Read and initialize the entire login Configuration.
* Retrieve an entry from the {@code Configuration} using an application
* name as an index.
*
* <p>
*
* @exception IOException if the Configuration can not be initialized. <p>
* @exception SecurityException if the caller does not have permission
* to initialize the Configuration.
*/
private
void
init
(
URL
url
)
throws
IOException
{
boolean
initialized
=
false
;
FileReader
fr
=
null
;
String
sep
=
File
.
separator
;
if
(
"false"
.
equals
(
System
.
getProperty
(
"policy.expandProperties"
)))
{
expandProp
=
false
;
}
// new configuration
HashMap
<
String
,
LinkedList
<
AppConfigurationEntry
>>
newConfig
=
new
HashMap
<>();
if
(
url
!=
null
)
{
/**
* If the caller specified a URI via Configuration.getInstance,
* we only read from that URI
*/
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"reading "
+
url
);
}
init
(
url
,
newConfig
);
configuration
=
newConfig
;
return
;
}
/**
* Caller did not specify URI via Configuration.getInstance.
* Read from URLs listed in the java.security properties file.
*/
String
allowSys
=
java
.
security
.
Security
.
getProperty
(
"policy.allowSystemProperty"
);
if
(
"true"
.
equalsIgnoreCase
(
allowSys
))
{
String
extra_config
=
System
.
getProperty
(
"java.security.auth.login.config"
);
if
(
extra_config
!=
null
)
{
boolean
overrideAll
=
false
;
if
(
extra_config
.
startsWith
(
"="
))
{
overrideAll
=
true
;
extra_config
=
extra_config
.
substring
(
1
);
}
try
{
extra_config
=
PropertyExpander
.
expand
(
extra_config
);
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Unable.to.properly.expand.config"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
extra_config
};
throw
new
IOException
(
form
.
format
(
source
));
}
URL
configURL
=
null
;
try
{
configURL
=
new
URL
(
extra_config
);
}
catch
(
java
.
net
.
MalformedURLException
mue
)
{
File
configFile
=
new
File
(
extra_config
);
if
(
configFile
.
exists
())
{
configURL
=
configFile
.
toURI
().
toURL
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"extra.config.No.such.file.or.directory."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
extra_config
};
throw
new
IOException
(
form
.
format
(
source
));
}
}
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"reading "
+
configURL
);
}
init
(
configURL
,
newConfig
);
initialized
=
true
;
if
(
overrideAll
)
{
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"overriding other policies!"
);
}
configuration
=
newConfig
;
return
;
}
}
}
int
n
=
1
;
String
config_url
;
while
((
config_url
=
java
.
security
.
Security
.
getProperty
(
"login.config.url."
+
n
))
!=
null
)
{
try
{
config_url
=
PropertyExpander
.
expand
(
config_url
).
replace
(
File
.
separatorChar
,
'/'
);
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"\tReading config: "
+
config_url
);
}
init
(
new
URL
(
config_url
),
newConfig
);
initialized
=
true
;
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Unable.to.properly.expand.config"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
config_url
};
throw
new
IOException
(
form
.
format
(
source
));
}
n
++;
}
if
(
initialized
==
false
&&
n
==
1
&&
config_url
==
null
)
{
// get the config from the user's home directory
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"\tReading Policy "
+
"from ~/.java.login.config"
);
}
config_url
=
System
.
getProperty
(
"user.home"
);
String
userConfigFile
=
config_url
+
File
.
separatorChar
+
".java.login.config"
;
// No longer throws an exception when there's no config file
// at all. Returns an empty Configuration instead.
if
(
new
File
(
userConfigFile
).
exists
())
{
init
(
new
File
(
userConfigFile
).
toURI
().
toURL
(),
newConfig
);
}
}
configuration
=
newConfig
;
}
private
void
init
(
URL
config
,
HashMap
<
String
,
LinkedList
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
InputStreamReader
isr
=
null
;
try
{
isr
=
new
InputStreamReader
(
getInputStream
(
config
),
"UTF-8"
);
readConfig
(
isr
,
newConfig
);
}
catch
(
FileNotFoundException
fnfe
)
{
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
fnfe
.
toString
());
}
throw
new
IOException
(
ResourcesMgr
.
getString
(
"Configuration.Error.No.such.file.or.directory"
,
"sun.security.util.AuthResources"
));
}
finally
{
if
(
isr
!=
null
)
{
isr
.
close
();
}
}
}
/**
* Retrieve an entry from the Configuration using an application name
* as an index.
*
* <p>
*
* @param applicationName the name used to index the Configuration.
* @return an array of AppConfigurationEntries which correspond to
* the stacked configuration of LoginModules for this
* @param applicationName the name used to index the {@code Configuration}
* @return an array of {@code AppConfigurationEntry} which correspond to
* the stacked configuration of {@code LoginModule}s for this
* application, or null if this application has no configured
*
LoginModule
s.
*
{@code LoginModule}
s.
*/
@Override
public
AppConfigurationEntry
[]
getAppConfigurationEntry
(
String
applicationName
)
{
LinkedList
<
AppConfigurationEntry
>
list
=
null
;
synchronized
(
configuration
)
{
list
=
configuration
.
get
(
applicationName
);
}
if
(
list
==
null
||
list
.
size
()
==
0
)
return
null
;
AppConfigurationEntry
[]
entries
=
new
AppConfigurationEntry
[
list
.
size
()];
Iterator
<
AppConfigurationEntry
>
iterator
=
list
.
iterator
();
for
(
int
i
=
0
;
iterator
.
hasNext
();
i
++)
{
AppConfigurationEntry
e
=
iterator
.
next
();
entries
[
i
]
=
new
AppConfigurationEntry
(
e
.
getLoginModuleName
(),
e
.
getControlFlag
(),
e
.
getOptions
());
}
return
entries
;
return
configFile
.
engineGetAppConfigurationEntry
(
applicationName
);
}
/**
* Refresh and reload the
Configuration
by re-reading all of the
* Refresh and reload the
{@code Configuration}
by re-reading all of the
* login configurations.
*
* <p>
*
* @exception SecurityException if the caller does not have permission
* to refresh the Configuration.
* @throws SecurityException if the caller does not have permission
* to refresh the {@code Configuration}
*/
@Override
public
synchronized
void
refresh
()
{
java
.
lang
.
SecurityManager
sm
=
System
.
getSecurityManager
();
if
(
sm
!=
null
)
sm
.
checkPermission
(
new
AuthPermission
(
"refreshLoginConfiguration"
));
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
try
{
init
(
url
);
}
catch
(
java
.
io
.
IOException
ioe
)
{
throw
(
SecurityException
)
new
SecurityException
(
ioe
.
getLocalizedMessage
()).
initCause
(
ioe
);
}
return
null
;
}
});
}
private
void
readConfig
(
Reader
reader
,
HashMap
<
String
,
LinkedList
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
int
linenum
=
1
;
if
(!(
reader
instanceof
BufferedReader
))
reader
=
new
BufferedReader
(
reader
);
st
=
new
StreamTokenizer
(
reader
);
st
.
quoteChar
(
'"'
);
st
.
wordChars
(
'$'
,
'$'
);
st
.
wordChars
(
'_'
,
'_'
);
st
.
wordChars
(
'-'
,
'-'
);
st
.
lowerCaseMode
(
false
);
st
.
slashSlashComments
(
true
);
st
.
slashStarComments
(
true
);
st
.
eolIsSignificant
(
true
);
lookahead
=
nextToken
();
while
(
lookahead
!=
StreamTokenizer
.
TT_EOF
)
{
parseLoginEntry
(
newConfig
);
}
}
private
void
parseLoginEntry
(
HashMap
<
String
,
LinkedList
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
String
appName
;
String
moduleClass
;
String
sflag
;
AppConfigurationEntry
.
LoginModuleControlFlag
controlFlag
;
LinkedList
<
AppConfigurationEntry
>
configEntries
=
new
LinkedList
<>();
// application name
appName
=
st
.
sval
;
lookahead
=
nextToken
();
if
(
debugParser
!=
null
)
{
debugParser
.
println
(
"\tReading next config entry: "
+
appName
);
}
match
(
"{"
);
// get the modules
while
(
peek
(
"}"
)
==
false
)
{
// get the module class name
moduleClass
=
match
(
"module class name"
);
// controlFlag (required, optional, etc)
sflag
=
match
(
"controlFlag"
);
if
(
sflag
.
equalsIgnoreCase
(
"REQUIRED"
))
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
REQUIRED
;
else
if
(
sflag
.
equalsIgnoreCase
(
"REQUISITE"
))
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
REQUISITE
;
else
if
(
sflag
.
equalsIgnoreCase
(
"SUFFICIENT"
))
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
SUFFICIENT
;
else
if
(
sflag
.
equalsIgnoreCase
(
"OPTIONAL"
))
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
OPTIONAL
;
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Invalid.control.flag.flag"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
sflag
};
throw
new
IOException
(
form
.
format
(
source
));
}
// get the args
HashMap
<
String
,
String
>
options
=
new
HashMap
<>();
String
key
;
String
value
;
while
(
peek
(
";"
)
==
false
)
{
key
=
match
(
"option key"
);
match
(
"="
);
try
{
value
=
expand
(
match
(
"option value"
));
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
throw
new
IOException
(
peee
.
getLocalizedMessage
());
}
options
.
put
(
key
,
value
);
}
lookahead
=
nextToken
();
// create the new element
if
(
debugParser
!=
null
)
{
debugParser
.
println
(
"\t\t"
+
moduleClass
+
", "
+
sflag
);
java
.
util
.
Iterator
<
String
>
i
=
options
.
keySet
().
iterator
();
while
(
i
.
hasNext
())
{
key
=
i
.
next
();
debugParser
.
println
(
"\t\t\t"
+
key
+
"="
+
options
.
get
(
key
));
}
}
AppConfigurationEntry
entry
=
new
AppConfigurationEntry
(
moduleClass
,
controlFlag
,
options
);
configEntries
.
add
(
entry
);
}
match
(
"}"
);
match
(
";"
);
// add this configuration entry
if
(
newConfig
.
containsKey
(
appName
))
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Can.not.specify.multiple.entries.for.appName"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
appName
};
throw
new
IOException
(
form
.
format
(
source
));
}
newConfig
.
put
(
appName
,
configEntries
);
}
private
String
match
(
String
expect
)
throws
IOException
{
String
value
=
null
;
switch
(
lookahead
)
{
case
StreamTokenizer
.
TT_EOF
:
MessageFormat
form1
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.expected.expect.read.end.of.file."
,
"sun.security.util.AuthResources"
));
Object
[]
source1
=
{
expect
};
throw
new
IOException
(
form1
.
format
(
source1
));
case
'"'
:
case
StreamTokenizer
.
TT_WORD
:
if
(
expect
.
equalsIgnoreCase
(
"module class name"
)
||
expect
.
equalsIgnoreCase
(
"controlFlag"
)
||
expect
.
equalsIgnoreCase
(
"option key"
)
||
expect
.
equalsIgnoreCase
(
"option value"
))
{
value
=
st
.
sval
;
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect.found.value."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
'{'
:
if
(
expect
.
equalsIgnoreCase
(
"{"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
';'
:
if
(
expect
.
equalsIgnoreCase
(
";"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
'}'
:
if
(
expect
.
equalsIgnoreCase
(
"}"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
'='
:
if
(
expect
.
equalsIgnoreCase
(
"="
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
default
:
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect.found.value."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
return
value
;
}
private
boolean
peek
(
String
expect
)
{
boolean
found
=
false
;
switch
(
lookahead
)
{
case
','
:
if
(
expect
.
equalsIgnoreCase
(
","
))
found
=
true
;
break
;
case
';'
:
if
(
expect
.
equalsIgnoreCase
(
";"
))
found
=
true
;
break
;
case
'{'
:
if
(
expect
.
equalsIgnoreCase
(
"{"
))
found
=
true
;
break
;
case
'}'
:
if
(
expect
.
equalsIgnoreCase
(
"}"
))
found
=
true
;
break
;
default
:
}
return
found
;
}
private
int
nextToken
()
throws
IOException
{
int
tok
;
while
((
tok
=
st
.
nextToken
())
==
StreamTokenizer
.
TT_EOL
)
{
linenum
++;
}
return
tok
;
}
/*
* Fast path reading from file urls in order to avoid calling
* FileURLConnection.connect() which can be quite slow the first time
* it is called. We really should clean up FileURLConnection so that
* this is not a problem but in the meantime this fix helps reduce
* start up time noticeably for the new launcher. -- DAC
*/
private
InputStream
getInputStream
(
URL
url
)
throws
IOException
{
if
(
"file"
.
equalsIgnoreCase
(
url
.
getProtocol
()))
{
// Compatibility notes:
//
// Code changed from
// String path = url.getFile().replace('/', File.separatorChar);
// return new FileInputStream(path);
//
// The original implementation would search for "/tmp/a%20b"
// when url is "file:///tmp/a%20b". This is incorrect. The
// current codes fix this bug and searches for "/tmp/a b".
// For compatibility reasons, when the file "/tmp/a b" does
// not exist, the file named "/tmp/a%20b" will be tried.
//
// This also means that if both file exists, the behavior of
// this method is changed, and the current codes choose the
// correct one.
try
{
return
url
.
openStream
();
}
catch
(
Exception
e
)
{
String
file
=
url
.
getPath
();
if
(
url
.
getHost
().
length
()
>
0
)
{
// For Windows UNC
file
=
"//"
+
url
.
getHost
()
+
file
;
}
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"cannot read "
+
url
+
", try "
+
file
);
}
return
new
FileInputStream
(
file
);
}
}
else
{
return
url
.
openStream
();
}
}
private
String
expand
(
String
value
)
throws
PropertyExpander
.
ExpandException
,
IOException
{
if
(
""
.
equals
(
value
))
{
return
value
;
}
if
(
expandProp
)
{
String
s
=
PropertyExpander
.
expand
(
value
);
if
(
s
==
null
||
s
.
length
()
==
0
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.system.property.value.expanded.to.empty.value"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
value
};
throw
new
IOException
(
form
.
format
(
source
));
}
return
s
;
}
else
{
return
value
;
}
configFile
.
engineRefresh
();
}
}
src/share/classes/sun/security/provider/ConfigSpiFile.java
浏览文件 @
c3692651
/*
* Copyright (c) 200
5, 2006
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 200
0, 2012
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -25,81 +25,668 @@
package
sun.security.provider
;
import
java.io.*
;
import
java.net.MalformedURLException
;
import
java.net.URI
;
import
java.net.URL
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
import
java.security.PrivilegedActionException
;
import
java.security.PrivilegedExceptionAction
;
import
java.security.Security
;
import
java.security.URIParameter
;
import
java.text.MessageFormat
;
import
java.util.*
;
import
javax.security.auth.AuthPermission
;
import
javax.security.auth.login.AppConfigurationEntry
;
import
javax.security.auth.login.Configuration
;
import
javax.security.auth.login.ConfigurationSpi
;
import
javax.security.auth.login.AppConfigurationEntry
;
import
com.sun.security.auth.login.ConfigFile
;
import
sun.security.util.Debug
;
import
sun.security.util.PropertyExpander
;
import
sun.security.util.ResourcesMgr
;
/**
* This class wraps the ConfigFile subclass implementation of Configuration
* inside a ConfigurationSpi implementation that is available from the
* SUN provider via the Configuration.getInstance calls.
* This class represents a default implementation for
* {@code javax.security.auth.login.Configuration}.
*
* <p> This object stores the runtime login configuration representation,
* and is the amalgamation of multiple static login
* configurations that resides in files.
* The algorithm for locating the login configuration file(s) and reading their
* information into this {@code Configuration} object is:
*
* <ol>
* <li>
* Loop through the security properties,
* <i>login.config.url.1</i>, <i>login.config.url.2</i>, ...,
* <i>login.config.url.X</i>.
* Each property value specifies a <code>URL</code> pointing to a
* login configuration file to be loaded. Read in and load
* each configuration.
*
* <li>
* The {@code java.lang.System} property
* <i>java.security.auth.login.config</i>
* may also be set to a {@code URL} pointing to another
* login configuration file
* (which is the case when a user uses the -D switch at runtime).
* If this property is defined, and its use is allowed by the
* security property file (the Security property,
* <i>policy.allowSystemProperty</i> is set to <i>true</i>),
* also load that login configuration.
*
* <li>
* If the <i>java.security.auth.login.config</i> property is defined using
* "==" (rather than "="), then ignore all other specified
* login configurations and only load this configuration.
*
* <li>
* If no system or security properties were set, try to read from the file,
* ${user.home}/.java.login.config, where ${user.home} is the value
* represented by the "user.home" System property.
* </ol>
*
* <p> The configuration syntax supported by this implementation
* is exactly that syntax specified in the
* {@code javax.security.auth.login.Configuration} class.
*
* @see javax.security.auth.login.LoginContext
* @see java.security.Security security properties
*/
public
final
class
ConfigSpiFile
extends
ConfigurationSpi
{
private
ConfigFile
cf
;
private
URL
url
;
private
boolean
expandProp
=
true
;
private
Map
<
String
,
List
<
AppConfigurationEntry
>>
configuration
;
private
int
linenum
;
private
StreamTokenizer
st
;
private
int
lookahead
;
private
static
Debug
debugConfig
=
Debug
.
getInstance
(
"configfile"
);
private
static
Debug
debugParser
=
Debug
.
getInstance
(
"configparser"
);
/**
* Create a new {@code Configuration} object.
*
* @throws SecurityException if the {@code Configuration} can not be
* initialized
*/
public
ConfigSpiFile
()
{
try
{
init
();
}
catch
(
IOException
ioe
)
{
throw
new
SecurityException
(
ioe
);
}
}
/**
* Create a new {@code Configuration} object from the specified {@code URI}.
*
* @param uri the {@code URI}
* @throws SecurityException if the {@code Configuration} can not be
* initialized
* @throws NullPointerException if {@code uri} is null
*/
public
ConfigSpiFile
(
URI
uri
)
{
// only load config from the specified URI
try
{
url
=
uri
.
toURL
();
init
();
}
catch
(
IOException
ioe
)
{
throw
new
SecurityException
(
ioe
);
}
}
public
ConfigSpiFile
(
final
Configuration
.
Parameters
params
)
throws
java
.
io
.
IOException
{
throws
IOException
{
// call in a doPrivileged
//
// we have already passed the Configuration.getInstance
// security check. also this class is not freely accessible
// (it is in the "sun" package).
//
// we can not put doPrivileged calls into
// ConfigFile because it is a public com.sun class
try
{
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
AccessController
.
doPrivileged
(
new
Privileged
Exception
Action
<
Void
>()
{
public
Void
run
()
throws
IOException
{
if
(
params
==
null
)
{
cf
=
new
ConfigFile
();
init
();
}
else
{
if
(!(
params
instanceof
URIParameter
))
{
throw
new
IllegalArgumentException
(
"Unrecognized parameter: "
+
params
);
}
URIParameter
uriParam
=
(
URIParameter
)
params
;
url
=
uriParam
.
getURI
().
toURL
();
init
();
}
return
null
;
}
});
}
catch
(
PrivilegedActionException
pae
)
{
throw
(
IOException
)
pae
.
getException
();
}
// if init() throws some other RuntimeException,
// let it percolate up naturally.
}
/**
* Read and initialize the entire login Configuration from the configured
* URL.
*
* @throws IOException if the Configuration can not be initialized
* @throws SecurityException if the caller does not have permission
* to initialize the Configuration
*/
private
void
init
()
throws
IOException
{
boolean
initialized
=
false
;
// For policy.expandProperties, check if either a security or system
// property is set to false (old code erroneously checked the system
// prop so we must check both to preserve compatibility).
String
expand
=
Security
.
getProperty
(
"policy.expandProperties"
);
if
(
expand
==
null
)
{
expand
=
System
.
getProperty
(
"policy.expandProperties"
);
}
if
(
"false"
.
equals
(
expand
))
{
expandProp
=
false
;
}
// new configuration
Map
<
String
,
List
<
AppConfigurationEntry
>>
newConfig
=
new
HashMap
<>();
if
(
url
!=
null
)
{
/**
* If the caller specified a URI via Configuration.getInstance,
* we only read from that URI
*/
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"reading "
+
url
);
}
init
(
url
,
newConfig
);
configuration
=
newConfig
;
return
;
}
/**
* Caller did not specify URI via Configuration.getInstance.
* Read from URLs listed in the java.security properties file.
*/
String
allowSys
=
Security
.
getProperty
(
"policy.allowSystemProperty"
);
if
(
"true"
.
equalsIgnoreCase
(
allowSys
))
{
String
extra_config
=
System
.
getProperty
(
"java.security.auth.login.config"
);
if
(
extra_config
!=
null
)
{
boolean
overrideAll
=
false
;
if
(
extra_config
.
startsWith
(
"="
))
{
overrideAll
=
true
;
extra_config
=
extra_config
.
substring
(
1
);
}
try
{
extra_config
=
PropertyExpander
.
expand
(
extra_config
);
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Unable.to.properly.expand.config"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
extra_config
};
throw
new
IOException
(
form
.
format
(
source
));
}
URL
configURL
=
null
;
try
{
configURL
=
new
URL
(
extra_config
);
}
catch
(
MalformedURLException
mue
)
{
File
configFile
=
new
File
(
extra_config
);
if
(
configFile
.
exists
())
{
configURL
=
configFile
.
toURI
().
toURL
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"extra.config.No.such.file.or.directory."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
extra_config
};
throw
new
IOException
(
form
.
format
(
source
));
}
}
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"reading "
+
configURL
);
}
init
(
configURL
,
newConfig
);
initialized
=
true
;
if
(
overrideAll
)
{
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"overriding other policies!"
);
}
configuration
=
newConfig
;
return
;
}
}
}
int
n
=
1
;
String
config_url
;
while
((
config_url
=
Security
.
getProperty
(
"login.config.url."
+
n
))
!=
null
)
{
try
{
config_url
=
PropertyExpander
.
expand
(
config_url
).
replace
(
File
.
separatorChar
,
'/'
);
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"\tReading config: "
+
config_url
);
}
init
(
new
URL
(
config_url
),
newConfig
);
initialized
=
true
;
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Unable.to.properly.expand.config"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
config_url
};
throw
new
IOException
(
form
.
format
(
source
));
}
n
++;
}
if
(
initialized
==
false
&&
n
==
1
&&
config_url
==
null
)
{
// get the config from the user's home directory
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"\tReading Policy "
+
"from ~/.java.login.config"
);
}
config_url
=
System
.
getProperty
(
"user.home"
);
String
userConfigFile
=
config_url
+
File
.
separatorChar
+
".java.login.config"
;
// No longer throws an exception when there's no config file
// at all. Returns an empty Configuration instead.
if
(
new
File
(
userConfigFile
).
exists
())
{
init
(
new
File
(
userConfigFile
).
toURI
().
toURL
(),
newConfig
);
}
}
configuration
=
newConfig
;
}
private
void
init
(
URL
config
,
Map
<
String
,
List
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
try
(
InputStreamReader
isr
=
new
InputStreamReader
(
getInputStream
(
config
),
"UTF-8"
))
{
readConfig
(
isr
,
newConfig
);
}
catch
(
FileNotFoundException
fnfe
)
{
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
fnfe
.
toString
());
}
throw
new
IOException
(
ResourcesMgr
.
getString
(
"Configuration.Error.No.such.file.or.directory"
,
"sun.security.util.AuthResources"
));
}
}
/**
* Retrieve an entry from the Configuration using an application name
* as an index.
*
* @param applicationName the name used to index the Configuration.
* @return an array of AppConfigurationEntries which correspond to
* the stacked configuration of LoginModules for this
* application, or null if this application has no configured
* LoginModules.
*/
@Override
public
AppConfigurationEntry
[]
engineGetAppConfigurationEntry
(
String
applicationName
)
{
List
<
AppConfigurationEntry
>
list
=
null
;
synchronized
(
configuration
)
{
list
=
configuration
.
get
(
applicationName
);
}
if
(
list
==
null
||
list
.
size
()
==
0
)
return
null
;
AppConfigurationEntry
[]
entries
=
new
AppConfigurationEntry
[
list
.
size
()];
Iterator
<
AppConfigurationEntry
>
iterator
=
list
.
iterator
();
for
(
int
i
=
0
;
iterator
.
hasNext
();
i
++)
{
AppConfigurationEntry
e
=
iterator
.
next
();
entries
[
i
]
=
new
AppConfigurationEntry
(
e
.
getLoginModuleName
(),
e
.
getControlFlag
(),
e
.
getOptions
());
}
return
entries
;
}
cf
=
new
ConfigFile
(
uriParam
.
getURI
());
/**
* Refresh and reload the Configuration by re-reading all of the
* login configurations.
*
* @throws SecurityException if the caller does not have permission
* to refresh the Configuration.
*/
@Override
public
synchronized
void
engineRefresh
()
{
SecurityManager
sm
=
System
.
getSecurityManager
();
if
(
sm
!=
null
)
sm
.
checkPermission
(
new
AuthPermission
(
"refreshLoginConfiguration"
));
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
try
{
init
();
}
catch
(
IOException
ioe
)
{
throw
new
SecurityException
(
ioe
.
getLocalizedMessage
(),
ioe
);
}
return
null
;
}
});
}
catch
(
SecurityException
se
)
{
}
// if ConfigFile threw a standalone SecurityException
// (no cause), re-throw it.
//
// ConfigFile chains checked IOExceptions to SecurityException.
private
void
readConfig
(
Reader
reader
,
Map
<
String
,
List
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
linenum
=
1
;
Throwable
cause
=
se
.
getCause
();
if
(
cause
!=
null
&&
cause
instanceof
java
.
io
.
IOException
)
{
throw
(
java
.
io
.
IOException
)
cause
;
if
(!(
reader
instanceof
BufferedReader
))
reader
=
new
BufferedReader
(
reader
);
st
=
new
StreamTokenizer
(
reader
);
st
.
quoteChar
(
'"'
);
st
.
wordChars
(
'$'
,
'$'
);
st
.
wordChars
(
'_'
,
'_'
);
st
.
wordChars
(
'-'
,
'-'
);
st
.
lowerCaseMode
(
false
);
st
.
slashSlashComments
(
true
);
st
.
slashStarComments
(
true
);
st
.
eolIsSignificant
(
true
);
lookahead
=
nextToken
();
while
(
lookahead
!=
StreamTokenizer
.
TT_EOF
)
{
parseLoginEntry
(
newConfig
);
}
}
// unrecognized cause
throw
se
;
private
void
parseLoginEntry
(
Map
<
String
,
List
<
AppConfigurationEntry
>>
newConfig
)
throws
IOException
{
List
<
AppConfigurationEntry
>
configEntries
=
new
LinkedList
<>();
// application name
String
appName
=
st
.
sval
;
lookahead
=
nextToken
();
if
(
debugParser
!=
null
)
{
debugParser
.
println
(
"\tReading next config entry: "
+
appName
);
}
// if ConfigFile throws some other RuntimeException,
// let it percolate up naturally.
match
(
"{"
);
// get the modules
while
(
peek
(
"}"
)
==
false
)
{
// get the module class name
String
moduleClass
=
match
(
"module class name"
);
// controlFlag (required, optional, etc)
AppConfigurationEntry
.
LoginModuleControlFlag
controlFlag
;
String
sflag
=
match
(
"controlFlag"
).
toUpperCase
();
switch
(
sflag
)
{
case
"REQUIRED"
:
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
REQUIRED
;
break
;
case
"REQUISITE"
:
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
REQUISITE
;
break
;
case
"SUFFICIENT"
:
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
SUFFICIENT
;
break
;
case
"OPTIONAL"
:
controlFlag
=
AppConfigurationEntry
.
LoginModuleControlFlag
.
OPTIONAL
;
break
;
default
:
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Invalid.control.flag.flag"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
sflag
};
throw
new
IOException
(
form
.
format
(
source
));
}
// get the args
Map
<
String
,
String
>
options
=
new
HashMap
<>();
while
(
peek
(
";"
)
==
false
)
{
String
key
=
match
(
"option key"
);
match
(
"="
);
try
{
options
.
put
(
key
,
expand
(
match
(
"option value"
)));
}
catch
(
PropertyExpander
.
ExpandException
peee
)
{
throw
new
IOException
(
peee
.
getLocalizedMessage
());
}
}
lookahead
=
nextToken
();
// create the new element
if
(
debugParser
!=
null
)
{
debugParser
.
println
(
"\t\t"
+
moduleClass
+
", "
+
sflag
);
for
(
String
key
:
options
.
keySet
())
{
debugParser
.
println
(
"\t\t\t"
+
key
+
"="
+
options
.
get
(
key
));
}
}
configEntries
.
add
(
new
AppConfigurationEntry
(
moduleClass
,
controlFlag
,
options
));
}
match
(
"}"
);
match
(
";"
);
// add this configuration entry
if
(
newConfig
.
containsKey
(
appName
))
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Can.not.specify.multiple.entries.for.appName"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
appName
};
throw
new
IOException
(
form
.
format
(
source
));
}
newConfig
.
put
(
appName
,
configEntries
);
}
protected
AppConfigurationEntry
[]
engineGetAppConfigurationEntry
(
String
name
)
{
return
cf
.
getAppConfigurationEntry
(
name
);
private
String
match
(
String
expect
)
throws
IOException
{
String
value
=
null
;
switch
(
lookahead
)
{
case
StreamTokenizer
.
TT_EOF
:
MessageFormat
form1
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.expected.expect.read.end.of.file."
,
"sun.security.util.AuthResources"
));
Object
[]
source1
=
{
expect
};
throw
new
IOException
(
form1
.
format
(
source1
));
case
'"'
:
case
StreamTokenizer
.
TT_WORD
:
if
(
expect
.
equalsIgnoreCase
(
"module class name"
)
||
expect
.
equalsIgnoreCase
(
"controlFlag"
)
||
expect
.
equalsIgnoreCase
(
"option key"
)
||
expect
.
equalsIgnoreCase
(
"option value"
))
{
value
=
st
.
sval
;
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect.found.value."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
protected
void
engineRefresh
()
{
cf
.
refresh
();
case
'{'
:
if
(
expect
.
equalsIgnoreCase
(
"{"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
';'
:
if
(
expect
.
equalsIgnoreCase
(
";"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
'}'
:
if
(
expect
.
equalsIgnoreCase
(
"}"
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
case
'='
:
if
(
expect
.
equalsIgnoreCase
(
"="
))
{
lookahead
=
nextToken
();
}
else
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
break
;
default
:
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.expected.expect.found.value."
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
expect
,
st
.
sval
};
throw
new
IOException
(
form
.
format
(
source
));
}
return
value
;
}
private
boolean
peek
(
String
expect
)
{
boolean
found
=
false
;
switch
(
lookahead
)
{
case
','
:
if
(
expect
.
equalsIgnoreCase
(
","
))
found
=
true
;
break
;
case
';'
:
if
(
expect
.
equalsIgnoreCase
(
";"
))
found
=
true
;
break
;
case
'{'
:
if
(
expect
.
equalsIgnoreCase
(
"{"
))
found
=
true
;
break
;
case
'}'
:
if
(
expect
.
equalsIgnoreCase
(
"}"
))
found
=
true
;
break
;
default
:
}
return
found
;
}
private
int
nextToken
()
throws
IOException
{
int
tok
;
while
((
tok
=
st
.
nextToken
())
==
StreamTokenizer
.
TT_EOL
)
{
linenum
++;
}
return
tok
;
}
private
InputStream
getInputStream
(
URL
url
)
throws
IOException
{
if
(
"file"
.
equalsIgnoreCase
(
url
.
getProtocol
()))
{
// Compatibility notes:
//
// Code changed from
// String path = url.getFile().replace('/', File.separatorChar);
// return new FileInputStream(path);
//
// The original implementation would search for "/tmp/a%20b"
// when url is "file:///tmp/a%20b". This is incorrect. The
// current codes fix this bug and searches for "/tmp/a b".
// For compatibility reasons, when the file "/tmp/a b" does
// not exist, the file named "/tmp/a%20b" will be tried.
//
// This also means that if both file exists, the behavior of
// this method is changed, and the current codes choose the
// correct one.
try
{
return
url
.
openStream
();
}
catch
(
Exception
e
)
{
String
file
=
url
.
getPath
();
if
(
url
.
getHost
().
length
()
>
0
)
{
// For Windows UNC
file
=
"//"
+
url
.
getHost
()
+
file
;
}
if
(
debugConfig
!=
null
)
{
debugConfig
.
println
(
"cannot read "
+
url
+
", try "
+
file
);
}
return
new
FileInputStream
(
file
);
}
}
else
{
return
url
.
openStream
();
}
}
private
String
expand
(
String
value
)
throws
PropertyExpander
.
ExpandException
,
IOException
{
if
(
value
.
isEmpty
())
{
return
value
;
}
if
(
expandProp
)
{
String
s
=
PropertyExpander
.
expand
(
value
);
if
(
s
==
null
||
s
.
length
()
==
0
)
{
MessageFormat
form
=
new
MessageFormat
(
ResourcesMgr
.
getString
(
"Configuration.Error.Line.line.system.property.value.expanded.to.empty.value"
,
"sun.security.util.AuthResources"
));
Object
[]
source
=
{
new
Integer
(
linenum
),
value
};
throw
new
IOException
(
form
.
format
(
source
));
}
return
s
;
}
else
{
return
value
;
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录