SlideShare a Scribd company logo
245 | P a g e
If we consider vulnerability origin as a whole (according to classification in Appendix 2) we’ll see that
vulnerabilities caused by insufficient administration are 20% more frequent (P. 5). At the same time, there
are up to 4 issues per site caused by administration flaws and up to 8 vulnerabilities caused by design
errors (T. 2).
T. 2 The probability to detect vulnerabilities depending on vulnerability origin
No. of Vulns No. of Sites % Vulns % Sites No. Vulns on Site
Vulnerability in administration 41859 10347 42.91% 84.91% 4.05
Vulnerability in code 55695 7023 57.09% 57.63% 7.93
Less than 60% of vulnerabilities are in
code
246 | P a g e
P. 5 The probability to detect vulnerabilities depending on their origin
Detailed web application analysis by black box and white box methods shows that appreciable percent of
sites are vulnerable to Content Spoofing and Path Traversal (P. 6), and the probability to detect a
vulnerability of SQL Injection type reaches 19% in this approach (P. 7).
P. 6 The most widespread vulnerabilities in web applications (% Vulns BlackBox & WhiteBox)
247 | P a g e
P. 7 The probability to detect the most widespread vulnerabilities in web applications (% Sites BlackBox
& WhiteBox)
P. 8 Percent of vulnerabilities out of total number of vulnerabilities (% Vulns BlackBox & WhiteBox)
If we consider the prevalence of high risk level vulnerabilities in detailed web application analysis (P. 9)
we’ll see that the most widespread is Credential/Session Prediction errors. SQL Injection, Path Traversal
248 | P a g e
and implementation and configuration errors in authentication and authorization systems are also
widespread.
P. 9 The probability to detect the most risky vulnerabilities in Web applications (% Sites BlackBox &
WhiteBox)
If we consider the probability to detect vulnerabilities in terms of web resource visitors and web server
impact (according to classification in appendix 2), the server-side vulnerabilities are the most widespread
(P. 10). But the vulnerability distribution by impact type per site is irregular and greatly depends on used
vulnerability search method (P. 11).
249 | P a g e
P. 10 The probability to detect vulnerability by impact type
Whitebox approach (dynamic or static) is
Required to catch vulnerabilities
250 | P a g e
P. 11.Vulnerabilities per site by different search methods (No. Vulns on Site)
T. 3 Vulnerabilities by impact
No. of Vulns No. of Sites %
Vulns
% Sites No. Vulns on Site
ALL Stat (Server-Side) 50856 10125 52.13% 83.09% 5.02
ALL Stat (Client-Side) 46698 7580 47.87% 62.20% 6.16
Scans (Server-Side) 19746 8922 55.60% 85.40% 2.21
Scans (Client-Side) 15767 6607 44.40% 63.24% 2.39
BlackBox (Server-Side) 4260 804 23.77% 76.86% 5.30
BlackBox (Client-Side) 13665 747 76.23% 71.41% 18.29
WhiteBox (Server-Side) 17700 145 63.73% 96.67% 122.07
WhiteBox (Client-Side) 10072 117 36.27% 78.00% 86.09
251 | P a g e
Data analysis according to PCI DSS requirements
If we consider data sets about vulnerable Web applications according to PCI DSS requirements, we can
easily sort (T. 4) those that are about certain vulnerability elimination in Web applications. In addition, PCI
DSS Technical and Operational Requirements for Approved Scanning Vendors (ASVs) includes similar
requirements but affects only ASV scanning by PCI (T. 5).
T. 4 PCI DSS requirements for Web application security
PCI DSS v.1.2 requirements
Procedure
6.5 Develop all web applications
(internal and external, and including web
administrative access to application)
based on secure coding guidelines such
as the Open Web Application Security
Project Guide. Cover prevention of
common coding vulnerabilities in
software development processes, to
include the following:
-
6.5.1 Cross-site scripting (XSS) 6.5.1 Cross-site scripting (XSS) (Validate all
parameters before inclusion.)
6.5.2 Injection flaws, particularly SQL
injection. Also consider LDAP and Xpath
injection flaws as well as other injection
flaws.
6.5.2 Injection flaws, particularly SQL injection
(Validate input to verify user data cannot modify
meaning of commands and queries.)
6.5.3 Malicious file execution 6.5.3 Malicious file execution (Validate input to verify
application does not accept filenames or files from
users.)
6.5.5 Cross-site request forgery (CSRF) 6.5.5 Cross-site request forgery (CSRF) (Do not reply
on authorization credentials and tokens automatically
submitted by browsers.)
6.5.6 Information leakage and improper 6.5.6 Information leakage and improper error
252 | P a g e
error handling handling (Do not leak information via error messages
or other means.)
6.5.7 Broken authentication and session
management
6.5.7 Broken authentication and session management
(Properly authenticate users and protect account
credentials and session tokens.)
6.5.9 Insecure communications 6.5.9 Insecure communications (Properly encrypt all
authenticated and sensitive communications.)
6.6 For public-facing web
applications, address new threats and
vulnerabilities on an ongoing basis and
ensure these applications are protected
against known attacks by either of the
following methods:
- Reviewing public-facing web
applications via manual or
automated application vulnerability
security assessment tools or
methods, at least annually and
after any changes
- Installing a web-application firewall
in front of public-facing web
applications
-
T. 5 PCI DSS Technical and Operational Requirements for Approved Scanning Vendors (ASVs) for WEB
Technical and Operational
Requirements for Approved
Scanning Vendors (ASVs) v.1.1
Procedure
Web Server Check The ASV scanning solution must be able to test for all known
vulnerabilities and configuration issues on web servers. New
exploits are routinely discovered in web server products. The ASV
scanning solution must be able to detect and report known
exploits.
253 | P a g e
Browsing of directories on a web server is not a good practice.
The ASV scanning solution must be able to scan the web site and
verify that directory browsing is not possible on the server.
The ASV scanning solution must be able to detect all known CGI
vulnerabilities.
Custom Web Application Check The ASV scanning solution must be able to detect the following
application vulnerabilities and configuration issues:
• Unvalidated parameters which lead to SQL injection attacks
• Cross-site scripting (XSS) flaws
Assessing collected data statistics by criteria from T. 4 and T. 5, we conclude the following (see T. 6 and P.
12 – 14).
T. 6 % of sites which are not complaint to PCI DSS requirements in Web application scanning methods
PCI DSS v.1.2
requirement
Non
compliant. ALL
(% Sites)
Non
compliant. Scans
(% Sites)
Non compliant.
BlackBox (% Sites)
Non
compliant. WhiteBox
(% Sites)
6.5.1 Cross-site scripting
(XSS)
38.45% 37.66% 56.41% 58.67%
6.5.2 Injection flaws.
particularly SQL
injection. Also consider
LDAP and Xpath injection
flaws as well as other
injection flaws.
14.55% 12.70% 19.31% 64.00%
6.5.3 Malicious file
execution
0.94% 0.08% 1.05% 8.67%
6.5.5 Cross-site request
forgery (CSRF)
1.32% 0.02% 7.93% 0.67%
6.5.6 Information
leakage and improper
error handling
66.67% 74.05% 38.24% 54.00%
254 | P a g e
6.5.7 Broken
authentication and
session management
7.62% 0.52% 30.98% 71.33%
6.5.9 Insecure
communications
34.42% 39.96% 0.00%* 17.33%
Technical and
Operational
Requirements for
Approved Scanning
Vendors (ASVs) v.1.1
Web Server Check Inapplicable 5.73% Inapplicable Inapplicable
Custom Web Application
Check
Inapplicable 44.92% Inapplicable Inapplicable
* Vulnerability of this class are not incuded into reports during web application security assessment by
black box method.
P 12. The distribution of sites non compliant to PCI DSS
255 | P a g e
P 13.Compliance level of Web application to PCI DSS (QSA) requirements
P 14. Compliance level of Web application to PCI DSS (ASV) requirements
256 | P a g e
Thus, more than 48 % of scanned Web applications are not compliant to PCI DSS requirements by ASV
scanning. Meanwhile, deeper analysis shows that 99% of Web applications are not complaint to the
standard requirements.
APPENDIX 1: RISK ASSESSMENT METHODOLOGY
T. 8 Risk level assessment routine
Threat Classification
Basic CVSS Score PCI DSS Risk
Abuse of Functionality 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium
Brute Force Attack 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
Buffer Overflow 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Content Spoofing 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High
Credential/Session Prediction 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
Cross-Site Scripting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical
Cross-Site Request Forgery 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High
Denial of Service 7.8 (AV:N/AC:L/Au:N/C:N/I:N/A:C) High
Format String Attack 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
HTTP Request Splitting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical
HTTP Response Splitting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical
HTTP Request Smuggling 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical
HTTP Response Smuggling 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical
Integer Overflow 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
LDAP Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Mail Command Injection 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High
OS Commanding 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Path Traversal 7.8 (AV:N/AC:L/Au:N/C:C/I:N/A:N) Critical
Predictable Resource Location 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
Remote File Inclusion 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
257 | P a g e
Routing Detour 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
SOAP Array Abuse 7.8 (AV:N/AC:L/Au:N/C:N/I:N/A:C) High
SSI Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Session Fixation 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
SQL Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
URL Redirectors 2.6 (AV:N/AC:H/Au:N/C:N/I:P/A:N) Medium
XPath Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
XML Attribute Blowup 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
XML External Entity 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
XML Entity Expansion 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
XML Injection 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P) Critical
XQuery Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Application Misconfiguration 5.1 (AV:N/AC:H/Au:N/C:P/I:P/A:P) Medium
Directory Indexing 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
Fingerprinting 0 (AV:N/AC:L/Au:N/C:N/I:N/A:N) Low
Improper Parsing 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Improper Permissions 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
Information leakage 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
Insecure Indexing 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
Insufficient Anti-automation 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium
Insufficient Authentication 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
Insufficient Authorization 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
Insufficient Data Protection 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High
Insufficient Process Validation 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium
Insufficient Session Expiration 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical
Insufficient Transport Layer
Protection
4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium
Server Misconfiguration 5.1 (AV:N/AC:H/Au:N/C:P/I:P/A:P) Medium
258 | P a g e
APPENDIX 2: ADDITIONAL VULNERABILITY CLASSIFICATION
T. 9 Vulnerability classification by origin and impact
Threat Classification
Vulnerability in Impact
Abuse of Functionality code server-side
Brute Force Attack administration server-side
Buffer Overflow code server-side
Content Spoofing code client-side
Credential/Session Prediction code server-side
Cross-Site Scripting code client-side
Cross-Site Request Forgery code client-side
Denial of Service administration server-side
Format String Attack code server-side
HTTP Request Splitting code client-side
HTTP Response Splitting code client-side
HTTP Request Smuggling administration client-side
HTTP Response Smuggling administration client-side
Integer Overflow code server-side
LDAP Injection code server-side
Mail Command Injection code server-side
OS Commanding code server-side
Path Traversal code server-side
Predictable Resource Location administration server-side
Remote File Inclusion code server-side
Routing Detour code server-side
SOAP Array Abuse code server-side
SSI Injection code server-side
259 | P a g e
Session Fixation code server-side
SQL Injection code server-side
URL Redirectors code client-side
XPath Injection code server-side
XML Attribute Blowup code server-side
XML External Entity code server-side
XML Entity Expansion code server-side
XML Injection code server-side
XQuery Injection code server-side
Application Misconfiguration administration server-side
Directory Indexing administration server-side
Fingerprinting administration server-side
Improper Parsing code server-side
Improper Permissions administration server-side
Information leakage administration server-side
Insecure Indexing administration server-side
Insufficient Anti-automation code server-side
Insufficient Authentication code server-side
Insufficient Authorization code server-side
Insufficient Data Protection administration server-side
Insufficient Process Validation code server-side
Insufficient Session Expiration code server-side
Insufficient Transport Layer Protection administration client-side
Server Misconfiguration administration server-side
APPENDIX 3: STATISTICS
Overall Data
T. 10 General statistics Threat Classification
260 | P a g e
Threat Classification
N of Vulns N of Sites Vulns% Sites%
Abuse of Functionality 153 83 0.16% 0.68%
Brute Force Attack 79 51 0.08% 0.42%
Buffer Overflow 537 84 0.55% 0.69%
Content Spoofing 1564 304 1.60% 2.49%
Credential/Session Prediction 794 147 0.81% 1.21%
Cross-Site Scripting 37624 4686 38.57% 38.45%
Cross-Site Request Forgery 285 161 0.29% 1.32%
Denial of Service 42 36 0.04% 0.30%
Format String Attack 52 43 0.05% 0.35%
HTTP Request Splitting 311 162 0.32% 1.33%
HTTP Response Splitting 2592 161 2.66% 1.32%
HTTP Request Smuggling 0 0 0.00% 0.00%
HTTP Response Smuggling 0 0 0.00% 0.00%
Integer Overflow 79 46 0.08% 0.38%
LDAP Injection 41 16 0.04% 0.13%
Mail Command Injection 1 1 0.00% 0.01%
OS Commanding 76 30 0.08% 0.25%
Path Traversal 1563 139 1.60% 1.14%
Predictable Resource Location 1507 295 1.54% 2.42%
Remote File Inclusion 99 44 0.10% 0.36%
Routing Detour 0 0 0.00% 0.00%
SOAP Array Abuse 2 1 0.00% 0.01%
SSI Injection 157 33 0.16% 0.27%
Session Fixation 137 123 0.14% 1.01%
SQL Injection 6345 1555 6.50% 12.76%
URL Redirectors 5 4 0.01% 0.03%
261 | P a g e
XPath Injection 64 19 0.07% 0.16%
XML Attribute Blowup 0 0 0.00% 0.00%
XML External Entity 0 0 0.00% 0.00%
XML Entity Expansion 0 0 0.00% 0.00%
XML Injection 0 0 0.00% 0.00%
XQuery Injection 0 0 0.00% 0.00%
Application Misconfiguration 85 60 0.09% 0.49%
Directory Indexing 370 184 0.38% 1.51%
Fingerprinting 3663 3604 3.75% 29.57%
Improper Parsing 1464 524 1.50% 4.30%
Improper Permissions 4 4 0.00% 0.03%
Information leakage 31527 7942 32.32% 65.17%
Insecure Indexing 8 7 0.01% 0.06%
Insufficient Anti-automation 108 36 0.11% 0.30%
Insufficient Authentication 806 304 0.83% 2.49%
Insufficient Authorization 615 286 0.63% 2.35%
Insufficient Data Protection 64 21 0.07% 0.17%
Insufficient Process Validation 52 34 0.05% 0.28%
Insufficient Session Expiration 169 71 0.17% 0.58%
Insufficient Transport Layer Protection 4317 4195 4.43% 34.42%
Server Misconfiguration 193 113 0.20% 0.93%
Total 97554 12186
T. 11 Vulnerabilities distribution by risk Threat rank
Threat rank
N of Vulns N of Sites Vulns% % Sites
Urgent 8918 2287 9.14% 18.77%
Critical 44669 5511 45.79% 45.22%
High 35375 8807 36.26% 72.27%
262 | P a g e
Medium 4908 4455 5.03% 36.56%
Low 3663 3618 3.75% 29.69%
Automatic scans
T. 12 General statistics Threat Classification
Threat Classification
N of Vulns N of
Sites
Vulns% Sites%
Abuse of Functionality 1 1 0.00% 0.01%
Brute Force Attack 5 5 0.01% 0.05%
Buffer Overflow 6 3 0.02% 0.03%
Content Spoofing 29 22 0.08% 0.21%
Credential/Session Prediction 9 9 0.03% 0.09%
Cross-Site Scripting 11230 3934 31.62% 37.66%
Cross-Site Request Forgery 2 2 0.01% 0.02%
Denial of Service 30 25 0.08% 0.24%
Format String Attack 0 0 0.00% 0.00%
HTTP Request Splitting 311 162 0.88% 1.55%
HTTP Response Splitting 0 0 0.00% 0.00%
HTTP Request Smuggling 0 0 0.00% 0.00%
HTTP Response Smuggling 0 0 0.00% 0.00%
Integer Overflow 0 0 0.00% 0.00%
LDAP Injection 0 0 0.00% 0.00%
Mail Command Injection 0 0 0.00% 0.00%
OS Commanding 28 5 0.08% 0.05%
Path Traversal 82 56 0.23% 0.54%
Predictable Resource Location 16 15 0.05% 0.14%
Remote File Inclusion 86 36 0.24% 0.34%
Routing Detour 0 0 0.00% 0.00%
263 | P a g e
SOAP Array Abuse 0 0 0.00% 0.00%
SSI Injection 157 33 0.44% 0.32%
Session Fixation 3 3 0.01% 0.03%
SQL Injection 2969 1217 8.36% 11.65%
URL Redirectors 1 1 0.00% 0.01%
XPath Injection 0 0 0.00% 0.00%
XML Attribute Blowup 0 0 0.00% 0.00%
XML External Entity 0 0 0.00% 0.00%
XML Entity Expansion 0 0 0.00% 0.00%
XML Injection 0 0 0.00% 0.00%
XQuery Injection 0 0 0.00% 0.00%
Application Misconfiguration 48 37 0.14% 0.35%
Directory Indexing 12 11 0.03% 0.11%
Fingerprinting 3604 3587 10.15% 34.34%
Improper Parsing 1463 523 4.12% 5.01%
Improper Permissions 2 2 0.01% 0.02%
Information leakage 11134 7593 31.35% 72.68%
Insecure Indexing 8 7 0.02% 0.07%
Insufficient Anti-automation 0 0 0.00% 0.00%
Insufficient Authentication 24 15 0.07% 0.14%
Insufficient Authorization 14 14 0.04% 0.13%
Insufficient Data Protection 10 10 0.03% 0.10%
Insufficient Process Validation 12 11 0.03% 0.11%
Insufficient Session Expiration 1 1 0.00% 0.01%
Insufficient Transport Layer Protection 4194 4175 11.81% 39.96%
Server Misconfiguration 22 22 0.06% 0.21%
Total 35513 10447
264 | P a g e
T. 13 Vulnerabilities distribution by risk Threat rank
Threat rank
N of Vulns N of Sites Vulns% % Sites
Urgent 4711 1745 13.27% 16.70%
Critical 11679 4100 32.89% 39.25%
High 11257 7636 31.70% 73.09%
Medium 4294 4199 12.09% 40.19%
Low 3625 3599 10.21% 34.45%
Black Box
T. 14 General statistics Threat Classification
Threat Classification
N of Vulns N of
Sites
Vulns% Sites%
Abuse of Functionality 135 75 0.75% 7.17%
Brute Force Attack 34 29 0.19% 2.77%
Buffer Overflow 0 0 0.00% 0.00%
Content Spoofing 1110 241 6.19% 23.04%
Credential/Session Prediction 15 12 0.08% 1.15%
Cross-Site Scripting 11768 590 65.65% 56.41%
Cross-Site Request Forgery 185 83 1.03% 7.93%
Denial of Service 9 8 0.05% 0.76%
Format String Attack 2 2 0.01% 0.19%
HTTP Request Splitting 0 0 0.00% 0.00%
HTTP Response Splitting 601 77 3.35% 7.36%
HTTP Request Smuggling 0 0 0.00% 0.00%
HTTP Response Smuggling 0 0 0.00% 0.00%
Integer Overflow 9 6 0.05% 0.57%
LDAP Injection 0 0 0.00% 0.00%
Mail Command Injection 0 0 0.00% 0.00%
265 | P a g e
OS Commanding 16 11 0.09% 1.05%
Path Traversal 29 20 0.16% 1.91%
Predictable Resource Location 855 155 4.77% 14.82%
Remote File Inclusion 3 3 0.02% 0.29%
Routing Detour 0 0 0.00% 0.00%
SOAP Array Abuse 0 0 0.00% 0.00%
SSI Injection 0 0 0.00% 0.00%
Session Fixation 83 79 0.46% 7.55%
SQL Injection 1556 169 8.68% 16.16%
URL Redirectors 1 1 0.01% 0.10%
XPath Injection 59 17 0.33% 1.63%
XML Attribute Blowup 0 0 0.00% 0.00%
XML External Entity 0 0 0.00% 0.00%
XML Entity Expansion 0 0 0.00% 0.00%
XML Injection 0 0 0.00% 0.00%
XQuery Injection 0 0 0.00% 0.00%
Application Misconfiguration 31 20 0.17% 1.91%
Directory Indexing 104 42 0.58% 4.02%
Fingerprinting 1 1 0.01% 0.10%
Improper Parsing 1 1 0.01% 0.10%
Improper Permissions 2 2 0.01% 0.19%
Information leakage 745 399 4.16% 38.15%
Insecure Indexing 0 0 0.00% 0.00%
Insufficient Anti-automation 6 4 0.03% 0.38%
Insufficient Authentication 158 90 0.88% 8.60%
Insufficient Authorization 312 155 1.74% 14.82%
Insufficient Data Protection 2 2 0.01% 0.19%
Insufficient Process Validation 5 5 0.03% 0.48%
266 | P a g e
Insufficient Session Expiration 30 27 0.17% 2.58%
Insufficient Transport Layer Protection 0 0 0.00% 0.00%
Server Misconfiguration 58 38 0.32% 3.63%
Total 17925 1046
T. 15 Vulnerabilities distribution by risk Threat rank
Threat rank
N of Vulns N of Sites Vulns% % Sites
Urgent 1648 206 9.19% 19.69%
Critical 13030 782 72.69% 74.76%
High 3011 612 16.80% 58.51%
Medium 235 126 1.31% 12.05%
Low 1 1 0.01% 0.10%
White Box
T. 16 General statistics Threat Classification
Threat Classification
N of Vulns N of Sites Vulns% Sites%
Abuse of Functionality 7 4 0.03% 2.67%
Brute Force Attack 15 11 0.05% 7.33%
Buffer Overflow 421 1 1.52% 0.67%
Content Spoofing 0 0 0.00% 0.00%
Credential/Session Prediction 695 66 2.50% 44.00%
Cross-Site Scripting 8006 88 28.83% 58.67%
Cross-Site Request Forgery 2 1 0.01% 0.67%
Denial of Service 3 3 0.01% 2.00%
Format String Attack 2 1 0.01% 0.67%
HTTP Request Splitting 0 0 0.00% 0.00%
HTTP Response Splitting 1941 54 6.99% 36.00%
267 | P a g e
HTTP Request Smuggling 0 0 0.00% 0.00%
HTTP Response Smuggling 0 0 0.00% 0.00%
Integer Overflow 0 0 0.00% 0.00%
LDAP Injection 0 0 0.00% 0.00%
Mail Command Injection 1 1 0.00% 0.67%
OS Commanding 29 12 0.10% 8.00%
Path Traversal 1450 59 5.22% 39.33%
Predictable Resource Location 15 13 0.05% 8.67%
Remote File Inclusion 3 2 0.01% 1.33%
Routing Detour 0 0 0.00% 0.00%
SOAP Array Abuse 0 0 0.00% 0.00%
SSI Injection 0 0 0.00% 0.00%
Session Fixation 1 1 0.00% 0.67%
SQL Injection 898 59 3.23% 39.33%
URL Redirectors 0 0 0.00% 0.00%
XPath Injection 0 0 0.00% 0.00%
XML Attribute Blowup 0 0 0.00% 0.00%
XML External Entity 0 0 0.00% 0.00%
XML Entity Expansion 0 0 0.00% 0.00%
XML Injection 0 0 0.00% 0.00%
XQuery Injection 0 0 0.00% 0.00%
Application Misconfiguration 1 1 0.00% 0.67%
Directory Indexing 2 2 0.01% 1.33%
Fingerprinting 8 6 0.03% 4.00%
Improper Parsing 0 0 0.00% 0.00%
Improper Permissions 0 0 0.00% 0.00%
Information leakage 13598 81 48.96% 54.00%
Insecure Indexing 0 0 0.00% 0.00%
268 | P a g e
Insufficient Anti-automation 2 2 0.01% 1.33%
Insufficient Authentication 324 45 1.17% 30.00%
Insufficient Authorization 89 6 0.32% 4.00%
Insufficient Data Protection 52 9 0.19% 6.00%
Insufficient Process Validation 5 3 0.02% 2.00%
Insufficient Session Expiration 78 28 0.28% 18.67%
Insufficient Transport Layer Protection 123 26 0.44% 17.33%
Server Misconfiguration 1 1 0.00% 0.67%
Total 27772 150
T. 17 Vulnerabilities distribution by risk Threat rank
Threat rank
N of Vulns N of Sites Vulns% % Sites
Urgent 1353 75 4.87% 50.00%
Critical 12599 138 45.37% 92.00%
High 13673 93 49.23% 62.00%
Medium 139 36 0.50% 24.00%
Low 8 6 0.03% 4.00%
269 | P a g e
OWASP Application Security Verification Standard (ASVS)
Types of security verification
 In addition, in ASVS
 level 3 is “Design Verification” (manual)
 level 4 is “Internal Verification” (manual)
ASVS
 High-level requirements
 Detailed requirements
270 | P a g e
 Reporting requirements
 “Tools are an important part of every ASVS level. At higher levels in ASVS, the use of
tools is encouraged. But to be effective, the tools must be heavily tailored and
configured to the application and framework in use. And, at all levels, tool results must
be manually verified.”
ASVS Detailed requirements
 V1. Security Architecture
 V2. Authentication
 V3. Session Management
 V4. Access Control
 V5. Input Validation
 V6. Output Encoding/Escaping
 V7. Cryptography
 V8. Error Handling and Logging
 V9. Data Protection
 V10. Communication Security
 V11. HTTP Security
 V12. Security Configuration
 V13. Malicious Code Search
 V14. Internal Security
271 | P a g e
ASVS Verification Requirements Matrix
272 | P a g e
Quasi-scientific quantitative matrix analysis
Examples of what requirements CAN be verified by automatic code scan
 [V5.2] Verify that a positive validation pattern is defined and applied to all input.
 [V6.1] Verify that all untrusted data that are output to HTML (including HTML elements,
HTML attributes, JavaScript data values, CSS blocks, and URI attributes) are properly
escaped for the applicable context.
 [V8.1] Verify that that the application does not output error messages containing
sensitive data that could assist an attacker, including session id and personal
information.
 [V11.2] Verify that the application accepts only a defined set of HTTP request methods,
such as GET and POST.
Examples of what requirements CANNOT be verified using automated code
scan
273 | P a g e
 [V2.5] Verify that all authentication controls (including libraries that call external
authentication services) have a centralized implementation.
 [V2.13] Verify that account passwords are salted using a salt that is unique to that
account (e.g., internal user ID, account creation) and hashed before storing.
 [V4.4] Verify that direct object references are protected, such that only authorized
objects are
 accessible to each user. (This can be of course checked dynamically.)
 [V5.7] Verify that all input validation failures are logged.
 [V8.6] Verify that each log event includes: 1. a time stamp from a reliable source, 2.
severity level of the event […] and 7. a description of the event.
 [V9.2] Verify that the list of sensitive data processed by this application is identified, and
that there is an explicit policy for how access to this data must be controlled, and when
this data must be encrypted (both at rest and in transit). Verify that this policy is
properly enforced.
 [V14.2] Verify that security control interfaces are simple enough to use that developers
are likely to use them correctly. (This is a level 4 requirement.)
Problems in automatic source code scan
 A static analyzer cannot step back and look at the big picture, e.g. architectural layers
 Evaluating non-functional security is almost impossible, e.g. robustness against DoS
attack
 Logic flaws (e.g. in authorization) or missing security requirements cannot be detected
 Significant parts of the code may be missed completely, e.g. when in a different
language or IoC/plugin code
 Configuration analysis may be problematic as Well
Mixing automation and manual work
 Manual code review on paper is pain!
 Tools are of great value, e.g.:
 An IDE for traversing code (esp. jumping between caller and callee)
 Grep or similar to quickly get pointers to interesting places and getting overview of
technology used
 Manual testing is good match for manual code review, and for that good tools (e.g.
browser plugins) are essential
274 | P a g e
From manual review to automation
 Build automated checks for manual findings
 Doing this statically is not easy without proper tools
 Dynamic approach may be easier, e.g. targeted
 automated scan or unit tests
Conclusion
 When, where and how to use automated tools?
 Web portals implemented on a known and robust platform using systematic access
control may be very good candidates:
 Typical findings would be injection problems
 Probably not much privacy or business assets to protect
 Complex business web application (e.g. extranet application) could be harder to verify:
o Logical checks, privacy more delicate
o Scalability and transactions to think of
 Choice of verification methodology based on risk analysis
 Automatic code scan can give a rough measurement of a system even when run un-
configured
 Automatic code scanning is best combined with manual inspection, and/or as part of
development build cycle
 Scanner needs to be properly configured, though
275 | P a g e
Using Automatic Tools to Discover Java Security & Reliability Vulnerabilities
Fortify 360:
276 | P a g e
277 | P a g e
Another Example:
278 | P a g e
279 | P a g e
280 | P a g e
281 | P a g e
Weak XML Schema: Type Any
282 | P a g e
283 | P a g e
Weak XML Schema: Lax Processing
284 | P a g e
285 | P a g e
Passwords stored in clear text/base64 in code:
286 | P a g e
Unreleased Resource Streams
287 | P a g e
288 | P a g e
289 | P a g e
Null Dereference
290 | P a g e
291 | P a g e
Path Manipulation
292 | P a g e
293 | P a g e
Most Common False Positive:
Real Case:
294 | P a g e
Log Forging
295 | P a g e
296 | P a g e
297 | P a g e
Command Injection
298 | P a g e
299 | P a g e
Often Misused: Authentication
300 | P a g e
301 | P a g e
Unreleased Resource: Database
302 | P a g e
303 | P a g e
New object is created on each for loop iteration object is never closed
304 | P a g e
Denial Of Service
305 | P a g e
306 | P a g e
307 | P a g e
Password Management: Hardcoded Password
308 | P a g e
309 | P a g e
SQL Injection: iBatis Data Map
310 | P a g e
311 | P a g e
Common Java Code Security Pitfalls
FindBugs (1.2.1-dev-20070506) Analysis for jdk1.7.0-b12
Bug Summary Analysis Information List bugs by bug category List bugs
1. Bad practice (954: 118/836/0/0)
1.1. BC: Bad casts of object references (5: 1/4/0/0)
1.2. Equals method should not assume anything about the type of its argument (4:
0/4/0/0)
2. Random object created and used only once (1: 1/0/0/0)
3. CN: Bad implementation of cloneable idiom (50: 0/50/0/0)
4. Class implements Cloneable but does not define or use clone method (14: 0/14/0/0)
5. clone method does not call super.clone() (36: 0/36/0/0)
6. Co: Problems with compareTo() (1: 0/1/0/0)
7. Covariant compareTo() method defined (1: 0/1/0/0)
8. DE: Dropped or ignored exception (50: 3/47/0/0)
9. Method might ignore exception (50: 3/47/0/0)
10. Dm: Dubious method used (3: 0/3/0/0)
11. Method invokes System.exit(...) (3: 0/3/0/0)
12. Eq: Problems with equals() (20: 1/19/0/0)
13. Class defines compareTo(...) and uses Object.equals() (14: 0/14/0/0)
14. Covariant equals() method defined, Object.equals(Object) inherited (6: 1/5/0/0)
15. ES: Checking String equality using == or != (133: 42/91/0/0)
16. Comparison of String parameter using == or != (92: 42/50/0/0)
17. Comparison of String objects using == or != (41: 0/41/0/0)
312 | P a g e
18. FI: Incorrect use of finalizers (12: 0/12/0/0)
19. Empty finalizer should be deleted (2: 0/2/0/0)
20. Finalizer does not call superclass finalizer (1: 0/1/0/0)
21. Finalizer nullifies superclass finalizer (9: 0/9/0/0)
22. HE: Equal objects must have equal hashcodes (200: 22/178/0/0)
23. Class defines equals() but not hashCode() (6: 0/6/0/0)
24. Class defines equals() and uses Object.hashCode() (41: 22/19/0/0)
25. Class inherits equals() and uses Object.hashCode() (153: 0/153/0/0)
26. It: Incorrect definition of Iterator (2: 0/2/0/0)
27. Iterator next() method can't throw NoSuchElement exception (2: 0/2/0/0)
28. Nm: Confusing method name (101: 0/101/0/0)
29. Class names should start with an upper case letter (8: 0/8/0/0)
30. Class is not derived from an Exception, even though it is named as such (9: 0/9/0/0)
31. Field names should start with an lower case letter (1: 0/1/0/0)
32. Method names should start with an lower case letter (69: 0/69/0/0)
33. Very confusing method names (but intentional) (14: 0/14/0/0)
34. NP: Null pointer dereference (16: 0/16/0/0)
35. Clone method may return null (4: 0/4/0/0)
36. equals() method does not check for null argument (10: 0/10/0/0)
37. toString method may return null (2: 0/2/0/0)
38. NS: Suspicious use of non-short-circuit boolean operator (1: 0/1/0/0)
39. Questionable use of non-short-circuit logic (1: 0/1/0/0)
40. OS: Stream not closed on all paths (14: 0/14/0/0)
41. Method may fail to close stream (14: 0/14/0/0)
42. RR: Method ignores results of InputStream.read() (29: 0/29/0/0)
43. Method ignores results of InputStream.read() (10: 0/10/0/0)
44. Method ignores results of InputStream.skip() (19: 0/19/0/0)
45. Se: Incorrect definition of Serializable class (275: 49/226/0/0)
46. Non-transient non-serializable instance field in serializable class (206: 20/186/0/0)
47. Non-serializable class has a serializable inner class (3: 0/3/0/0)
48. Non-serializable value stored into instance field of a serializable class (8: 2/6/0/0)
49. Comparator doesn't implement Serializable (11: 0/11/0/0)
50. Class is Serializable but its superclass doesn't define a void constructor (6: 6/0/0/0)
51. Class is Externalizable but doesn't define a void constructor (2: 0/2/0/0)
52. Transient field that isn't set by deserialization. (39: 21/18/0/0)
53. SnVI: Serializable class with no Version ID (42: 0/42/0/0)
53.1. Class is Serializable, but doesn't define serialVersionUID (42: 0/42/0/0)
54. Correctness (249: 81/168/0/0)
55. BC: Bad casts of object references (4: 1/3/0/0)
56. Impossible cast (1: 1/0/0/0)
313 | P a g e
57. instanceof will always return false (3: 0/3/0/0)
58. Bx: Questionable Boxing of primitive value (1: 0/1/0/0)
59. Primitive value is unboxed and coerced for ternary operator (1: 0/1/0/0)
60. DMI: Dubious method invocation (17: 0/17/0/0)
61. Invocation of toString on an array (17: 0/17/0/0)
62. EC: Suspicious equals() comparison (3: 2/1/0/0)
63. Call to equals() with null argument (1: 0/1/0/0)
64. Call to equals() comparing different types (2: 2/0/0/0)
65. FE: Test for floating point equality (6: 6/0/0/0)
66. Doomed test for equality to NaN (6: 6/0/0/0)
67. ICAST: Casting from integer values (5: 5/0/0/0)
68. int value cast to double and then passed to Math.ceil (3: 3/0/0/0)
69. int value cast to float and then passed to Math.round (2: 2/0/0/0)
70. IP: Ignored parameter (2: 0/2/0/0)
71. A parameter is dead upon entry to a method but overwritten (2: 0/2/0/0)
72. MF: Masked Field (16: 8/8/0/0)
73. Class defines field that masks a superclass field (16: 8/8/0/0)
74. Nm: Confusing method name (3: 2/1/0/0)
75. Class defines hashcode(); should it be hashCode()? (1: 1/0/0/0)
76. Apparent method/constructor confusion (1: 0/1/0/0)
77. Very confusing method names (1: 1/0/0/0)
78. NP: Null pointer dereference (69: 17/52/0/0)
79. Null pointer dereference (4: 4/0/0/0)
80. Null value is guaranteed to be dereferenced (5: 3/2/0/0)
81. A known null value is checked to see if it is an instance of a type (3: 0/3/0/0)
82. Possible null pointer dereference (22: 5/17/0/0)
83. Possible null pointer dereference in method on exception path (14: 0/14/0/0)
84. Method call passes null for unconditionally dereferenced parameter (13: 4/9/0/0)
85. Non-virtual method call passes null for unconditionally dereferenced parameter (1:
1/0/0/0)
86. Read of unwritten field (7: 0/7/0/0)
87. NS: Suspicious use of non-short-circuit boolean operator (4: 4/0/0/0)
88. Potentially dangerous use of non-short-circuit logic (4: 4/0/0/0)
89. RC: Suspicious reference comparison (8: 0/8/0/0)
90. Suspicious reference comparison (8: 0/8/0/0)
91. RCN: Redundant comparison to null (35: 10/25/0/0)
92. Nullcheck of value previously dereferenced (35: 10/25/0/0)
93. RV: Bad use of return value from method (7: 3/4/0/0)
94. Method ignores return value (7: 3/4/0/0)
95. SA: Useless self-operation (14: 12/2/0/0)
314 | P a g e
96. Double assignment of field (1: 0/1/0/0)
97. Self assignment of field (1: 0/1/0/0)
98. Self comparison of value with itself (12: 12/0/0/0)
99. SF: Switch case falls through (3: 3/0/0/0)
100. Dead store due to switch statement fall through (3: 3/0/0/0)
101. UCF: Useless control flow (1: 1/0/0/0)
102. Useless control flow to next line (1: 1/0/0/0)
103. UMAC: Uncallable method of anonymous class (6: 6/0/0/0)
104. Uncallable method defined in anonymous class (6: 6/0/0/0)
105. UR: Uninitialized read of field in constructor (5: 0/5/0/0)
106. Uninitialized read of field in constructor (5: 0/5/0/0)
107. UwF: Unwritten field (40: 1/39/0/0)
107.1.1. Field only ever set to null (6: 1/5/0/0)
107.1.2. Unwritten field (34: 0/34/0/0)
108. Multithreaded correctness (272: 1/271/0/0)
108.1. DC: Possible double check of field (76: 0/76/0/0)
108.2. Possible double check of field (76: 0/76/0/0)
108.3. IS: Inconsistent synchronization (121: 0/121/0/0)
108.4. Inconsistent synchronization (121: 0/121/0/0)
108.5. LI: Unsynchronized Lazy Initialization (1: 0/1/0/0)
108.6. Incorrect lazy initialization of static field (1: 0/1/0/0)
108.7. ML: Synchronization on updated field (Mutable Lock) (3: 0/3/0/0)
108.8. Method synchronizes on an updated field (3: 0/3/0/0)
108.9. MWN: Mismatched wait() or notify() (1: 0/1/0/0)
108.10. Mismatched wait() (1: 0/1/0/0)
108.11. NN: Naked notify (9: 0/9/0/0)
108.12. Naked notify (9: 0/9/0/0)
108.13. RS: Class's readObject() method is synchronized (9: 0/9/0/0)
108.14. Class's readObject() method is synchronized (9: 0/9/0/0)
108.15. Ru: Method invokes run() (1: 0/1/0/0)
108.16. Invokes run on a thread (did you mean to start it instead?) (1: 0/1/0/0)
108.17. SC: Constructor invokes Thread.start() (4: 0/4/0/0)
108.18. Constructor invokes Thread.start() (4: 0/4/0/0)
108.19. SWL: Sleep with lock held (2: 0/2/0/0)
108.20. Method calls Thread.sleep() with a lock held (2: 0/2/0/0)
108.21. TLW: Wait with two locks held (1: 1/0/0/0)
108.22. Wait with two locks held (1: 1/0/0/0)
108.23. UG: Unsynchronized get method, synchronized set method (25: 0/25/0/0)
108.24. Unsynchronized get method, synchronized set method (25: 0/25/0/0)
315 | P a g e
108.25. UL: Lock not released on all paths (3: 0/3/0/0)
108.26. Method does not release lock on all exception paths (3: 0/3/0/0)
108.27. UW: Unconditional wait (6: 0/6/0/0)
108.28. Unconditional wait (6: 0/6/0/0)
108.29. VO: Use of volatile (2: 0/2/0/0)
108.29.1. A volatile reference to an array doesn't treat the array elements as
volatile (2: 0/2/0/0)
108.30. Wa: Wait not in loop (8: 0/8/0/0)
108.31. Wait not in loop (8: 0/8/0/0)
109. Performance (1772: 7/1765/0/0)
109.1. Bx: Questionable Boxing of primitive value (1095: 0/1095/0/0)
109.2. Primitive value is boxed then unboxed to perform primative coercion (1:
0/1/0/0)
109.3. Method invokes inefficient Number constructor; use static valueOf instead
(1094: 0/1094/0/0)
109.4. Dm: Dubious method used (153: 7/146/0/0)
109.5. Method invokes inefficient Boolean constructor; use Boolean.valueOf(...)
instead (65: 0/65/0/0)
109.6. Explicit garbage collection; extremely dubious except in benchmarking code (1:
1/0/0/0)
109.7. Method invokes inefficient new String(String) constructor (65: 0/65/0/0)
109.8. Method invokes toString() method on a String (11: 0/11/0/0)
109.9. Method invokes inefficient new String() constructor (5: 0/5/0/0)
109.10. The equals and hashCode methods of URL are blocking (6: 6/0/0/0)
109.11. SBSC: String concatenation in loop using + operator (40: 0/40/0/0)
109.12. Method concatenates strings using + in a loop (40: 0/40/0/0)
109.13. SIC: Inner class could be made static (144: 0/144/0/0)
109.14. Should be a static inner class (144: 0/144/0/0)
109.15. SS: Unread field should be static (54: 0/54/0/0)
109.16. Unread field: should this field be static? (54: 0/54/0/0)
109.17. UPM: Private method is never called (19: 0/19/0/0)
109.18. Private method is never called (19: 0/19/0/0)
109.19. UrF: Unread field (216: 0/216/0/0)
109.20. Unread field (216: 0/216/0/0)
109.21. UuF: Unused field (43: 0/43/0/0)
109.22. Unused field (43: 0/43/0/0)
109.23. WMI: Wrong Map Iterator (8: 0/8/0/0)
109.23.1. Inefficient use of keySet iterator instead of entrySet iterator (8:
0/8/0/0)
110. Dodgy (654: 52/602/0/0)
316 | P a g e
110.1. BC: Bad casts of object references (32: 1/31/0/0)
110.2. Unchecked/unconfirmed cast (24: 1/23/0/0)
110.3. instanceof will always return true (8: 0/8/0/0)
110.4. DB: Duplicate Branches (13: 0/13/0/0)
110.5. Method uses the same code for two branches (13: 0/13/0/0)
110.6. DLS: Dead local store (283: 27/256/0/0)
110.7. Dead store to local variable (283: 27/256/0/0)
110.8. DMI: Dubious method invocation (9: 0/9/0/0)
110.9. Code contains a hard coded reference to an absolute pathname (2: 0/2/0/0)
110.10. Non serializable object written to ObjectOutput (3: 0/3/0/0)
110.11. Invocation of substring(0), which returns the original value (4: 0/4/0/0)
110.12. FE: Test for floating point equality (8: 7/1/0/0)
110.13. Test for floating point equality (8: 7/1/0/0)
110.14. IC: Initialization circularity (10: 0/10/0/0)
110.15. Initialization circularity (10: 0/10/0/0)
110.16. ICAST: Casting from integer values (12: 0/12/0/0)
110.17. int division result cast to double or float (8: 0/8/0/0)
110.18. Result of integer multiplication cast to long (3: 0/3/0/0)
110.19. Unsigned right shift cast to short/byte (1: 0/1/0/0)
110.20. IM: Questionable integer math (28: 0/28/0/0)
110.21. Computation of average could overflow (21: 0/21/0/0)
110.22. Check for oddness that won't work for negative numbers (7: 0/7/0/0)
110.23. INT: Suspicious integer expression (1: 0/1/0/0)
110.24. Vacuous comparison of integer value (1: 0/1/0/0)
110.25. NP: Null pointer dereference (52: 0/52/0/0)
110.26. Immediate dereference of the result of readLine() (2: 0/2/0/0)
110.27. Load of known null value (43: 0/43/0/0)
110.28. Possible null pointer dereference due to return value of called method (7:
0/7/0/0)
110.29. RCN: Redundant comparison to null (21: 0/21/0/0)
110.30. Redundant comparison of two null values (2: 0/2/0/0)
110.31. Redundant nullcheck of value known to be non-null (14: 0/14/0/0)
110.32. Redundant nullcheck of value known to be null (5: 0/5/0/0)
110.33. REC: RuntimeException capture (90: 0/90/0/0)
110.34. Exception is caught when Exception is not thrown (90: 0/90/0/0)
110.35. SF: Switch case falls through (51: 3/48/0/0)
110.36. Switch statement found where one case falls through to the next case (51:
3/48/0/0)
110.37. ST: Misuse of static fields (44: 14/30/0/0)
110.38. Write to static field from instance method (44: 14/30/0/0)
317 | P a g e
318 | P a g e
OWASP ESASPI 2
http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html
svn checkout http://owasp-esapi-java.googlecode.com/svn/trunk/ owasp-esapi-java-read-only
ESAPI 2.0.1 API
Packages
org.owasp.esapi
The ESAPI interfaces
and Exception classes model the most
important security functions to
enterprise web applications.
org.owasp.esapi.codecs
This package contains codecs for
application layer encoding/escaping
schemes that can be used for both
canonicalization and output encoding.
org.owasp.esapi.crypto
This package contains ESAPI
cryptography-related classes used
throughout ESAPI.
org.owasp.esapi.errors
A set of exception classes designed to
model the error conditions that
frequently arise in enterprise web
applications and web services.
org.owasp.esapi.filters
This package contains several filters
that demonstrate ways of using the
ESAPI security controls in front of your
application.
org.owasp.esapi.reference
This package contains reference
implementations of the ESAPI
interfaces.
org.owasp.esapi.reference.accesscontrol
319 | P a g e
org.owasp.esapi.reference.accesscontrol.policyloader
org.owasp.esapi.reference.crypto
This package contains the reference
implementation for some of the ESAPI
cryptography-related classes used
throughout ESAPI.
org.owasp.esapi.reference.validation
This package contains data format-
specific validation rule functions.
org.owasp.esapi.tags
This package contains sample JSP tags
that demonstrate how to use the ESAPI
functions to protect an application from
within a JSP page.
org.owasp.esapi.util
This package contains ESAPI utility
classes used throughout the reference
implementation of ESAPI but may also
be directly useful.
org.owasp.esapi.waf
This package contains the ESAPI Web
Application Firewall (WAF).
org.owasp.esapi.waf.actions
This package contains the Action
objects that are executed after a Rule
subclass executes.
org.owasp.esapi.waf.configuration
This package contains the both the
configuration object model and the
utility class to create that object model
from an existing policy file.
org.owasp.esapi.waf.internal
This package contains all HTTP-related
classes used internally by the WAF for
the implementation of its rules.
org.owasp.esapi.waf.rules This package contains all of the Rule
subclasses that correspond to policy file
320 | P a g e
entries.
321 | P a g e
Java & OpenSSO
Harden OpenSSO By Disabling ssoadm.jsp
Notwithstanding that it is still a secret, we've just added a property that allows you to disable
the ssoadm.jsp to harden your system and reduce attack vectors. The property is
ssoadm.disabled and can be added with a value of true to the Advanced properties.
Log into the OpenSSO console as administrator.
Click the Configuration tab.
Click the Servers and Sites tab.
Click the Server name in the Servers table.
Click the Advanced tab.
Click Add in the Advanced Properties table.
Enter ssoadm.disabled as the Property Name and true as the Property Value.
Click Save.
You can also add this property as a default setting for future server configurations by clicking the
Default Server Settings button under the Servers and Sites tab.
Importing the Root CA Certificate for Secure OpenSSO Rainbow Connections
When configuring OpenSSO for a scenario that involves a secure connection (SSL or LDAPS) and
multiple JVMs, you need to import the root CA certificate into the JVM trust store (by default
JAVA_HOME/jre/lib/security/cacerts) and restart the OpenSSO web container before
performing any configurations.
For example, to configure a second instance of OpenSSO in a defined Site (when the first
instance of OpenSSO is SSL-enabled), the root Certificate Authority (CA) certificate for the first
OpenSSO server certificate must be imported into the JVM key store of the web container in
which the second instance of OpenSSO is deployed. (Restart the web container of the second
instance after the import.)
An example of a command to import a root CA certificate to this key store is:
keytool -import -v -alias alias -keystore JAVA_HOME/jre/lib/security/cacerts -storepass changeit
-file CAcert.crt
Use the following command to verify that the root CA certificate was imported correctly.
322 | P a g e
keytool -list -keystore JAVA_HOME/jre/lib/security/cacerts -storepass changeit
RedHat Security
JBoss Software & Platform Provider
323 | P a g e
324 | P a g e
325 | P a g e
326 | P a g e
327 | P a g e
328 | P a g e
329 | P a g e
330 | P a g e
331 | P a g e
332 | P a g e
333 | P a g e
334 | P a g e
335 | P a g e
JBOSS Security
What is JBoss
JBoss Application Server (or JBoss AS) is a free software/open-source Java EE-based application server.
An important distinction for this class of software is that it not only implements a server that runs on Java,
but it actually implements the Java EE part of Java. Because it is Java-based, the JBoss application server
operates cross-platform: usable on any operating system that supports Java. JBoss AS was developed
by JBoss, now a division of Red Hat.
J2EE Security Configuration and Architecture
Security is a fundamental part of any enterprise application. You need to be
able to restrict who is allowed to access your applications and control what
operations application users may perform. The J2EE specifications define a
simple role-based security model for EJBs and web components. The JBoss
component framework that handles security is the JBossSX extension
336 | P a g e
framework. The JBossSX security extension provides support for both the role-
based declarative J2EE security model as well as integration of custom security
via a security proxy layer. The default implementation of the declarative
security model is based on Java Authentication and Authorization Service
(JAAS) login modules and subjects. The security proxy layer allows custom
security that cannot be described using the declarative model to be added to
an EJB in a way that is independent of the EJB business object. Before getting
into the JBoss security implementation details, we will revie EJB and Servlet
specification security models as well as JAAS to establish the foundation for
these details.
8.1. J2EE Declarative Security Overview
The security model advocated by the J2EE specification is a declarative model.
It is declarative in that you describe the security roles and permissions using a
standard XML descriptor rather than embedding security into your business
component. This isolates security from business-level code because security
tends to be a more a function of where the component is deployed, rather
than an inherent aspect of the component's business logic. For example,
consider an ATM component that is to be used to access a bank account. The
security requirements, roles and permissions will vary independent of how
one accesses the bank account based on what bank is managing the account,
where the ATM machine is deployed, and so on.
Securing a J2EE application is based on the specification of the application
security requirements via the standard J2EE deployment descriptors. You
secure access to EJBs and web components in an enterprise application by
using the ejb-jar.xml and web.xml deployment descriptors. Figure 8.1, “A
subset of the EJB 2.0 deployment descriptor content model that shows the
security related elements.” and Figure 8.2, “A subset of the Servlet 2.2
deployment descriptor content model that shows the security related
elements.” illustrate the security-related elements in the EJB 2.0 and Servlet
2.2 deployment descriptors, respectively.
337 | P a g e
Figure 8.1. A subset of the EJB 2.0 deployment descriptor content model that
shows the security related elements.
338 | P a g e
Figure 8.2. A subset of the Servlet 2.2 deployment descriptor content model
that shows the security related elements.
The purpose and usage of the various security elements given in Figure 8.1, “A
subset of the EJB 2.0 deployment descriptor content model that shows the
security related elements.” and Figure 8.2, “A subset of the Servlet 2.2
deployment descriptor content model that shows the security related
elements.” is discussed in the following subsections.
339 | P a g e
8.1.1. Security References
Both EJBs and servlets may declare one or more security-role-ref elements. This
element is used to declare that a component is using the role-name value as
an argument to the isCallerInRole(String) method. Using the isCallerInRole method, a
component can verify if the caller is in a role that has been declared with
a security-role-ref/role-name element. The role-name element value must link to
a security-role element through the role-link element. The typical use ofisCallerInRole is
to perform a security check that cannot be defined using the role based method-
permissions elements. However, use of isCallerInRole is discouraged because this
results in security logic embedded inside of the component code. Example
descriptor fragments that illustrate the security-role-ref element usage are
presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which
illustrate the security-role element usage.” and Example 8.5, “An example
web.xml descriptor fragment which illustrate the security-role element
usage.”.
Example 8.1. An example ejb-jar.xml descriptor fragments which illustrate
the security-role-ref element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ASessionBean</ejb-name>
...
<security-role-ref>
<role-name>TheRoleICheck</role-name>
<role-link>TheApplicationRole</role-link>
</security-role-ref>
</session>
</enterprise-beans>
...
</ejb-jar>
Example 8.2. An example web.xml descriptor fragments which illustrate the
security-role-ref element usage.
<web-app>
<servlet>
<servlet-name>AServlet</servlet-name>
...
<security-role-ref>
340 | P a g e
<role-name>TheServletRole</role-name>
<role-link>TheApplicationRole</role-link>
</security-role-ref>
</servlet>
...
</web-app>
8.1.2. Security Identity
EJBs can optionally declare a security-identity element. New to EJB 2.0 is the
capability to specify what identity an EJB should use when it invokes methods
on other components. The invocation identity can be that of the current caller,
or a specific role. The application assembler uses the security-identity element
with a use-caller-identity child element to indicate the current caller's identity
should be propagated as the security identity for method invocations made by
the EJB. Propagation of the caller's identity is the default used in the absence
of an explicit security-identity element declaration.
Alternatively, the application assembler can use the run-as/role-name child
element to specify that a specific security role given by the role-name value
should be used as the security identity for method invocations made by the
EJB. Note that this does not change the caller's identity as seen
by EJBContext.getCallerPrincipal(). Rather, the caller's security roles are set to the
single role specified by the run-as/role-name element value. One use case for
the run-as element is to prevent external clients from accessing internal EJBs.
This is accomplished by assigning the internal EJB method-permission elements
that restrict access to a role never assigned to an external client. EJBs that
need to use internal EJB are then configured with a run-as/role-nameequal to the
restricted role. An example descriptor fragment that illustrates security-
identity element usage is presented in Example 8.3, “An example ejb-jar.xml
descriptor fragment which illustrates the security-identity element usage.”.
Example 8.3. An example ejb-jar.xml descriptor fragment which illustrates
the security-identity element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ASessionBean</ejb-name>
<!-- ... -->
341 | P a g e
<security-identity>
<use-caller-identity/>
</security-identity>
</session>
<session>
<ejb-name>RunAsBean</ejb-name>
<!-- ... -->
<security-identity>
<run-as>
<description>A private internal role</description>
<role-name>InternalRole</role-name>
</run-as>
</security-identity>
</session>
</enterprise-beans>
<!-- ... -->
</ejb-jar>
8.1.3. Security roles
The security role name referenced by either the security-role-ref or security-
identity element needs to map to one of the application's declared roles. An
application assembler defines logical security roles by declaring security-
role elements. Therole-name value is a logical application role name like
Administrator, Architect, SalesManager, etc.
What is a role? The J2EE specifications note that it is important to keep in
mind that the security roles in the deployment descriptor are used to define
the logical security view of an application. Roles defined in the J2EE
deployment descriptors should not be confused with the user groups, users,
principals, and other concepts that exist in the target enterprise's operational
environment. The deployment descriptor roles are application constructs with
application domain specific names. For example, a banking application might
use role names like BankManager, Teller, and Customer.
In JBoss, a security-role is only used to map security-role-ref/role-name values to the
logical role that the component role referenced. The user's assigned roles are
a dynamic function of the application's security manager, as you will see when
we discuss the JBossSX implementation details. JBoss does not require the
definition of security-roles in order to declare method permissions. Therefore, the
specification of security-role elements is simply a good practice to ensure
portability across application servers and for deployment descriptor
342 | P a g e
maintenance. Example descriptor fragments that illustrate security-role usage are
presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which
illustrate the security-role element usage.”and Example 8.5, “An example
web.xml descriptor fragment which illustrate the security-role element
usage.”.
Example 8.4. An example ejb-jar.xml descriptor fragments which illustrate
the security-role element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<!-- ... -->
<assembly-descriptor>
<security-role>
<description>The single application role</description>
<role-name>TheApplicationRole</role-name>
</security-role>
</assembly-descriptor>
</ejb-jar>
Example 8.5. An example web.xml descriptor fragment which illustrate the
security-role element usage.
<!-- A sample web.xml fragment -->
<web-app>
<!-- ... -->
<security-role>
<description>The single application role</description>
<role-name>TheApplicationRole</role-name>
</security-role>
</web-app>
8.1.4. EJB method permissions
An application assembler can set the roles that are allowed to invoke an EJB's
home and remote interface methods through method-permission element
declarations. Each method-permission element contains one or more role-name
child elements that define the logical roles allowed access the EJB methods as
identified by method child elements. As of EJB 2.0, you can now specify an
unchecked element instead of the role-name element to declare that any
authenticated user can access the methods identified by method child
elements. In addition, you can declare that no one should have access to a
method with the exclude-list element. If an EJB has methods that have not been
343 | P a g e
declared as accessible by a role using a method-permission element, the EJB
methods default to being excluded from use. This is equivalent to defaulting
the methods into the exclude-list.
There are three supported styles of method element declarations.
 Style 1 is used for referring to all of the home and component interface
methods of the named enterprise bean.
<method>
<ejb-name>EJBNAME</ejb-name>
<method-name>*</method-name>
</method>
 Style 2 is used for referring to a specified method of the home or
component interface of the named enterprise bean. If there are
multiple methods with the same overloaded name, this style refers to
all of the overloaded methods.
<method>
<ejb-name>EJBNAME</ejb-name>
<method-name>METHOD</method-name>
</method>
 Style 3 is used to refer to a specified method within a set of methods
with an overloaded name. The method must be defined in the specified
enterprise bean's home or remote interface. The method-param
element values are the fully qualified name of the corresponding
method parameter type. If there are multiple methods with the same
overloaded signature, the permission applies to all of the matching
overloaded methods.
<method>
<ejb-name>EJBNAME</ejb-name>
<method-name>METHOD</method-name>
<method-params>
<method-param>PARAMETER_1</method-param>
<!-- ... -->
<method-param>PARAMETER_N</method-param>
</method-params>
</method>
344 | P a g e
The optional method-intf element can be used to differentiate methods with
the same name and signature that are defined in both the home and remote
interfaces of an enterprise bean. Example 8.6, “An example ejb-jar.xml
descriptor fragment which illustrates the method-permission element
usage.” provides examples of the method-permission element usage.
Example 8.6. An example ejb-jar.xml descriptor fragment which illustrates
the method-permission element usage.
<ejb-jar>
<assembly-descriptor>
<method-permission>
<description>The employee and temp-employee roles may access any
method of the EmployeeService bean </description>
<role-name>employee</role-name>
<role-name>temp-employee</role-name>
<method>
<ejb-name>EmployeeService</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>The employee role may access the findByPrimaryKey,
getEmployeeInfo, and the updateEmployeeInfo(String) method of
the AardvarkPayroll bean </description>
<role-name>employee</role-name>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>findByPrimaryKey</method-name>
</method>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>getEmployeeInfo</method-name>
</method>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>updateEmployeeInfo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>
</method-permission>
<method-permission>
<description>The admin role may access any method of the
EmployeeServiceAdmin bean </description>
<role-name>admin</role-name>
<method>
345 | P a g e
<ejb-name>EmployeeServiceAdmin</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>Any authenticated user may access any method of the
EmployeeServiceHelp bean</description>
<unchecked/>
<method>
<ejb-name>EmployeeServiceHelp</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<exclude-list>
<description>No fireTheCTO methods of the EmployeeFiring bean may be
used in this deployment</description>
<method>
<ejb-name>EmployeeFiring</ejb-name>
<method-name>fireTheCTO</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>
8.1.5. Web Content Security Constraints
In a web application, security is defined by the roles allowed access to content
by a URL pattern that identifies the protected content. This set of information
is declared using the web.xml security-constraint element. The content to be secured
is declared using one or more web-resource-collection elements. Each web-resource-
collection element contains an optional series of url-pattern elements followed by
an optional series of http-method elements. The url-pattern element value specifies
a URL pattern against which a request URL must match for the request to
correspond to an attempt to access secured content. The http-method element
value specifies a type of HTTP request to allow.
The optional user-data-constraint element specifies the requirements for the
transport layer of the client to server connection. The requirement may be for
content integrity (preventing data tampering in the communication process)
or for confidentiality (preventing reading while in transit). The transport-
guarantee element value specifies the degree to which communication
between client and server should be protected. Its values are NONE, INTEGRAL,
or CONFIDENTIAL. A value of NONE means that the application does not require any
transport guarantees. A value of INTEGRAL means that the application requires
346 | P a g e
the data sent between the client and server be sent in such a way that it can't
be changed in transit. A value of CONFIDENTIAL means that the application
requires the data be transmitted in a fashion that prevents other entities from
observing the contents of the transmission. In most cases, the presence of
the INTEGRAL or CONFIDENTIAL flag indicates that the use of SSL is required.
The optional login-config is used to configure the authentication method that
should be used, the realm name that should be used for this application, and
the attributes that are needed by the form login mechanism. The auth-
method child element specifies the authentication mechanism for the web
application. As a prerequisite to gaining access to any web resources that are
protected by an authorization constraint, a user must have authenticated
using the configured mechanism. Legal values for auth-method
areBASIC, DIGEST, FORM, or CLIENT-CERT. The realm-name child element specifies the
realm name to use in HTTP basic and digest authorization. The form-login-
config child element specifies the log in as well as error pages that should be
used in form-based login. If the auth-method value is not FORM, form-login-config and
its child elements are ignored.
As an example, the web.xml descriptor fragment given in Example 8.7, “ A
web.xml descriptor fragment which illustrates the use of the security-
constraint and related elements.” indicates that any URL lying under the web
application /restricted path requires an AuthorizedUser role. There is no required
transport guarantee and the authentication method used for obtaining the
user identity is BASIC HTTP authentication.
Example 8.7. A web.xml descriptor fragment which illustrates the use of the
security-constraint and related elements.
<web-app>
<!-- ... -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Content</web-resource-name>
<url-pattern>/restricted/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>AuthorizedUser</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
347 | P a g e
</user-data-constraint>
</security-constraint>
<!-- ... -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>The Restricted Zone</realm-name>
</login-config>
<!-- ... -->
<security-role>
<description>The role required to access restricted content </description>
<role-name>AuthorizedUser</role-name>
</security-role>
</web-app>
8.1.6. Enabling Declarative Security in JBoss
The J2EE security elements that have been covered describe only the security
requirements from the application's perspective. Since J2EE security elements
declare logical roles, the application deployer maps the roles from the
application domain onto the deployment environment. The J2EE specifications
omit these application-server-specific details. In JBoss, mapping the
application roles onto the deployment environment entails specifying a
security manager that implements the J2EE security model using JBoss server
specific deployment descriptors. We will avoid discussion the details of this
step for now. The details behind the security configuration will be discussed
when we describe the generic JBoss server security interfaces in Section 8.3,
“The JBoss Security Model”.
8.2. An Introduction to JAAS
The default implementation of the JBossSX framework is based on the JAAS
API. It is important that you understand the basic elements of the JAAS API to
understand the implementation details of JBossSX. This section provides an
introduction to JAAS to prepare you for the JBossSX architecture discussion.
Additional details on the JAAS package can be found at the JAAS home page
at: http://java.sun.com/products/jaas/.
348 | P a g e
8.2.1. What is JAAS?
The JAAS 1.0 API consists of a set of Java packages designed for user
authentication and authorization. It implements a Java version of the standard
Pluggable Authentication Module (PAM) framework and compatibly extends
the Java 2 Platform's access control architecture to support user-based
authorization. JAAS was first released as an extension package for JDK 1.3 and
is bundled with JDK 1.4+. Because the JBossSX framework uses only the
authentication capabilities of JAAS to implement the declarative role-based
J2EE security model, this introduction focuses on only that topic.
Much of this section's material is derived from the JAAS 1.0 Developers Guide,
so if you are familiar with its content you can skip ahead to the JBossSX
architecture discussion in Section 8.4, “The JBoss Security Extension
Architecture”
JAAS authentication is performed in a pluggable fashion. This permits Java
applications to remain independent from underlying authentication
technologies and allows the JBossSX security manager to work in different
security infrastructures. Integration with a security infrastructure can be
achieved without changing the JBossSX security manager implementation. All
that needs to change is the configuration of the authentication stack that JAAS
uses.
8.2.1.1. The JAAS Core Classes
The JAAS core classes can be broken down into three categories: common,
authentication, and authorization. The following list presents only the
common and authentication classes because these are the specific classes
used to implement the functionality of JBossSX covered in this chapter.
Common classes:
 Subject (javax.security.auth.Subject)
 Principal (java.security.Principal)
Authentication classes:
349 | P a g e
 Callback (javax.security.auth.callback.Callback)
 CallbackHandler (javax.security.auth.callback.CallbackHandler)
 Configuration (javax.security.auth.login.Configuration)
 LoginContext (javax.security.auth.login.LoginContext)
 LoginModule (javax.security.auth.spi.LoginModule)
8.2.1.1.1. Subject and Principal
To authorize access to resources, applications first need to authenticate the
request's source. The JAAS framework defines the term subject to represent a
request's source. The Subject class is the central class in JAAS.
A Subject represents information for a single entity, such as a person or service.
It encompasses the entity's principals, public credentials, and private
credentials. The JAAS APIs use the existing Java 2 java.security.Principal interface to
represent a principal, which is essentially just a typed name.
During the authentication process, a subject is populated with associated
identities, or principals. A subject may have many principals. For example, a
person may have a name principal (John Doe), a social security number
principal (123-45-6789), and a username rincipal (johnd), all of which help
distinguish the subject from other subjects. To retrieve the principals
associated with a swubject, two methods are available:
public Set getPrincipals() {...}
public Set getPrincipals(Class c) {...}
The first method returns all princiaps contained in the subject. The second
method only returns those principals that are instances of Class c or one of its
subclasses. An empty set will be returned if the subject has no matching
principals. Note that thejava.security.acl.Group interface is a subinterface
of java.security.Principal, and so an instance in the principals set may represent a
logical grouping of other principals or groups of principals.
8.2.1.1.2. Authentication of a Subject
Authentication of a subject requires a JAAS login. The login procedure consists
of the following steps:
350 | P a g e
 An application instantiates a LoginContext passing in the name of the login
configuration and a CallbackHandler to populate the Callback objects as
required by the configuration LoginModules.
 The LoginContext consults a Configuration to load all of
the LoginModules included in the named login configuration. If no such
named configuration exists the other configuration is used as a default.
 The application invokes the LoginContext.login method.
 The login method invokes all the loaded LoginModules. As
each LoginModule attempts to authenticate the subject, it invokes the
handle method on the associated CallbackHandler to obtain the information
required for the authentication process. The required information is
passed to the handle method in the form of an array of Callback objects.
Upon success, the LoginModules associate relevant principals and
credentials with the subject.
 The LoginContext returns the authentication status to the application.
Success is represented by a return from the login method. Failure is
represented through a LoginException being thrown by the login
method.
 If authentication succeeds, the application retrieves the authenticated
subject using the LoginContext.getSubject method.
 After the scope of the subject authentication is complete, all principals
and related information associated with the subject by the login
method may be removed by invoking the LoginContext.logout method.
The LoginContext class provides the basic methods for authenticating subjects
and offers a way to develop an application independent of the underlying
authentication technology. The LoginContext consults a Configuration to determine
the authentication services configured for a particular
application. LoginModule classes represent the authentication services.
Therefore, you can plug in different login modules into an application without
changing the application itself. Example 8.8, “An illustration of the steps of the
authentication process from the application perspective.” provides code
fragments that illustrate the steps required by an application to authenticate a
subject.
Example 8.8. An illustration of the steps of the authentication process from
the application perspective.
351 | P a g e
CallbackHandler handler = new MyHandler();
LoginContext lc = new LoginContext("some-config", handler);
try {
lc.login();
Subject subject = lc.getSubject();
} catch(LoginException e) {
System.out.println("authentication failed");
e.printStackTrace();
}
// Perform work as authenticated Subject
// ...
// Scope of work complete, logout to remove authentication info
try {
lc.logout();
} catch(LoginException e) {
System.out.println("logout failed");
e.printStackTrace();
}
// A sample MyHandler class
class MyHandler
implements CallbackHandler
{
public void handle(Callback[] callbacks) throws
IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(username);
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
}
Developers integrate with an authentication technology by creating an
implementation of the LoginModule interface. This allows different
authentication technologies to be plugged into an application by
administrator. Multiple LoginModules can be chained together to allow for more
352 | P a g e
than one authentication technology as part of the authentication process. For
example, one LoginModule may perform username/password-based
authentication, while another may interface to hardware devices such as
smart card readers or biometric authenticators. The life cycle of a LoginModule is
driven by the LoginContext object against which the client creates and issues the
login method. The process consists of a two phases. The steps of the process
are as follows:
 The LoginContext creates each configured LoginModule using its public no-
arg constructor.
 Each LoginModule is initialized with a call to its initialize method. The
Subject argument is guaranteed to be non-null. The signature of the
initialize method is: public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options).
 The login method is then called to start the authentication process. An
example method implementation might prompt the user for a
username and password, and then verify the information against data
stored in a naming service such as NIS or LDAP. Alternative
implementations might interface to smart cards and biometric devices,
or simply extract user information from the underlying operating
system. The validation of user identity by each LoginModule is considered
phase 1 of JAAS authentication. The signature of the login method
is: boolean login() throws LoginException. Failure is indicated by throwing
a LoginException. A return of true indicates that the method succeeded,
while a return of false indicates that the login module should be
ignored.
 If the LoginContext's overall authentication succeeds, commit is invoked
on each LoginModule. If phase 1 succeeded for a LoginModule, then the
commit method continues with phase 2: associating relevant principals,
public credentials, and/or private credentials with the subject. If phase
1 fails for a LoginModule, then commit removes any previously stored
authentication state, such as usernames or passwords. The signature of
the commit method is: boolean commit() throws LoginException. Failure to
complete the commit phase is indicated by throwing a LoginException. A
return of true indicates that the method succeeded, while a return of
false indicates that the login module should be ignored.
353 | P a g e
 If the LoginContext's overall authentication failed, then the abort method is
invoked on each LoginModule. The abort method removes/destroys any
authentication state created by the login or initialize methods. The
signature of the abort method is:boolean abort() throws LoginException. Failure
to complete the abort phase is indicated by throwing a LoginException. A
return of true indicates that the method succeeded, while a return of
false indicates that the login module should be ignored.
 Removal of the authentication state after a successful login is
accomplished when the application invokes logout on the LoginContext.
This in turn results in a logout method invocation on each LoginModule.
The logout method removes the principals and credentials originally
associated with the subject during the commit operation. Credentials
should be destroyed upon removal. The signature of the logout method
is: boolean logout() throws LoginException. Failure to complete the logout process
is indicated by throwing a LoginException. A return of true indicates that
the method succeeded, while a return of false indicates that the login
module should be ignored.
When a LoginModule must communicate with the user to obtain authentication
information, it uses a CallbackHandler object. Applications implement
the CallbackHandler interface and pass it to the LoginContext, which forwards it
directly to the underlying login modules. Login modules use
the CallbackHandler both to gather input from users, such as a password or smart-
card PIN number, and to supply information to users, such as status
information. By allowing the application to specify theCallbackHandler,
underlying LoginModules remain independent from the different ways
applications interact with users. For example, a CallbackHandler's implementation
for a GUI application might display a window to solicit user input. On the other
hand, a callbackhandler's implementation for a non-GUI environment, such as an
application server, might simply obtain credential information using an
application server API. The callbackhandler interface has one method to
implement:
void handle(Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException;
The last authentication class to cover is the Callback interface. This is a tagging
interface for which several default implementations are provided,
354 | P a g e
including NameCallback and PasswordCallback that were used in Example 8.8, “An
illustration of the steps of the authentication process from the application
perspective.” LoginModule s use a Callback to request information required by
the authentication mechanism the LoginModule encapsulates. LoginModule s pass
an array of Callback s directly to theCallbackHandler.handle method during the
authentication's login phase. If a callbackhandler does not understand how to use
a Callback object passed into the handle method, it throws
an UnsupportedCallbackException to abort the login call.
The JBoss Security Model
Similar to the rest of the JBoss architecture, security at the lowest level is
defined as a set of interfaces for which alternate implementations may be
provided. There are three basic interfaces that define the JBoss server security
layer:org.jboss.security.AuthenticationManager, org.jboss.security.RealmMapping,
and org.jboss.security.SecurityProxy. Figure 8.3, “The key security model interfaces
and their relationship to the JBoss server EJB container elements.”shows a
class diagram of the security interfaces and their relationship to the EJB
container architecture.
355 | P a g e
Figure 8.3. The key security model interfaces and their relationship to the
JBoss server EJB container elements.
The light blue classes represent the security interfaces while the yellow classes
represent the EJB container layer. The two interfaces required for the
implementation of the J2EE security model are
the org.jboss.security.AuthenticationManager andorg.jboss.security.RealmMapping. The roles of
the security interfaces presented in Figure 8.3, “The key security model
interfaces and their relationship to the JBoss server EJB container
elements.” are summarized in the following list.
 AuthenticationManager is an interface responsible for validating credentials
associated with principals. Principals are identities and examples
356 | P a g e
include usernames, employee numbers, social security numbers, and so
on. Credentials are proof of the identity and examples include
passwords, session keys, digital signatures, and so on. The isValid method
is invoked to see if a user identity and associated credentials as known
in the operational environment are valid proof of the user identity.
 RealmMapping is an interface responsible for principal mapping and role
mapping. The getPrincipal method takes a user identity as known in the
operational environment and returns the application domain identity.
The doesUserHaveRole method validates that the user identity in the
operation environment has been assigned the indicated role from the
application domain.
 SecurityProxy is an interface describing the requirements for a custom
SecurityProxyInterceptor plugin. A SecurityProxy allows for the
externalization of custom security checks on a per-method basis for
both the EJB home and remote interface methods.
 SubjectSecurityManager is a subinterface of AuthenticationManager that simply
adds accessor methods for obtaining the security domain name of the
security manager and the current thread's authenticated Subject.
 SecurityDomain is an extension of the AuthenticationManager, RealmMapping,
and SubjectSecurityManager interfaces. It is a move to a comprehensive
security interface based on the JAAS Subject, a java.security.KeyStore, and
the
JSSE com.sun.net.ssl.KeyManagerFactory and com.sun.net.ssl.TrustManagerFactory interfa
ces. This interface is still a work in progress that will be the basis of a
multi-domain security architecture that will better support ASP style
deployments of applications and resources.
Note that the AuthenticationManager, RealmMapping and SecurityProxy interfaces have no
association to JAAS related classes. Although the JBossSX framework is heavily
dependent on JAAS, the basic security interfaces required for implementation
of the J2EE security model are not. The JBossSX framework is simply an
implementation of the basic security plug-in interfaces that are based on JAAS.
The component diagram presented in Figure 8.4, “The relationship between
the JBossSX framework implementation classes and the JBoss server EJB
container layer.” illustrates this fact. The implication of this plug-in
architecture is that you are free to replace the JAAS-based JBossSX
implementation classes with your own custom security manager
357 | P a g e
implementation that does not make use of JAAS, if you so desire. You'll see
how to do this when you look at the JBossSX MBeans available for the
configuration of JBossSX in Figure 8.4, “The relationship between the JBossSX
framework implementation classes and the JBoss server EJB container layer.”.
Figure 8.4. The relationship between the JBossSX framework
implementation classes and the JBoss server EJB container layer.
358 | P a g e
8.3.1. Enabling Declarative Security in JBoss Revisited
Recall that our discussion of the J2EE standard security model ended with a
requirement for the use of JBoss server specific deployment descriptor to
enable security. The details of this configuration is presented here, as this is
part of the generic JBoss security model. Figure 8.5, “The security element
subsets of the JBoss server jboss.xml and jboss-web.xml deployment
descriptors.” shows the JBoss-specific EJB and web application deployment
descriptor's security-related elements.
Figure 8.5. The security element subsets of the JBoss server jboss.xml and
jboss-web.xml deployment descriptors.
359 | P a g e
The value of a security-domain element specifies the JNDI name of the security
manager interface implementation that JBoss uses for the EJB and web
containers. This is an object that implements both of
the AuthenticationManager and RealmMappinginterfaces. When specified as a top-level
element it defines what security domain in effect for all EJBs in the
deployment unit. This is the typical usage because mixing security managers
within a deployment unit complicates inter-component operation and
administration.
To specify the security domain for an individual EJB, you specify the security-
domain at the container configuration level. This will override any top-level
security-domain element.
The unauthenticated-principal element specifies the name to use for
the Principal object returned by the EJBContext.getUserPrincpal method when an
unauthenticated user invokes an EJB. Note that this conveys no special
permissions to an unauthenticated caller. Its primary purpose is to allow
unsecured servlets and JSP pages to invoke unsecured EJBs and allow the
target EJB to obtain a non-null Principal for the caller using
the getUserPrincipal method. This is a J2EE specification requirement.
The security-proxy element identifies a custom security proxy implementation
that allows per-request security checks outside the scope of the EJB
declarative security model without embedding security logic into the EJB
implementation. This may be an implementation of
the org.jboss.security.SecurityProxy interface, or just an object that implements
methods in the home, remote, local home or local interfaces of the EJB to
secure without implementing any common interface. If the given class does
not implement the SecurityProxy interface, the instance must be wrapped in
a SecurityProxy implementation that delegates the method invocations to the
object. The org.jboss.security.SubjectSecurityProxy is an
example SecurityProxyimplementation used by the default JBossSX installation.
Take a look at a simple example of a custom SecurityProxy in the context of a
trivial stateless session bean. The custom SecurityProxy validates that no one
invokes the bean's echo method with a four-letter word as its argument. This is
a check that is not possible with role-based security; you cannot define
a FourLetterEchoInvoker role because the security context is the method argument,
360 | P a g e
not a property of the caller. The code for the custom SecurityProxy is given
in Example 8.9, “The example 1 custom EchoSecurityProxy implementation
that enforces the echo argument-based security constraint.”, and the full
source code is available in the src/main/org/jboss/chap8/ex1 directory of the book
examples. The associated jboss.xml descriptor that installs the EchoSecurityProxy as
the custom proxy for the EchoBean is given in Example 8.10, “The jboss.xml
descriptor which configures the EchoSecurityProxy as the custom security
proxy for the EchoBean.”.
Example 8.9. The example 1 custom EchoSecurityProxy implementation that
enforces the echo argument-based security constraint.
package org.jboss.chap8.ex1;
import java.lang.reflect.Method;
import javax.ejb.EJBContext;
import org.apache.log4j.Category;
import org.jboss.security.SecurityProxy;
/** A simple example of a custom SecurityProxy implementation
* that demonstrates method argument based security checks.
* @author Scott.Stark@jboss.org
* @version $Revision: 1.15 $
*/
public class EchoSecurityProxy implements SecurityProxy
{
Category log = Category.getInstance(EchoSecurityProxy.class);
Method echo;
public void init(Class beanHome, Class beanRemote,
Object securityMgr)
throws InstantiationException
{
log.debug("init, beanHome="+beanHome
+ ", beanRemote="+beanRemote
+ ", securityMgr="+securityMgr);
// Get the echo method for equality testing in invoke
try {
Class[] params = {String.class};
echo = beanRemote.getDeclaredMethod("echo", params);
} catch(Exception e) {
String msg = "Failed to finde an echo(String) method";
log.error(msg, e);
throw new InstantiationException(msg);
361 | P a g e
}
}
public void setEJBContext(EJBContext ctx)
{
log.debug("setEJBContext, ctx="+ctx);
}
public void invokeHome(Method m, Object[] args)
throws SecurityException
{
// We don't validate access to home methods
}
public void invoke(Method m, Object[] args, Object bean)
throws SecurityException
{
log.debug("invoke, m="+m);
// Check for the echo method
if (m.equals(echo)) {
// Validate that the msg arg is not 4 letter word
String arg = (String) args[0];
if (arg == null || arg.length() == 4)
throw new SecurityException("No 4 letter words");
}
// We are not responsible for doing the invoke
}
}
Example 8.10. The jboss.xml descriptor which configures the
EchoSecurityProxy as the custom security proxy for the EchoBean.
<jboss>
<security-domain>java:/jaas/other</security-domain>
<enterprise-beans>
<session>
<ejb-name>EchoBean</ejb-name>
<security-proxy>org.jboss.chap8.ex1.EchoSecurityProxy</security-proxy>
</session>
</enterprise-beans>
</jboss>
The EchoSecurityProxy checks that the method to be invoked on the bean instance
corresponds to the echo(String) method loaded the init method. If there is a
match, the method argument is obtained and its length compared against 4 or
362 | P a g e
null. Either case results in a SecurityException being thrown. Certainly this is a
contrived example, but only in its application. It is a common requirement that
applications must perform security checks based on the value of method
arguments. The point of the example is to demonstrate how custom security
beyond the scope of the standard declarative security model can be
introduced independent of the bean implementation. This allows the
specification and coding of the security requirements to be delegated to
security experts. Since the security proxy layer can be done independent of
the bean implementation, security can be changed to match the deployment
environment requirements.
Now test the custom proxy by running a client that attempts to invoke
the EchoBean.echo method with the arguments Hello and Four as illustrated in this
fragment:
public class ExClient
{
public static void main(String args[])
throws Exception
{
Logger log = Logger.getLogger("ExClient");
log.info("Looking up EchoBean");
InitialContext iniCtx = new InitialContext();
Object ref = iniCtx.lookup("EchoBean");
EchoHome home = (EchoHome) ref;
Echo echo = home.create();
log.info("Created Echo");
log.info("Echo.echo('Hello') = "+echo.echo("Hello"));
log.info("Echo.echo('Four') = "+echo.echo("Four"));
}
}
The first call should succeed, while the second should fail due to the fact
that Four is a four-letter word. Run the client as follows using Ant from the
examples directory:
[nr@toki examples]$ ant -Dchap=chap8 -Dex=1 run-example
run-example1:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 5 seconds for deploy...
[java] [INFO,ExClient] Looking up EchoBean
[java] [INFO,ExClient] Created Echo
363 | P a g e
[java] [INFO,ExClient] Echo.echo('Hello') = Hello
[java] Exception in thread "main" java.rmi.ServerException: RemoteException occurred
in server thread; nested exception is:
[java] java.rmi.AccessException: SecurityException; nested exception is:
[java] java.lang.SecurityException: No 4 letter words
...
[java] at org.jboss.chap8.ex1.ExClient.main(ExClient.java:28)
[java] Caused by: java.rmi.AccessException: SecurityException; nested exception is:
[java] java.lang.SecurityException: No 4 letter words
...
The result is that the echo('Hello') method call succeeds as expected and
the echo('Four') method call results in a rather messy looking exception, which is
also expected. The above output has been truncated to fit in the book. The
key part to the exception is that the SecurityException("No 4 letter words") generated
by the EchoSecurityProxy was thrown to abort the attempted method invocation
as desired.
8.4. The JBoss Security Extension Architecture
The preceding discussion of the general JBoss security layer has stated that
the JBossSX security extension framework is an implementation of the security
layer interfaces. This is the primary purpose of the JBossSX framework. The
details of the implementation are interesting in that it offers a great deal of
customization for integration into existing security infrastructures. A security
infrastructure can be anything from a database or LDAP server to a
sophisticated security software suite. The integration flexibility is achieved
using the pluggable authentication model available in the JAAS framework.
The heart of the JBossSX framework is org.jboss.security.plugins.JaasSecurityManager. This
is the default implementation of
the AuthenticationManager and RealmMapping interfaces. Figure 8.6, “The relationship
between the security-domain component deployment descriptor value, the
component container and the JaasSecurityManager.” shows how
the JaasSecurityManager integrates into the EJB and web container layers based on
the security-domain element of the corresponding component deployment
descriptor.
364 | P a g e
Figure 8.6. The relationship between the security-domain component
deployment descriptor value, the component container and the
JaasSecurityManager.
Figure 8.6, “The relationship between the security-domain component
deployment descriptor value, the component container and the
JaasSecurityManager.” depicts an enterprise application that contains both
EJBs and web content secured under the security domain jwdomain. The EJB and
web containers have a request interceptor architecture that includes a
security interceptor, which enforces the container security model. At
365 | P a g e
deployment time, the security-domain element value in the jboss.xml and jboss-
web.xml descriptors is used to obtain the security manager instance associated
with the container. The security interceptor then uses the security manager to
perform its role. When a secured component is requested, the security
interceptor delegates security checks to the security manager instance
associated with the container.
The JBossSX JaasSecurityManager implementation, shown in Figure 8.6, “The
relationship between the security-domain component deployment descriptor
value, the component container and the JaasSecurityManager.” as
the JaasSecurityMgr component, performs security checks based on the
information associated with the Subject instance that results from executing the
JAAS login modules configured under the name matching the security-domain
element value. We will drill into the JaasSecurityManagerimplementation and its
use of JAAS in the following section.
8.4.1. How the JaasSecurityManager Uses JAAS
The JaasSecurityManager uses the JAAS packages to implement
the AuthenticationManager and RealmMapping interface behavior. In particular, its
behavior derives from the execution of the login module instances that are
configured under the name that matches the security domain to which
the JaasSecurityManager has been assigned. The login modules implement the
security domain's principal authentication and role-mapping behavior. Thus,
you can use the JaasSecurityManager across different security domains simply by
plugging in different login module configurations for the domains.
To illustrate the details of the JaasSecurityManager's usage of the JAAS
authentication process, you will walk through a client invocation of an EJB
home method invocation. The prerequisite setting is that the EJB has been
deployed in the JBoss server and its home interface methods have been
secured using method-permission elements in the ejb-jar.xml descriptor, and it has
been assigned a security domain named jwdomain using
the jboss.xml descriptor security-domain element.
366 | P a g e
Figure 8.7. An illustration of the steps involved in the authentication and
authorization of a secured EJB home method invocation.
Figure 8.7, “An illustration of the steps involved in the authentication and
authorization of a secured EJB home method invocation.” provides a view of
367 | P a g e
the client to server communication we will discuss. The numbered steps
shown are:
1. The client first has to perform a JAAS login to establish the principal and
credentials for authentication, and this is labeled Client Side Login in the
figure. This is how clients establish their login identities in JBoss.
Support for presenting the login information via
JNDI InitialContext properties is provided via an alternate configuration. A
JAAS login entails creating a LoginContext instance and passing the name of
the configuration to use. The configuration name is other. This one-time
login associates the login principal and credentials with all subsequent
EJB method invocations. Note that the process might not authenticate
the user. The nature of the client-side login depends on the login
module configuration that the client uses. In this example,
theother client-side login configuration entry is set up to use
the ClientLoginModule module (an org.jboss.security.ClientLoginModule). This is the
default client side module that simply binds the username and
password to the JBoss EJB invocation layer for later authentication on
the server. The identity of the client is not authenticated on the client.
2. Later, the client obtains the EJB home interface and attempts to create
a bean. This event is labeled as Home Method Invocation. This results in
a home interface method invocation being sent to the JBoss server. The
invocation includes the method arguments passed by the client along
with the user identity and credentials from the client-side JAAS login
performed in step 1.
3. On the server side, the security interceptor first requires authentication
of the user invoking the call, which, as on the client side, involves a JAAS
login.
4. The security domain under which the EJB is secured determines the
choice of login modules. The security domain name is used as the login
configuration entry name passed to the LoginContext constructor. The EJB
security domain is jwdomain. If the JAAS login authenticates the user, a
JAAS Subject is created that contains the following in its PrincipalsSet:
 A java.security.Principal that corresponds to the client identity as
known in the deployment security environment.
 A java.security.acl.Group named Roles that contains the role names
from the application domain to which the user has been
368 | P a g e
assigned. org.jboss.security.SimplePrincipal objects are used to represent
the role names;SimplePrincipal is a simple string-based
implementation of Principal. These roles are used to validate the
roles assigned to methods in ejb-jar.xml and
the EJBContext.isCallerInRole(String) method implementation.
 An optional java.security.acl.Group named CallerPrincipal, which contains
a single org.jboss.security.SimplePrincipal that corresponds to the identity
of the application domain's caller. The CallerPrincipal sole group
member will be the value returned by
the EJBContext.getCallerPrincipal() method. The purpose of this mapping
is to allow a Principal as known in the operational security
environment to map to a Principal with a name known to the
application. In the absence of a CallerPrincipal mapping the
deployment security environment principal is used as
the getCallerPrincipal method value. That is, the operational principal
is the same as the application domain principal.
5. The final step of the security interceptor check is to verify that the
authenticated user has permission to invoke the requested method This
is labeled as Server Side Authorization in Figure 8.7, “An illustration of
the steps involved in the authentication and authorization of a secured
EJB home method invocation.”. Performing the authorization this
entails the following steps:
 Obtain the names of the roles allowed to access the EJB method
from the EJB container. The role names are determined by ejb-
jar.xml descriptor role-name elements of all method-
permission elements containing the invoked method.
 If no roles have been assigned, or the method is specified in
an exclude-list element, then access to the method is denied.
Otherwise, the doesUserHaveRole method is invoked on the security
manager by the security interceptor to see if the caller has one of
the assigned role names. This method iterates through the role
names and checks if the authenticated user's Subject Roles group
contains a SimplePrincipal with the assigned role name. Access is
allowed if any role name is a member of the Roles group. Access is
denied if none of the role names are members.
 If the EJB was configured with a custom security proxy, the
method invocation is delegated to it. If the security proxy wants
369 | P a g e
to deny access to the caller, it will throw a java.lang.SecurityException. If
no SecurityException is thrown, access to the EJB method is allowed
and the method invocation passes to the next container
interceptor. Note that the SecurityProxyInterceptor handles this check
and this interceptor is not shown.
Every secured EJB method invocation, or secured web content access, requires
the authentication and authorization of the caller because security
information is handled as a stateless attribute of the request that must be
presented and validated on each request. This can be an expensive operation
if the JAAS login involves client-to-server communication. Because of this,
the JaasSecurityManager supports the notion of an authentication cache that is
used to store principal and credential information from previous successful
logins. You can specify the authentication cache instance to use as part of
the JaasSecurityManager configuration as you will see when the associated MBean
service is discussed in following section. In the absence of any user-defined
cache, a default cache that maintains credential information for a configurable
period of time is used.
8.4.2. The JaasSecurityManagerService MBean
The JaasSecurityManagerService MBean service manages security managers.
Although its name begins with Jaas, the security managers it handles need not
use JAAS in their implementation. The name arose from the fact that the
default security manager implementation is the JaasSecurityManager. The primary
role of the JaasSecurityManagerService is to externalize the security manager
implementation. You can change the security manager implementation by
providing an alternate implementation of
theAuthenticationManager and RealmMapping interfaces. Of course this is optional
because, by default, the JaasSecurityManager implementation is used.
The second fundamental role of the JaasSecurityManagerService is to provide a
JNDI javax.naming.spi.ObjectFactory implementation to allow for simple code-free
management of the JNDI name to security manager implementation mapping.
It has been mentioned that security is enabled by specifying the JNDI name of
the security manager implementation via the security-domain deployment
descriptor element. When you specify a JNDI name, there has to be an object-
binding there to use. To simplify the setup of the JNDI name to security
370 | P a g e
manager bindings, the JaasSecurityManagerService manages the association of
security manager instances to names by binding a next naming system
reference with itself as the JNDI ObjectFactory under the name java:/jaas. This
allows one to use a naming convention of the form java:/jaas/XYZ as the value for
the security-domain element, and the security manager instance for
the XYZ security domain will be created as needed for you. The security
manager for the domain XYZ is created on the first lookup against
the java:/jaas/XYZ binding by creating an instance of the class specified by
the SecurityManagerClassName attribute using a constructor that takes the name of
the security domain. For example, consider the following container security
configuration snippet:
<jboss>
<!-- Configure all containers to be secured under the "hades" security domain -->
<security-domain>java:/jaas/hades</security-domain>
<!-- ... -->
</jboss>
Any lookup of the name java:/jaas/hades will return a security manager instance
that has been associated with the security domain named hades. This security
manager will implement the AuthenticationManager and RealmMapping
security interfaces and will be of the type specified by
the JaasSecurityManagerService SecurityManagerClassName attribute.
The JaasSecurityManagerService MBean is configured by default for use in the
standard JBoss distribution, and you can often use the default configuration as
is. The configurable attributes of the JaasSecurityManagerService include:
 SecurityManagerClassName: The name of the class that provides the
security manager implementation. The implementation must support
both
the org.jboss.security.AuthenticationManager and org.jboss.security.RealmMappinginterfa
ces. If not specified this defaults to the JAAS-
based org.jboss.security.plugins.JaasSecurityManager.
 CallbackHandlerClassName: The name of the class that provides
the javax.security.auth.callback.CallbackHandler implementation used by
the JaasSecurityManager. You can override the handler used by
the JaasSecurityManagerif the default implementation
(org.jboss.security.auth.callback.SecurityAssociationHandler) does not meet your
371 | P a g e
needs. This is a rather deep configuration that generally should not be
set unless you know what you are doing.
 SecurityProxyFactoryClassName: The name of the class that provides
the org.jboss.security.SecurityProxyFactory implementation. If not specified this
defaults to org.jboss.security.SubjectSecurityProxyFactory.
 AuthenticationCacheJndiName: Specifies the location of the security
credential cache policy. This is first treated as an ObjectFactory location
capable of returning CachePolicy instances on a per-security-domain basis.
This is done by appending the name of the security domain to this name
when looking up the CachePolicy for a domain. If this fails, the location is
treated as a single CachePolicy for all security domains. As a default, a
timed cache policy is used.
 DefaultCacheTimeout: Specifies the default timed cache policy timeout
in seconds. The default value is 1800 seconds (30 minutes). The value
you use for the timeout is a tradeoff between frequent authentication
operations and how long credential information may be out of synch
with respect to the security information store. If you want to disable
caching of security credentials, set this to 0 to force authentication to
occur every time. This has no affect if the AuthenticationCacheJndiName has
been changed from the default value.
 DefaultCacheResolution: Specifies the default timed cache policy
resolution in seconds. This controls the interval at which the cache
current timestamp is updated and should be less than
the DefaultCacheTimeout in order for the timeout to be meaningful. The
default resolution is 60 seconds(1 minute). This has no affect if
the AuthenticationCacheJndiName has been changed from the default value.
The JaasSecurityManagerService also supports a number of useful operations. These
include flushing any security domain authentication cache at runtime, getting
the list of active users in a security domain authentication cache, and any of
the security manager interface methods.
Flushing a security domain authentication cache can be used to drop all
cached credentials when the underlying store has been updated and you want
the store state to be used immediately. The MBean operation signature
is: public void flushAuthenticationCache(String securityDomain).
372 | P a g e
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...;
String jaasMgrName = "jboss.security:service=JaasSecurityManager";
ObjectName jaasMgr = new ObjectName(jaasMgrName);
Object[] params = {domainName};
String[] signature = {"java.lang.String"};
server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);
Getting the list of active users provides a snapshot of the Principals keys in a
security domain authentication cache that are not expired. The MBean
operation signature is: public List getAuthenticationCachePrincipals(String securityDomain).
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...;
String jaasMgrName = "jboss.security:service=JaasSecurityManager";
ObjectName jaasMgr = new ObjectName(jaasMgrName);
Object[] params = {domainName};
String[] signature = {"java.lang.String"};
List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals",
params, signature);
The security manager has a few additional access methods.
public boolean isValid(String securityDomain, Principal principal, Object credential);
public Principal getPrincipal(String securityDomain, Principal principal);
public boolean doesUserHaveRole(String securityDomain, Principal principal,
Object credential, Set roles);
public Set getUserRoles(String securityDomain, Principal principal, Object credential);
They provide access to the
corresponding AuthenticationManager and RealmMapping interface method of the
associated security domain named by the securityDomain argument.
8.4.3. The JaasSecurityDomain MBean
The org.jboss.security.plugins.JaasSecurityDomain is an extension of JaasSecurityManager that
adds the notion of a KeyStore, aJSSE KeyManagerFactory and a TrustManagerFactory for
supporting SSL and other cryptographic use cases. The additional configurable
attributes of the JaasSecurityDomain include:
JKS
373 | P a g e
 KeyStoreType: The type of the KeyStore implementation. This is the type
argument passed to the java.security.KeyStore.getInstance(String type) factory
method.
 KeyStoreURL: A URL to the location of the KeyStore database. This is used
to obtain an InputStream to initialize the KeyStore. If the string is not a value
URL, it iss treated as a file.
 KeyStorePass: The password associated with the KeyStore database
contents. The KeyStorePass is also used in combination with
the Salt and IterationCount attributes to create a PBE secret key used with
the encode/decode operations. TheKeyStorePass attribute value format is
one of the following:
o The plaintext password for the KeyStore The toCharArray() value of the
string is used without any manipulation.
o A command to execute to obtain the plaintext password. The
format is {EXT}... where the ... is the exact command line that will
be passed to the Runtime.exec(String) method to execute a platform-
specific command. The first line of the command output is used
as the password.
o A class to create to obtain the plaintext password. The format
is {CLASS}classname[:ctorarg] where the [:ctorarg] is an optional string that
will be passed to the constructor when instantiating the
the classname. The password is obtained from classname by
invoking a toCharArray() method if found, otherwise,
the toString() method is used.
 Salt: The PBEParameterSpec salt value.
 IterationCount: The PBEParameterSpec iteration count value.
 ManagerServiceName: Sets the JMX object name string of the security
manager service MBean. This is used to register the defaults to register
the JaasSecurityDomain as a the security manager
under java:/jaas/<domain> where <domain> is the name passed to the MBean
constructor. The name defaults to jboss.security:service=JaasSecurityManager.
 LoadSunJSSEProvider: A flag indicating if the
Sun com.sun.net.ssl.internal.ssl.Provider security provider should be loaded on
startup. This is needed when using the Sun JSSE jars without them
installed as an extension with JDK 1.3. This should be set to false with
JDK 1.4 or when using an alternate JSSE provider. This flag currently
defaults to true.
374 | P a g e
8.4.4. An XML JAAS Login Configuration MBean
JBoss uses a custom implementation of the javax.security.auth.login.Configuration class
that is provided by the org.jboss.security.auth.login.XMLLoginConfig MBean. This
configuration implementation uses an XML format that conforms to the DTD
given by Figure 8.8, “The XMLLoginConfig DTD”.
Figure 8.8. The XMLLoginConfig DTD
The name attribute of the application-policy is the login configuration name.
This corresponds to the portion of the jboss.xml and jboss-web.xml security-
domain element value after the java:/jaas/ prefix. The code attribute of the login-
moduleelement specifies the class name of the login module implementation.
The flag attribute controls the overall behavior of the authentication stack.
The allowed values and measnings are:
 required: the LoginModule is required to succeed. If it succeeds or fails,
authentication still continues to proceed down the LoginModule list.
 requisite: the LoginModule is required to succeed. If it succeeds,
authentication continues down the LoginModule list. If it fails, control
immediately returns to the application (authentication does not
proceed down the LoginModule list).
 sufficient: the LoginModule is not required to succeed. If it does succeed,
control immediately returns to the application (authentication does not
proceed down the LoginModule list). If it fails, authentication continues
down the LoginModule list.
375 | P a g e
 optional: the LoginModule is not required to succeed. If it succeeds or fails,
authentication still continues to proceed down the LoginModule list.
Zero or more module-option elements may be specified as child elements of
a login-module. These define name/value string pairs that are made available to
the login module during initialization. The name attribute specifies the option
name while themodule-option body provides the value. An example login
configuration is given in Example 8.11, “A sample login module configuration
suitable for use with XMLLoginConfig”.
Example 8.11. A sample login module configuration suitable for use with
XMLLoginConfig
<policy>
<application-policy name="srp-test">
<authentication>
<login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
flag="required">
<module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag="required">
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
The XMLLoginConfig MBean supports the following attributes:
 ConfigURL: specifies the URL of the XML login configuration file that
should be loaded by this MBean on startup. This must be a valid URL
string representation.
 ConfigResource: specifies the resource name of the XML login
configuration file that should be loaded by this MBean on startup. The
name is treated as a classpath resource for which a URL is located using
the thread context class loader.
 ValidateDTD: a flag indicating if the XML configuration should be
validated against its DTD. This defaults to true.
376 | P a g e
The MBean also supports the following operations that allow one to
dynamically extend the login configurations at runtime. Note that any
operation that attempts to alter login configuration requires
ajavax.security.auth.AuthPermission("refreshLoginConfiguration") when running with a
security manager. The org.jboss.chap8.service.SecurityConfig service demonstrates how
this can be used to add/remove a deployment specific scurity configuration
dynamically.
 void addAppConfig(String appName, AppConfigurationEntry[] entries): this adds the given
login module configuration stack to the current configuration under the
given appName. This replaces any existing entry under that name.
 void removeAppConfig(String appName): this removes the login module
configuration registered under the given appName.
 String[] loadConfig(URL configURL) throws Exception: this loads one or more login
configurations from a URL representing either an XML or legacy Sun
login configuration file. Note that all login configurations must be added
or none will be added. It returns the names of the login configurations
that were added.
 void removeConfigs(String[] appNames): this removes the login configurations
specified appNames array.
 String displayAppConfig(String appName): this operation displays a simple string
format of the named configuration if it exists.
8.4.5. The JAAS Login Configuration Management MBean
The installation of the custom javax.security.auth.login.Configuration is managed by
the org.jboss.security.plugins.SecurityConfig MBean. There is one configurable attribute:
 LoginConfig: Specifies the JMX ObjectName string of the that provides the
default JAAS login configuration. When the SecurityConfig is started, this
mean is queried for its javax.security.auth.login.Configuration by calling
itsgetConfiguration(Configuration currentConfig) operation. If
the LoginConfig attribute is not specified then the default
Sun Configuration implementation described in the Configuration class
JavaDocs is used.
In addition to allowing for a custom JAAS login configuration implementation,
this service allows configurations to be chained together in a stack at runtime.
377 | P a g e
This allows one to push a login configuration onto the stack and latter pop it.
This is a feature used by the security unit tests to install custom login
configurations into a default JBoss installation. Pusing a new configuration is
done using:
public void pushLoginConfig(String objectName) throws
JMException, MalformedObjectNameException;
The objectName parameters specifies an MBean similar to the LoginConfig attribute.
The current login configuration may be removed using:
public void popLoginConfig() throws JMException;
8.4.6. Using and Writing JBossSX Login Modules
The JaasSecurityManager implementation allows complete customization of the
authentication mechanism using JAAS login module configurations. By
defining the login module configuration entry that corresponds to the security
domain name you have used to secure access to your J2EE components, you
define the authentication mechanism and integration implementation.
The JBossSX framework includes a number of bundled login modules suitable
for integration with standard security infrastructure store protocols such as
LDAP and JDBC. It also includes standard base class implementations that help
enforce the expectedLoginModule to Subject usage pattern that was described in
theSection 8.4.7, “Writing Custom Login Modules”. These implementations
allow for easy integration of your own authentication protocol, if none of the
bundled login modules prove suitable. In this section we will first describe the
useful bundled login modules and their configuration, and then end with a
discussion of how to create your own custom LoginModule implementations for
use with JBoss.
8.4.6.1. org.jboss.security.auth.spi.IdentityLoginModule
The IdentityLoginModule is a simple login module that associates the principal
specified in the module options with any subject authenticated against the
module. It creates a SimplePrincipal instance using the name specified by
the principal option. Although this is certainly not an appropriate login module
for production strength authentication, it can be of use in development
378 | P a g e
environments when you want to test the security associated with a given
principal and associated roles.
The supported login module configuration options include:
 principal=string: The name to use for the SimplePrincipal all users are
authenticated as. The principal name defaults to guest if no principal
option is specified.
 roles=string-list: The names of the roles that will be assigned to the
user principal. The value is a comma-delimited list of role names.
 password-stacking=useFirstPass: When password-stacking option is
set, this module first looks for a shared username under the property
name javax.security.auth.login.name in the login module shared state map. If
found this is used as the principal name. If not found the principal name
set by this login module is stored under the property
name javax.security.auth.login.name.
A sample legacy Sun format login configuration entry that would authenticate
all users as the principal named jduke and assign role names of TheDuke,
and AnimatedCharacter is:
testIdentity {
org.jboss.security.auth.spi.IdentityLoginModule required
principal=jduke
roles=TheDuke,AnimatedCharater;
};
The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testIdentity">
<authentication>
<login-module code="org.jboss.security.auth.spi.IdentityLoginModule"
flag="required">
<module-option name="principal">jduke</module-option>
<module-option name="roles">TheDuke,AnimatedCharater</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
379 | P a g e
To add this entry to a JBoss server login cofiguration found in the default
configuration file set you would modify the conf/default/auth.conf file of the JBoss
distribution.
8.4.6.2. org.jboss.security.auth.spi.UsersRolesLoginModule
The UsersRolesLoginModule is another simple login module that supports multiple
users and user roles, and is based on two Java Properties formatted text files.
The username-to-password mapping file is called users.properties and the
username-to-roles mapping file is called roles.properties. The properties files are
loaded during initialization using the initialize method thread context class
loader. This means that these files can be placed into the J2EE deployment
JAR, the JBoss configuration directory, or any directory on the JBoss server or
system classpath. The primary purpose of this login module is to easily test the
security settings of multiple users and roles using properties files deployed
with the application.
The users.properties file uses a username=password format with each user entry on a
separate line as show here:
username1=password1
username2=password2
...
The roles.properties file uses as username=role1,role2,... format with an optional
group name value. For example:
username1=role1,role2,...
username1.RoleGroup1=role3,role4,...
username2=role1,role3,...
The username.XXX form of property name is used to assign the username roles to
a particular named group of roles where the XXX portion of the property name
is the group name. The username=... form is an abbreviation for username.Roles=...,
where the Roles group name is the standard name the JaasSecurityManager expects
to contain the roles which define the users permissions.
The following would be equivalent definitions for the jduke username:
jduke=TheDuke,AnimatedCharacter
380 | P a g e
jduke.Roles=TheDuke,AnimatedCharacter
The supported login module configuration options include the following:
 unauthenticatedIdentity=name: Defines the principal name that should
be assigned to requests that contain no authentication information.
This can be used to allow unprotected servlets to invoke methods on
EJBs that do not require a specific role. Such a principal has no
associated roles and so can only access either unsecured EJBs or EJB
methods that are associated with the unchecked permission constraint.
 password-stacking=useFirstPass: When password-stacking option is
set, this module first looks for a shared username and password under
the property
names javax.security.auth.login.name and javax.security.auth.login.passwordrespectivel
y in the login module shared state map. If found these are used as the
principal name and password. If not found the principal name and
password are set by this login module and stored under the property
namesjavax.security.auth.login.name and javax.security.auth.login.password respectivel
y.
 hashAlgorithm=string: The name of the java.security.MessageDigest algorithm
to use to hash the password. There is no default so this option must be
specified to enable hashing. When hashAlgorithm is specified, the clear text
password obtained from the callbackhandler is hashed before it is passed
to UsernamePasswordLoginModule.validatePassword as the inputPassword
argument. The expectedPassword as stored in the users.properties file must be
comparably hashed.
 hashEncoding=base64|hex: The string format for the hashed pass and
must be either base64 or hex. Base64 is the default.
 hashCharset=string: The encoding used to convert the clear text
password to a byte array. The platform default encoding is the default.
 usersProperties=string: The name of the properties resource containing
the username to password mappings. This defaults to users.properties.
 rolesProperties=string: The name of the properties resource containing
the username to roles mappings. This defaults to roles.properties.
A sample legacy Sun format login configuration entry that assigned
unauthenticated users the principal name nobody and contains based64
encoded, MD5 hashes of the passwords in a usersb64.properties file is:
381 | P a g e
testUsersRoles {
org.jboss.security.auth.spi.UsersRolesLoginModule required
usersProperties=usersb64.properties
hashAlgorithm=MD5
hashEncoding=base64
unauthenticatedIdentity=nobody
;
};
The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testUsersRoles">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag="required">
<module-option name="usersProperties">usersb64.properties</module-option>
<module-option name="hashAlgorithm">MD5</module-option>
<module-option name="hashEncoding">base64</module-option>
<module-option name="unauthenticatedIdentity">nobody</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
8.4.6.3. org.jboss.security.auth.spi.LdapLoginModule
The LdapLoginModule is a LoginModule implementation that authenticates against an
LDAP server using JNDI login using the login module configuration options. You
would use the LdapLoginModule if your username and credential information are
store in an LDAP server that is accessible using a JNDI LDAP provider.
The LDAP connectivity information is provided as configuration options that
are passed through to the environment object used to create JNDI initial
context. The standard LDAP JNDI properties used include the following:
 java.naming.factory.initial: The classname of
the InitialContextFactory implementation. This defaults to the Sun LDAP
provider implementation com.sun.jndi.ldap.LdapCtxFactory.
 java.naming.provider.url: The LDAP URL for the LDAP server
 java.naming.security.authentication: The security level to use. This
defaults to simple.
 java.naming.security.protocol: The transport protocol to use for secure
access, such as, ssl.
382 | P a g e
 java.naming.security.principal: The principal for authenticating the
caller to the service. This is built from other properties as described
below.
 java.naming.security.credentials: The value of the property depends on
the authentication scheme. For example, it could be a hashed
password, clear-text password, key, certificate, and so on.
The supported login module configuration options include the following:
 principalDNPrefix=string: A prefix to add to the username to form the
user distinguished name. See principalDNSuffix for more info.
 principalDNSuffix=string: A suffix to add to the username when forming
the user distiguished name. This is useful if you prompt a user for a
username and you don't want the user to have to enter the fully
distinguished name. Using this property andprincipalDNSuffix the userDN will
be formed as:
String userDN = principalDNPrefix + username + principalDNSuffix;
 useObjectCredential=true|false: Indicates that the credential should be
obtained as an opaque Object using
the org.jboss.security.auth.callback.ObjectCallback type of Callback rather than as
a char[] password using a JAASPasswordCallback. This allows for passing non-
char[] credential information to the LDAP server.
 rolesCtxDN=string: The fixed distinguished name to the context to
search for user roles.
 userRolesCtxDNAttributeName=string: The name of an attribute in the
user object that contains the distinguished name to the context to
search for user roles. This differs from rolesCtxDN in that the context to
search for a user's roles can be unique for each user.
 roleAttributeID=string: The name of the attribute that contains the
user roles. If not specified this defaults to roles.
 roleAttributeIsDN=string: A flag indicating whether
the roleAttributeID contains the fully distinguished name of a role object, or
the role name. If false, the role name is taken from the value
of roleAttributeID. If true, the role attribute represents the distinguished
name of a role object. The role name is taken from the value of
the roleNameAttributeId attribute of the context name by the distinguished
383 | P a g e
name. In certain directory schemas (e.g., MS ActiveDirectory), role
attributes in the user object are stored as DNs to role objects instead of
as simple names, in which case, this property should be set to true. The
default is false.
 roleNameAttributeID=string: The name of the attribute of the in the
context pointed to by the roleCtxDN distiguished name value which
contains the role name. If the roleAttributeIsDN property is set to true, this
property is used to find the role object's name attribute. The default
is group.
 uidAttributeID=string: The name of the attribute in the object
containing the user roles that corresponds to the userid. This is used to
locate the user roles. If not specified this defaults to uid.
 matchOnUserDN=true|false: A flag indicating if the search for user
roles should match on the user's fully distinguished name. If false, just
the username is used as the match value against
the uidAttributeName attribute. If true, the full userDN is used as the match
value.
 unauthenticatedIdentity=string: The principal name that should be
assigned to requests that contain no authentication information. This
behavior is inherited from the UsernamePasswordLoginModule superclass.
 password-stacking=useFirstPass: When the password-stacking option is
set, this module first looks for a shared username and password under
the property
names javax.security.auth.login.name andjavax.security.auth.login.password respectivel
y in the login module shared state map. If found these are used as the
principal name and password. If not found the principal name and
password are set by this login module and stored under the property
names javax.security.auth.login.name and javax.security.auth.login.password respectivel
y.
 hashAlgorithm=string: The name of the java.security.MessageDigest algorithm
to use to hash the password. There is no default so this option must be
specified to enable hashing. When hashAlgorithm is specified, the clear text
password obtained from the callbackhandler is hashed before it is passed
to UsernamePasswordLoginModule.validatePassword as the inputPassword argument.
The expectedPassword as stored in the LDAP server must be comparably
hashed.
384 | P a g e
 hashEncoding=base64|hex: The string format for the hashed pass and
must be either base64 or hex. Base64 is the default.
 hashCharset=string: The encoding used to convert the clear text
password to a byte array. The platform default encoding is the default.
 allowEmptyPasswords: A flag indicating if empty (length 0) passwords
should be passed to the LDAP server. An empty password is treated as
an anonymous login by some LDAP servers and this may not be a
desirable feature. Set this to false to reject empty passwords, true to
have the LDAP server validate the empty password. The default is true.
The authentication of a user is performed by connecting to the LDAP server
based on the login module configuration options. Connecting to the LDAP
server is done by creating an InitialLdapContext with an environment composed of
the LDAP JNDI properties described previously in this section.
The Context.SECURITY_PRINCIPAL is set to the distinguished name of the user as
obtained by the callback handler in combination with
the principalDNPrefix and principalDNSuffix option values, and
the Context.SECURITY_CREDENTIALS property is either set to the String password or
the Object credential depending on the useObjectCredential option.
Once authentication has succeeded by virtue of being able to create
an InitialLdapContext instance, the user's roles are queried by performing a search
on the rolesCtxDN location with search attributes set to
the roleAttributeName anduidAttributeName option values. The roles names are
obtaining by invoking the toString method on the role attributes in the search
result set.
A sample Sun legacy format login configuration entry is:
testLdap {
org.jboss.security.auth.spi.LdapLoginModule required
java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url="ldap://ldaphost.jboss.org:1389/"
java.naming.security.authentication=simple
principalDNPrefix=uid=
uidAttributeID=userid
roleAttributeID=roleName
principalDNSuffix=,ou=People,o=jboss.org
rolesCtxDN=cn=JBossSX Tests,ou=Roles,o=jboss.org
};
385 | P a g e
The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testLdap">
<authentication>
<login-module code="org.jboss.security.auth.spi.LdapLoginModule"
flag="required">
<module-option name="java.naming.factory.initial">
com.sun.jndi.ldap.LdapCtxFactory
</module-option>
<module-option name="java.naming.provider.url">
ldap://ldaphost.jboss.org:1389/
</module-option>
<module-option name="java.naming.security.authentication">
simple
</module-option>
<module-option name="principalDNPrefix">uid=</module-option>
<module-option name="uidAttributeID">userid</module-option>
<module-option name="roleAttributeID">roleName</module-option>
<module-option name="principalDNSuffix">,ou=People,o=jboss.org
</module-option>
<module-option name="rolesCtxDN">cn=JBossSX Tests,ou=Roles,o=jboss.org
</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
To help you understand all of the options of the LdapLoginModule, consider the
sample LDAP server data shown in Figure 8.9, “An LDAP server configuration
compatible with the testLdap sample configuration.”. This figure corresponds
to the testLdaplogin configuration just shown.
386 | P a g e
Figure 8.9. An LDAP server configuration compatible with the testLdap
sample configuration.
Take a look at the testLdap login module configuration in comparision to
the Figure 8.9, “An LDAP server configuration compatible with the testLdap
sample configuration.” schema.
The java.naming.factory.initial, java.naming.factory.url andjava.naming.security options indicate
the Sun LDAP JNDI provider implementation will be used, the LDAP server is
located on host ldaphost.jboss.org on port 1389, and that simple username and
password will be used to authenticate clients connecting to the LDAP server.
When the LdapLoginModule performs authentication of a user, it does so by
connecting to the LDAP server specified by the java.naming.factory.url.
The java.naming.security.principal property is built from the principalDNPrefix, passed in
username and principalDNSuffix as described above. For the testLdap configuration
example and a username of jduke, the java.naming.security.principal string would
be uid=jduke,ou=People,o=jboss.org. This corresponds to the LDAP context on the
lower right of Figure 8.9, “An LDAP server configuration compatible with the
testLdap sample configuration.” labeled as Principal Context.
The java.naming.security.credentials property would be set to the passed in password
and it would have to match the userPassword attribute of the principal context.
How a secured LDAP context stores the authentication credential information
387 | P a g e
depends on the LDAP server, so your LDAP server may handle the validation of
thejava.naming.security.credentials property differently.
Once authentication succeeds, the roles on which authorization will be based
are retrieved by performing a JNDI search of the LDAP context whose
distinguished name is given by the rolesCtxDN option value. For
the testLdap configuration this iscn=JBossSX Tests,ou=Roles,o=jboss.org and corresponds
to the LDAP context on the lower left of Figure 8.9, “An LDAP server
configuration compatible with the testLdap sample
configuration.” labeled Roles Context. The search attempts to locate any
subcontexts that contain an attribute whose name is given by
the uidAttributeID option, and whose value matches the username passed to the
login module. For any matching context, all values of the attribute whose
name is given by theroleAttributeID option are obtained. For
the testLdap configuration the attribute name that contains the roles is
called roleName. The resulting roleName values are stored in the
JAAS Subject associated with the LdapLoginModule as the Roles group principals that
will be used for role-based authorization. For the LDAP schema shown
in Figure 8.9, “An LDAP server configuration compatible with the testLdap
sample configuration.”, the roles that will be assigned to the
user jduke are TheDuke andAnimatedCharacter.
8.4.6.4. org.jboss.security.auth.spi.DatabaseServerLoginModule
The DatabaseServerLoginModule is a JDBC based login module that supports
authentication and role mapping. You would use this login module if you have
your username, password and role information in a JDBC accessible database.
TheDatabaseServerLoginModule is based on two logical tables:
Table Principals(PrincipalID text, Password text)
Table Roles(PrincipalID text, Role text, RoleGroup text)
The Principals table associates the user PrincipalID with the valid password and
the Roles table associates the user PrincipalID with its role sets. The roles used for
user permissions must be contained in rows with a RoleGroup column value
ofRoles. The tables are logical in that you can specify the SQL query that the
login module uses. All that is required is that the java.sql.ResultSet has the same
logical structure as the Principals and Roles tables described previously. The actual
388 | P a g e
names of the tables and columns are not relevant as the results are accessed
based on the column index. To clarify this notion, consider a database with
two tables, Principals and Roles, as already declared. The following statements
build the tables to contain aPrincipalID java with a Password of echoman in
the Principals table, a PrincipalID java with a role named Echo in the Roles RoleGroup in
the Roles table, and a PrincipalID java with a role named caller_java in
the CallerPrincipalRoleGroup in the Roles table:
INSERT INTO Principals VALUES('java', 'echoman')
INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
The supported login module configuration options include the following:
 dsJndiName: The JNDI name for the DataSource of the database
containing the logical Principals and Roles tables. If not specified this
defaults to java:/DefaultDS.
 principalsQuery: The prepared statement query equivalent to: select
Password from Principals where PrincipalID=?. If not specified this is the exact
prepared statement that will be used.
 rolesQuery: The prepared statement query equivalent to: select Role,
RoleGroup from Roles where PrincipalID=?. If not specified this is the exact
prepared statement that will be used.
 unauthenticatedIdentity=string: The principal name that should be
assigned to requests that contain no authentication information.
 password-stacking=useFirstPass: When password-stacking option is set, this
module first looks for a shared username and password under the
property
names javax.security.auth.login.name andjavax.security.auth.login.password respectivel
y in the login module shared state map. If found these are used as the
principal name and password. If not found the principal name and
password are set by this login module and stored under the property
names javax.security.auth.login.name and javax.security.auth.login.password respectivel
y.
 hashAlgorithm=string: The name of the java.security.MessageDigest algorithm
to use to hash the password. There is no default so this option must be
specified to enable hashing. When hashAlgorithm is specified, the clear text
password obtained from the callbackhandler is hashed before it is passed
389 | P a g e
to UsernamePasswordLoginModule.validatePassword as the inputPassword
argument. The expectedPassword as obtained from the database must be
comparably hashed.
 hashEncoding=base64|hex: The string format for the hashed pass and
must be either base64 or hex. Base64 is the default.
 hashCharset=string: The encoding used to convert the clear text
password to a byte array. The platform default encoding is the default
 ignorePasswordCase=true|false: A boolean flag indicating if the
password comparison should ignore case. This can be useful for hashed
password encoding where the case of the hashed password is not
significant.
 principalClass: An option that specifies a Principal implementation
class. This must support a constructor taking a string argument for the
princpal name.
As an example DatabaseServerLoginModule configuration, consider a custom table
schema like the following:
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32))
A sample Sun legacy format corresponding DatabaseServerLoginModule
configuration would be:
testDB {
org.jboss.security.auth.spi.DatabaseServerLoginModule required
dsJndiName="java:/MyDatabaseDS"
principalsQuery="select passwd from Users username where username=?"
rolesQuery="select userRoles, 'Roles' from UserRoles where username=?"
;
};
The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testDB">
<authentication>
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
flag="required">
<module-option name="dsJndiName">java:/MyDatabaseDS</module-option>
<module-option name="principalsQuery">
select passwd from Users username where username=?</module-option>
<module-option name="rolesQuery">
390 | P a g e
select userRoles, 'Roles' from UserRoles where username=?</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
8.4.6.5. BaseCertLoginModule
This is a login module which authenticates users based on X509 certificates. A
typical usecase for this login module is CLIENT-CERT authentication in the web
tier. This login module only performs authentication. You need to combine it
with another login module capable of acquiring the authorization roles to
completely define access to a secured web or EJB component. Two subclasses
of this login
module, CertRolesLoginModule and DatabaseCertLoginModule extend the
behavior to obtain the authorization roles from either a properties file or
database.
The BaseCertLoginModule needs a KeyStore to perform user validation. This is
obtained through a org.jboss.security.SecurityDomain implementation.
Typically, the SecurityDomain implementation is configured using
theorg.jboss.security.plugins.JaasSecurityDomain MBean as shown in
this jboss-service.xml configuration fragment:
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
name="jboss.web:service=SecurityDomain">
<constructor>
<arg type="java.lang.String" value="jmx-console"/>
</constructor>
<attribute name="KeyStoreURL">resource:localhost.keystore</attribute>
<attribute name="KeyStorePass">unit-tests-server</attribute>
</mbean>
This creates a security domain with the name jmx-
console whose SecurityDomain implementation is available via JNDI under the
name java:/jaas/jmx-console following the JBossSX security domain naming
pattern. To secure a web application such as thejmx-console.war using client
certs and role based authorization, one would first modify the web.xml to
declare the resources to be secured, along with the allowed roles and security
domain to be used for authentication and authorization.
<?xml version="1.0"?>
391 | P a g e
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with
the role JBossAdmin to access the HTML JMX console web
application </description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>JBoss JMX Console</realm-name>
</login-config>
<security-role>
<role-name>JBossAdmin</role-name>
</security-role>
</web-app>
Next we, need to specify the JBoss security domain in jboss-web.xml:
<jboss-web>
<security-domain>java:/jaas/jmx-console</security-domain>
</jboss-web>
Finally, you need to define the login module configuration for the jmx-console
security domain you just specified. This is done in the conf/login-config.xml file.
<application-policy name="jmx-console">
<authentication>
<login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
flag="required">
<module-option name="password-stacking">useFirstPass</module-option>
<module-option name="securityDomain">java:/jaas/jmx-console</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag="required">
<module-option name="password-stacking">useFirstPass</module-option>
<module-option name="usersProperties">jmx-console-users.properties</module-option>
392 | P a g e
<module-option name="rolesProperties">jmx-console-roles.properties</module-option>
</login-module>
</authentication>
</application-policy>
Here the BaseCertLoginModule is used for authentication of the client cert, and
the UsersRolesLoginModule is only used for authorization due to the password-
stacking=useFirstPass option. Both the localhost.keystore and the jmx-console-
roles.properties need an entry that maps to the principal associated with the
client cert. By default, the principal is created using the client certificate
distinguished name. Consider the following certificate:
[starksm@banshee9100 conf]$ keytool -printcert -file unit-tests-client.export
Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US
Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin
@jboss.com, OU=QA, O=JBoss Inc.
Serial number: 100103
Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005
Certificate fingerprints:
MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB
SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58
The localhost.keystore would need this cert stored with an alias of CN=unit-tests-client,
OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US and the jmx-console-roles.properties would
also need an entry for the same entry. Since the DN contains many characters
that are normally treated as delimiters, you will need to escape the problem
characters using a backslash ('') as shown here:
# A sample roles.properties file for use with the UsersRolesLoginModule
CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US=JBossAdmin
admin=JBossAdmin
8.4.6.6. org.jboss.security.auth.spi.ProxyLoginModule
The ProxyLoginModule is a login module that loads a delegate LoginModule using
the current thread context class loader. The purpose of this module is to work
around the current JAAS 1.0 class loader limitation that requires LoginModules to
be on the system classpath[2]
. Some custom LoginModules use classes that are
loaded from the JBoss server lib/ext directory and these are not available if
the LoginModule is placed on the system classpath. To work around this
limitation you use theProxyLoginModule to bootstrap the custom LoginModule.
The ProxyLoginModule has one required configuration option called moduleName. It
393 | P a g e
specifies the fully qualified class name of the LoginModule implementation that is
to be bootstrapped. Any number of additional configuration options may be
specified, and they will be passed to the bootstrapped login module.
As an example, consider a custom login module that makes use of some
service that is loaded from the JBoss lib/ext directory. The class name of the
custom login module is com.biz.CustomServiceLoginModule. A suitable Sun legacy
formatProxyLoginModule configuration entry for bootstrapping this custom login
module would be:
testProxy {
org.jboss.security.auth.spi.ProxyLoginModule required
moduleName=com.biz.CustomServiceLoginModule
customOption1=value1
customOption2=value2
customOption3=value3;
};
The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testProxy">
<authentication>
<login-module code="org.jboss.security.auth.spi.ProxyLoginModule"
flag="required">
<module-option name="moduleName">
com.biz.CustomServiceLoginModule
</module-option>
<module-option name="customOption1">value1</module-option>
<module-option name="customOption2">value2</module-option>
<module-option name="customOption3">value3</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
8.4.6.7. org.jboss.security.auth.spi.RunAsLoginModule
JBoss has a helper login module called RunAsLoginModule that pushes a run as role
for the duration of the login phase of authentication, and pops the run as role
in either the commit or abort phase. The purpose of this login module is to
provide a role for other login modules that need to access secured resources
in order to perform their authentication. An example would be a login module
394 | P a g e
that accesses an secured EJB. This login module must be configured ahead of
the login module(s) that need a run as role established.
The only login module configuration option is:
 roleName: the name of the role to use as the run as role during login
phase. If not specified a default of nobody is used.
8.4.6.8. org.jboss.security.ClientLoginModule
The ClientLoginModule is an implementation of LoginModule for use by JBoss clients
for the establishment of the caller identity and credentials. This simply sets
the org.jboss.security.SecurityAssociation.principal to the value of theNameCallback filled in
by the callbackhandler, and the org.jboss.security.SecurityAssociation.credential to the value
of the PasswordCallback filled in by the callbackhandler. This is the only supported
mechanism for a client to establish the current thread's caller. Both stand-
alone client applications and server environments, acting as JBoss EJB clients
where the security environment has not been configured to use JBossSX
transparently, need to use the ClientLoginModule. Of course, you could always set
the org.jboss.security.SecurityAssociation information directly, but this is considered an
internal API that is subject to change without notice.
Note that this login module does not perform any authentication. It merely
copies the login information provided to it into the JBoss server EJB invocation
layer for subsequent authentication on the server. If you need to perform
client-side authentication of users you would need to configure another login
module in addition to the ClientLoginModule.
The supported login module configuration options include the following:
 multi-threaded=true|false: When the multi-threaded option is set to
true, each login thread has its own principal and credential storage. This
is useful in client environments where multiple user identities are active
in separate threads. When true, each separate thread must perform its
own login. When set to false the login identity and credentials are
global variables that apply to all threads in the VM. The default for this
option is false.
395 | P a g e
 password-stacking=useFirstPass: When password-stacking option is set, this
module first looks for a shared username and password
using javax.security.auth.login.name and javax.security.auth.login.password respectively
in the login module shared state map. This allows a module configured
prior to this one to establish a valid username and password that
should be passed to JBoss. You would use this option if you want to
perform client-side authentication of clients using some other login
module such as the LdapLoginModule.
 restore-login-identity=[true|false]: When restore-login-identity is true,
the SecurityAssociation principal and credential seen on entry to
the login() method are saved and restored on either abort or logout.
When false (the default), the abort and logout simply clear
the SecurityAssociation. A restore-login-identity of true is needed if one need to
change identities and then restore the original caller identity.
A sample login configuration for ClientLoginModule is the default configuration
entry found in the JBoss distribution client/auth.conf file. The configuration is:
other {
// Put your login modules that work without jBoss here
// jBoss LoginModule
org.jboss.security.ClientLoginModule required;
// Put your login modules that need jBoss here
};
8.4.7. Writing Custom Login Modules
If the login modules bundled with the JBossSX framework do not work with
your security environment, you can write your own custom login module
implementation that does.
Recall from the section on the JaasSecurityManager architecture that
the JaasSecurityManager expected a particular usage pattern of the Subject principals
set. You need to understand the JAAS Subject class's information storage
features and the expected usage of these features to be able to write a login
module that works with the JaasSecurityManager. This section examines this
requirement and introduces two abstract base LoginModule implementations
that can help you implement your own custom login modules.
396 | P a g e
You can obtain security information associated with a Subject in six ways using
the following methods:
java.util.Set getPrincipals()
java.util.Set getPrincipals(java.lang.Class c)
java.util.Set getPrivateCredentials()
java.util.Set getPrivateCredentials(java.lang.Class c)
java.util.Set getPublicCredentials()
java.util.Set getPublicCredentials(java.lang.Class c)
For Subject identities and roles, JBossSX has selected the most natural choice:
the principals sets obtained via getPrincipals() and getPrincipals(java.lang.Class). The
usage pattern is as follows:
 User identities (username, social security number, employee ID, and so
on) are stored as java.security.Principal objects in the SubjectPrincipals set.
The Principal implementation that represents the user identity must base
comparisons and equality on the name of the principal. A suitable
implementation is available as the org.jboss.security.SimplePrincipal class.
Other Principal instances may be added to the SubjectPrincipals set as needed.
 The assigned user roles are also stored in the Principals set, but they are
grouped in named role sets using java.security.acl.Group instances.
The Group interface defines a collection of Principals and/or Groups, and is a
subinterface ofjava.security.Principal. Any number of role sets can be
assigned to a Subject. Currently, the JBossSX framework uses two well-
known role sets with the names Roles and CallerPrincipal. The Roles Group is
the collection of Principals for the named roles as known in the
application domain under which the Subject has been authenticated. This
role set is used by methods like the EJBContext.isCallerInRole(String), which EJBs
can use to see if the current caller belongs to the named application
domain role. The security interceptor logic that performs method
permission checks also uses this role set. The CallerPrincipalGroup consists of
the single Principal identity assigned to the user in the application
domain. TheEJBContext.getCallerPrincipal() method uses the CallerPrincipal to
allow the application domain to map from the operation environment
identity to a user identity suitable for the application. If a Subject does
not have aCallerPrincipalGroup, the application identity is the same as
operational environment identity.
397 | P a g e
8.4.7.1. Support for the Subject Usage Pattern
To simplify correct implementation of the Subject usage patterns described in
the preceding section, JBossSX includes two abstract login modules that
handle the population of the authenticated Subject with a template pattern that
enforces correct Subjectusage. The most generic of the two is
the org.jboss.security.auth.spi.AbstractServerLoginModule class. It provides a concrete
implementation of the javax.security.auth.spi.LoginModule interface and offers
abstract methods for the key tasks specific to an operation environment
security infrastructure. The key details of the class are highlighted in the
following class fragment. The JavaDoc comments detail the responsibilities of
subclasses.
package org.jboss.security.auth.spi;
/**
* This class implements the common functionality required for a JAAS
* server-side LoginModule and implements the JBossSX standard
* Subject usage pattern of storing identities and roles. Subclass
* this module to create your own custom LoginModule and override the
* login(), getRoleSets(), and getIdentity() methods.
*/
public abstract class AbstractServerLoginModule
implements javax.security.auth.spi.LoginModule
{
protected Subject subject;
protected CallbackHandler callbackHandler;
protected Map sharedState;
protected Map options;
protected Logger log;
/** Flag indicating if the shared credential should be used */
protected boolean useFirstPass;
/**
* Flag indicating if the login phase succeeded. Subclasses that
* override the login method must set this to true on successful
* completion of login
*/
protected boolean loginOk;
// ...
/**
* Initialize the login module. This stores the subject,
* callbackHandler and sharedState and options for the login
* session. Subclasses should override if they need to process
* their own options. A call to super.initialize(...) must be
* made in the case of an override.
398 | P a g e
*
* <p>
* The options are checked for the <em>password-stacking</em> parameter.
* If this is set to "useFirstPass", the login identity will be taken from the
* <code>javax.security.auth.login.name</code> value of the sharedState map,
* and the proof of identity from the
* <code>javax.security.auth.login.password</code> value of the sharedState map.
*
* @param subject the Subject to update after a successful login.
* @param callbackHandler the CallbackHandler that will be used to obtain the
* the user identity and credentials.
* @param sharedState a Map shared between all configured login module instances
* @param options the parameters passed to the login module.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
// ...
}
/**
* Looks for javax.security.auth.login.name and
* javax.security.auth.login.password values in the sharedState
* map if the useFirstPass option was true and returns true if
* they exist. If they do not or are null this method returns
* false.
* Note that subclasses that override the login method
* must set the loginOk ivar to true if the login succeeds in
* order for the commit phase to populate the Subject. This
* implementation sets loginOk to true if the login() method
* returns true, otherwise, it sets loginOk to false.
*/
public boolean login()
throws LoginException
{
// ...
}
/**
* Overridden by subclasses to return the Principal that
* corresponds to the user primary identity.
*/
abstract protected Principal getIdentity();
/**
* Overridden by subclasses to return the Groups that correspond
* to the role sets assigned to the user. Subclasses should
399 | P a g e
* create at least a Group named "Roles" that contains the roles
* assigned to the user. A second common group is
* "CallerPrincipal," which provides the application identity of
* the user rather than the security domain identity.
*
* @return Group[] containing the sets of roles
*/
abstract protected Group[] getRoleSets() throws LoginException;
}
You'll need to to pay attention to the loginOk instance variable. This must be set
to true if the login succeeds, false otherwise by any subclasses that override
the login method. Failure to set this variable correctly will result in the commit
method either not updating the Subject when it should, or updating
the Subject when it should not. Tracking the outcome of the login phase was
added to allow login module to be chained together with control flags that do
not require that the login module succeed in order for the overall login to
succeed.
The second abstract base login module suitable for custom login modules is
the org.jboss.security.auth.spi.UsernamePasswordLoginModule. The login module further
simplifies custom login module implementation by enforcing a string-based
username as the user identity and a char[] password as the authentication
credential. It also supports the mapping of anonymous users (indicated by a
null username and password) to a Principal with no roles. The key details of the
class are highlighted in the following class fragment. The JavaDoc comments
detail the responsibilities of subclasses.
package org.jboss.security.auth.spi;
/**
* An abstract subclass of AbstractServerLoginModule that imposes a
* an identity == String username, credentials == String password
* view on the login process. Subclasses override the
* getUsersPassword() and getUsersRoles() methods to return the
* expected password and roles for the user.
*/
public abstract class UsernamePasswordLoginModule
extends AbstractServerLoginModule
{
/** The login identity */
private Principal identity;
/** The proof of login identity */
private char[] credential;
400 | P a g e
/** The principal to use when a null username and password are seen */
private Principal unauthenticatedIdentity;
/**
* The message digest algorithm used to hash passwords. If null then
* plain passwords will be used. */
private String hashAlgorithm = null;
/**
* The name of the charset/encoding to use when converting the
* password String to a byte array. Default is the platform's
* default encoding.
*/
private String hashCharset = null;
/** The string encoding format to use. Defaults to base64. */
private String hashEncoding = null;
// ...
/**
* Override the superclass method to look for an
* unauthenticatedIdentity property. This method first invokes
* the super version.
*
* @param options,
* @option unauthenticatedIdentity: the name of the principal to
* assign and authenticate when a null username and password are
* seen.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
super.initialize(subject, callbackHandler, sharedState,
options);
// Check for unauthenticatedIdentity option.
Object option = options.get("unauthenticatedIdentity");
String name = (String) option;
if (name != null) {
unauthenticatedIdentity = new SimplePrincipal(name);
}
}
// ...
/**
* A hook that allows subclasses to change the validation of the
* input password against the expected password. This version
401 | P a g e
* checks that neither inputPassword or expectedPassword are null
* and that inputPassword.equals(expectedPassword) is true;
*
* @return true if the inputPassword is valid, false otherwise.
*/
protected boolean validatePassword(String inputPassword,
String expectedPassword)
{
if (inputPassword == null || expectedPassword == null) {
return false;
}
return inputPassword.equals(expectedPassword);
}
/**
* Get the expected password for the current username available
* via the getUsername() method. This is called from within the
* login() method after the CallbackHandler has returned the
* username and candidate password.
*
* @return the valid password String
*/
abstract protected String getUsersPassword()
throws LoginException;
}
The choice of subclassing
the AbstractServerLoginModule versus UsernamePasswordLoginModule is simply based on
whether a String based username and String credential are usable for the
authentication technology you are writing the login module for. If the string
based semantic is valid, then subclass UsernamePasswordLoginModule, else
subclass AbstractServerLoginModule.
The steps you are required to perform when writing a custom login module
are summerized in the following depending on which base login module class
you choose. When writing a custom login module that integrates with your
security infrastructure, you should start by
subclassing AbstractServerLoginModule or UsernamePasswordLoginModule to ensure that
your login module provides the authenticated Principal information in the form
expected by the JBossSX security manager.
When subclassing the AbstractServerLoginModule, you need to override the
following:
402 | P a g e
 void initialize(Subject, CallbackHandler, Map, Map): if you have custom options to
parse.
 boolean login(): to perform the authentication activity. Be sure to set
the loginOk instance variable to true if login succeeds, false if it fails.
 Principal getIdentity(): to return the Principal object for the user authenticated
by the log() step.
 Group[] getRoleSets(): to return at least one Group named Roles that contains
the roles assigned to the Principal authenticated during login(). A second
common Group is named CallerPrincipal and provides the user's application
identity rather than the security domain identity.
When subclassing the UsernamePasswordLoginModule, you need to override the
following:
 void initialize(Subject, CallbackHandler, Map, Map): if you have custom options to
parse.
 Group[] getRoleSets(): to return at least one Group named Roles that contains
the roles assigned to the Principal authenticated during login(). A second
common Group is named CallerPrincipal and provides the user's application
identity rather than the security domain identity.
 String getUsersPassword(): to return the expected password for the current
username available via the getUsername() method.
The getUsersPassword() method is called from within login() after
the callbackhandler returns the username and candidate password.
8.4.7.2. A Custom LoginModule Example
In this section we will develop a custom login module example. It will extend
the UsernamePasswordLoginModule and obtains a user's password and role names
from a JNDI lookup. The idea is that there is a JNDI context that will return a
user's password if you perform a lookup on the context using a name of the
form password/<username> where <username> is the current user being
authenticated. Similary, a lookup of the form roles/<username> returns the
requested user's roles.
The source code for the example is located in
the src/main/org/jboss/chap8/ex2 directory of the book examples. Example 8.12, “ A
JndiUserAndPass custom login module” shows the source code for
403 | P a g e
the JndiUserAndPass custom login module. Note that because this extends the
JBoss UsernamePasswordLoginModule, all the JndiUserAndPass does is obtain the user's
password and roles from the JNDI store. The JndiUserAndPass does not concern
itself with the JAAS LoginModule operations.
Example 8.12. A JndiUserAndPass custom login module
package org.jboss.chap8.ex2;
import java.security.acl.Group;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
/**
* An example custom login module that obtains passwords and roles
* for a user from a JNDI lookup.
*
* @author Scott.Stark@jboss.org
* @version $Revision: 1.15 $
*/
public class JndiUserAndPass
extends UsernamePasswordLoginModule
{
/** The JNDI name to the context that handles the password/username lookup */
private String userPathPrefix;
/** The JNDI name to the context that handles the roles/ username lookup */
private String rolesPathPrefix;
/**
* Override to obtain the userPathPrefix and rolesPathPrefix options.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options)
{
super.initialize(subject, callbackHandler, sharedState, options);
userPathPrefix = (String) options.get("userPathPrefix");
rolesPathPrefix = (String) options.get("rolesPathPrefix");
}
/**
404 | P a g e
* Get the roles the current user belongs to by querying the
* rolesPathPrefix + '/' + super.getUsername() JNDI location.
*/
protected Group[] getRoleSets() throws LoginException
{
try {
InitialContext ctx = new InitialContext();
String rolesPath = rolesPathPrefix + '/' + super.getUsername();
String[] roles = (String[]) ctx.lookup(rolesPath);
Group[] groups = {new SimpleGroup("Roles")};
log.info("Getting roles for user="+super.getUsername());
for(int r = 0; r < roles.length; r ++) {
SimplePrincipal role = new SimplePrincipal(roles[r]);
log.info("Found role="+roles[r]);
groups[0].addMember(role);
}
return groups;
} catch(NamingException e) {
log.error("Failed to obtain groups for
user="+super.getUsername(), e);
throw new LoginException(e.toString(true));
}
}
/**
* Get the password of the current user by querying the
* userPathPrefix + '/' + super.getUsername() JNDI location.
*/
protected String getUsersPassword()
throws LoginException
{
try {
InitialContext ctx = new InitialContext();
String userPath = userPathPrefix + '/' + super.getUsername();
log.info("Getting password for user="+super.getUsername());
String passwd = (String) ctx.lookup(userPath);
log.info("Found password="+passwd);
return passwd;
} catch(NamingException e) {
log.error("Failed to obtain password for
user="+super.getUsername(), e);
throw new LoginException(e.toString(true));
}
}
}
The details of the JNDI store are found in
the org.jboss.chap8.ex2.service.JndiStore MBean. This service binds an ObjectFactory that
405 | P a g e
returns a javax.naming.Context proxy into JNDI. The proxy handles lookup
operations done against it by checking the prefix of the lookup name
against password and roles. When the name begins with password, a user's
password is being requested. When the name begins with roles the user's roles
are being requested. The example implementation always returns a password
of theduke and an array of roles names equal to {"TheDuke", "Echo"} regardless of
what the username is. You can experiment with other implementations as you
wish.
The example code includes a simple session bean for testing the custom login
module. To build, deploy and run the example, execute the following
command from the examples directory. Make sure you have the JBoss server
running. The key lines from the client are given in Example 8.13, “The chap8-
ex2 secured client access output” while the server side operation of the is
shown in Example 8.14, “The chap8-ex2 server side behavior of the
JndiUserAndPass”.
Example 8.13. The chap8-ex2 secured client access output
[nr@toki examples]$ ant -Dchap=chap8 -Dex=2 run-example
Buildfile: build.xml
...
run-example2:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 5 seconds for deploy...
[java] [INFO,ExClient] Login with username=jduke, password=theduke
[java] [INFO,ExClient] Looking up EchoBean2
[java] [INFO,ExClient] Created Echo
[java] [INFO,ExClient] Echo.echo('Hello') = Hello
Example 8.14. The chap8-ex2 server side behavior of the JndiUserAndPass
17:48:11,458 INFO [EjbModule] Deploying EchoBean2
17:48:11,890 INFO [JndiStore] Start, bound security/store
17:48:11,896 INFO [SecurityConfig] Using JAAS AuthConfig: jar:file:/private/tmp/jboss-3.2.6/s
erver/default/tmp/deploy/tmp22821chap8-ex2.jar-contents/chap8-ex2.sar!/META-INF/login-config.x
ml
17:48:12,355 INFO [EJBDeployer] Deployed: file:/private/tmp/jboss-3.2.6/server/default/deploy
/chap8-ex2.jar
The choice of using the JndiUserAndPass custom login module for the server side
authentication of the user is determined by the login configuration for the
406 | P a g e
example security domain. The EJB JAR META-INF/jboss.xml descriptor sets the
security domain and the sar META-INF/login-config.xml descriptor defines the login
module configuration. The contents of these descriptors are shown
in Example 8.15, “The chap8-ex2 security domain and login module
configuration”.
Example 8.15. The chap8-ex2 security domain and login module
configuration
<?xml version="1.0"?>
<jboss>
<security-domain>java:/jaas/chap8-ex2</security-domain>
</jboss>
Example 8.16. The login-config.xml configuration fragment for the chap8-ex2
application
<application-policy name = "chap8-ex2">
<authentication>
<login-module code="org.jboss.chap8.ex2.JndiUserAndPass"
flag="required">
<module-option name = "userPathPrefix">/security/store/password</module-option>
<module-option name = "rolesPathPrefix">/security/store/roles</module-option>
</login-module>
</authentication>
</application-policy>
8.4.8. The DynamicLoginConfig service
Security domains defined in the login-config.xml file are essentially static. They are
read when JBoss starts up, but there is no easy way to add a new security
domain or change the definition for an existing one.
The DynamicLoginConfig service allows you to dynamically deploy security domains.
This allows you to specify JAAS login configuration as part of a deployment (or
just as a standalone service) rather than having to edit the static login-
config.xml file.
The service supports the following attributes:
 AuthConfig: The resource path to the JAAS login configuration file to
use. This defaults to login-config.xml
407 | P a g e
 LoginConfigService: the XMLLoginConfig service name to use for loading.
This service must support a String loadConfig(URL) operation to load the
configurations.
 SecurityManagerService: The SecurityManagerService name used to flush the
registered security domains. This service must support
a flushAuthenticationCache(String) operation to flush the case for the argument
security domain. Setting this triggers the flush of the authentication
caches when the service is stopped.
Here is an examble MBean definition using the DynamicLoginConfig service.
<server>
<mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="...">
<attribute name="AuthConfig">login-config.xml</attribute>
<!-- The service which supports dynamic processing of login-config.xml
configurations.
-->
<depends optional-attribute-name="LoginConfigService">
jboss.security:service=XMLLoginConfig </depends>
<!-- Optionally specify the security mgr service to use when
this service is stopped to flush the auth caches of the domains
registered by this service.
-->
<depends optional-attribute-name="SecurityManagerService">
jboss.security:service=JaasSecurityManager </depends>
</mbean>
</server>
This will load the specified AuthConfig resource using the
specified LoginConfigService MBean by invoking loadConfig with the apropriate
resource URL. When the service is stopped the configurations are removed.
The resource specified may be either an XML file, or a Sun JAAS login
configuration.
8.5. The Secure Remote Password (SRP) Protocol
The SRP protocol is an implementation of a public key exchange handshake
described in the Internet standards working group request for comments
2945(RFC2945). The RFC2945 abstract states:
This document describes a cryptographically strong network authentication
mechanism known as the Secure Remote Password (SRP) protocol. This
408 | P a g e
mechanism is suitable for negotiating secure connections using a user-
supplied password, while eliminating the security problems traditionally
associated with reusable passwords. This system also performs a secure key
exchange in the process of authentication, allowing security layers (privacy
and/or integrity protection) to be enabled during the session. Trusted key
servers and certificate infrastructures are not required, and clients are not
required to store or manage any long-term keys. SRP offers both security and
deployment advantages over existing challenge-response techniques, making
it an ideal drop-in replacement where secure password authentication is
needed.
Note: The complete RFC2945 specification can be obtained
from http://www.rfc-editor.org/rfc.html. Additional information on the SRP
algorithm and its history can be found at http://www-cs-
students.stanford.edu/~tjw/srp/.
SRP is similar in concept and security to other public key exchange algorithms,
such as Diffie-Hellman and RSA. SRP is based on simple string passwords in a
way that does not require a clear text password to exist on the server. This is
in contrast to other public key-based algorithms that require client certificates
and the corresponding certificate management infrastructure.
Algorithms like Diffie-Hellman and RSA are known as public key exchange
algorithms. The concept of public key algorithms is that you have two keys,
one public that is available to everyone, and one that is private and known
only to you. When someone wants to send encrypted information to you, then
encrpyt the information using your public key. Only you are able to decrypt
the information using your private key. Contrast this with the more traditional
shared password based encryption schemes that require the sender and
receiver to know the shared password. Public key algorithms eliminate the
need to share passwords. For more information on public key algorithms as
well as numerous other cryptographic algorithms, see Applied Cryptography,
Second Edition by Bruce Schneier, ISBN 0-471-11709-9.
The JBossSX framework includes an implementation of SRP that consists of the
following elements:
409 | P a g e
 An implementation of the SRP handshake protocol that is independent
of any particular client/server protocol
 An RMI implementation of the handshake protocol as the default
client/server SRP implementation
 A client side JAAS LoginModule implementation that uses the RMI
implementation for use in authenticating clients in a secure fashion
 A JMX MBean for managing the RMI server implementation. The MBean
allows the RMI server implementation to be plugged into a JMX
framework and externalizes the configuration of the verification
information store. It also establishes an authentication cache that is
bound into the JBoss server JNDI namespace.
 A server side JAAS LoginModule implementation that uses the
authentication cache managed by the SRP JMX MBean.
Figure 8.10, “The JBossSX components of the SRP client-server
framework.” gives a diagram of the key components involved in the JBossSX
implementation of the SRP client/server framework.
410 | P a g e
Figure 8.10. The JBossSX components of the SRP client-server framework.
On the client side, SRP shows up as a custom JAAS LoginModule implementation
that communicates to the authentication server through
an org.jboss.security.srp.SRPServerInterface proxy. A client enables authentication using
SRP by creating a login configuration entry that includes
the org.jboss.security.srp.jaas.SRPLoginModule. This module supports the following
configuration options:
 principalClassName: This option is no longer supported. The principal
class is now always org.jboss.security.srp.jaas.SRPPrincipal.
 srpServerJndiName: The JNDI name of the SRPServerInterface object to use
for communicating with the SRP authentication server. If
411 | P a g e
both srpServerJndiName and srpServerRmiUrl options are specified,
the srpServerJndiName is tried before srpServerRmiUrl.
 srpServerRmiUrl: The RMI protocol URL string for the location of
the SRPServerInterface proxy to use for communicating with the SRP
authentication server.
 externalRandomA: A true/false flag indicating if the random
component of the client public key A should come from the user
callback. This can be used to input a strong cryptographic random
number coming from a hardware token for example.
 hasAuxChallenge: A true/false flag indicating an that a string will be
sent to the server as an additional challenge for the server to validate. If
the client session supports an encryption cipher then a temporary
cipher will be created using the session private key and the challenge
object sent as a javax.crypto.SealedObject.
 multipleSessions: a true/false flag indicating if a given client may have
multiple SRP login sessions active simultaneously.
Any other options passed in that do not match one of the previous named
options is treated as a JNDI property to use for the environment passed to
the IntialContext constructor. This is useful if the SRP server interface is not
available from the defaultIntialContext.
The SRPLoginModule needs to be configured along with the
standard ClientLoginModule to allow the SRP authentication credentials to be used
for validation of access to security J2EE components. An example login
configuration entry that demonstrates such a setup is:
srp {
org.jboss.security.srp.jaas.SRPLoginModule required
srpServerJndiName="SRPServerInterface"
;
org.jboss.security.ClientLoginModule required
password-stacking="useFirstPass"
;
};
On the JBoss server side, there are two MBeans that manage the objects that
collectively make up the SRP server. The primary service is
the org.jboss.security.srp.SRPService MBean, and it is responsible for exposing an RMI
412 | P a g e
accessible version of the SRPServerInterface as well as updating the SRP
authentication session cache. The configurable SRPService MBean attributes
include the following:
 JndiName: The JNDI name from which the SRPServerInterface proxy
should be available. This is the location where the SRPService binds the
serializable dynamic proxy to the SRPServerInterface. If not specified it
defaults tosrp/SRPServerInterface.
 VerifierSourceJndiName: The JNDI name of
the SRPVerifierSource implementation that should be used by the SRPService.
If not set it defaults to srp/DefaultVerifierSource.
 AuthenticationCacheJndiName: The JNDI name under which the
authentication org.jboss.util.CachePolicy implementation to be used for
caching authentication information is bound. The SRP session cache is
made available for use through this binding. If not specified it defaults
to srp/AuthenticationCache.
 ServerPort: RMI port for the SRPRemoteServerInterface. If not specified it
defaults to 10099.
 ClientSocketFactory: An optional
custom java.rmi.server.RMIClientSocketFactory implementation class name used
during the export of the SRPServerInterface. If not specified the
default RMIClientSocketFactory is used.
 ServerSocketFactory: An optional
custom java.rmi.server.RMIServerSocketFactory implementation class name used
during the export of the SRPServerInterface. If not specified the
default RMIServerSocketFactory is used.
 AuthenticationCacheTimeout: Specifies the timed cache policy timeout
in seconds. If not specified this defaults to 1800 seconds(30 minutes).
 AuthenticationCacheResolution: Specifies the timed cache policy
resolution in seconds. This controls the interval between checks for
timeouts. If not specified this defaults to 60 seconds(1 minute).
 RequireAuxChallenge: Set if the client must supply an auxillary
challenge as part of the verify phase. This gives control over whether
the SRPLoginModule configuration used by the client must have
the useAuxChallenge option enabled.
 OverwriteSessions: A flag indicating if a successful user auth for an
existing session should overwrite the current session. This controls the
413 | P a g e
behavior of the server SRP session cache when clients have not enabled
the multiple session per user mode. The default is false meaning that
the second attempt by a user to authentication will succeeed, but the
resulting SRP session will not overwrite the previous SRP session state.
The one input setting is the VerifierSourceJndiName attribute. This is the location of
the SRP password information store implementation that must be provided
and made available through JNDI. The org.jboss.security.srp SRPVerifierStoreService is an
example MBean service that binds an implementation of
the SRPVerifierStore interface that uses a file of serialized objects as the persistent
store. Although not realistic for a production environment, it does allow for
testing of the SRP protocol and provides an example of the requirements for
an SRPVerifierStore service. The configurable SRPVerifierStoreService MBean attributes
include the following:
 JndiName: The JNDI name from which the SRPVerifierStore implementation
should be available. If not specified it defaults to srp/DefaultVerifierSource.
 StoreFile: The location of the user password verifier serialized object
store file. This can be either a URL or a resource name to be found in
the classpath. If not specified it defaults to SRPVerifierStore.ser.
The SRPVerifierStoreService MBean also supports addUser and delUser operations for
addition and deletion of users. The signatures are:
public void addUser(String username, String password) throws IOException;
public void delUser(String username) throws IOException;
An example configuration of these services is presented in Section 8.5, “The
Secure Remote Password (SRP) Protocol”.
8.5.1. Providing Password Information for SRP
The default implementation of the SRPVerifierStore interface is not likely to be
suitable for you production security environment as it requires all password
hash information to be available as a file of serialized objects. You need to
provide an MBean service that provides an implementation of
the SRPVerifierStore interface that integrates with your existing security
information stores. The SRPVerifierStore interface is shown in.
414 | P a g e
Example 8.17. The SRPVerifierStore interface
package org.jboss.security.srp;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyException;
public interface SRPVerifierStore
{
public static class VerifierInfo implements Serializable
{
/**
* The username the information applies to. Perhaps redundant
* but it makes the object self contained.
*/
public String username;
/** The SRP password verifier hash */
public byte[] verifier;
/** The random password salt originally used to verify the password */
public byte[] salt;
/** The SRP algorithm primitive generator */
public byte[] g;
/** The algorithm safe-prime modulus */
public byte[] N;
}
/**
* Get the indicated user's password verifier information.
*/
public VerifierInfo getUserVerifier(String username)
throws KeyException, IOException;
/**
* Set the indicated users' password verifier information. This
* is equivalent to changing a user's password and should
* generally invalidate any existing SRP sessions and caches.
*/
public void setUserVerifier(String username, VerifierInfo info)
throws IOException;
/**
* Verify an optional auxillary challenge sent from the client to
* the server. The auxChallenge object will have been decrypted
* if it was sent encrypted from the client. An example of a
* auxillary challenge would be the validation of a hardware token
* (SafeWord, SecureID, iButton) that the server validates to
* further strengthen the SRP password exchange.
*/
public void verifyUserChallenge(String username, Object auxChallenge)
415 | P a g e
throws SecurityException;
}
The primary function of a SRPVerifierStore implementation is to provide access to
the SRPVerifierStore.VerifierInfo object for a given username.
The getUserVerifier(String) method is called by the SRPService at that start of a user
SRP session to obtain the parameters needed by the SRP algorithm. The
elements of the VerifierInfo objects are:
 username: The user's name or id used to login.
 verifier: This is the one-way hash of the password or PIN the user
enters as proof of their identity. The org.jboss.security.Util class has
a calculateVerifier method that performs that password hashing algorithm.
The output passwordH(salt | H(username | ':' | password)) as defined by
RFC2945. Here H is the SHA secure hash function. The username is
converted from a string to a byte[] using the UTF-8 encoding.
 salt: This is a random number used to increase the difficulty of a brute
force dictionary attack on the verifier password database in the event
that the database is compromised. It is a value that should be
generated from a cryptographically strong random number algorithm
when the user's existing clear-text password is hashed.
 g: The SRP algorithm primitive generator. In general this can be a well
known fixed parameter rather than a per-user setting.
The org.jboss.security.srp.SRPConf utility class provides several settings for g
including a good default which can obtained
via SRPConf.getDefaultParams().g().
 N: The SRP algorithm safe-prime modulus. In general this can be a well
known fixed parameter rather than a per-user setting.
The org.jboss.security.srp.SRPConf utility class provides several settings
for N including a good default which can obtained
via SRPConf.getDefaultParams().N().
So, step 1 of integrating your existing password store is the creation of a
hashed version of the password information. If your passwords are already
store in an irreversible hashed form, then this can only be done on a per-user
basis as part of an upgrade proceedure for example. Note that
the setUserVerifier(String, VerifierInfo) method is not used by the current SRPSerivce
416 | P a g e
and may be implemented as noop method, or even one that throws an
exception stating that the store is read-only.
Step 2 is the creation of the custom SRPVerifierStore interface implementation
that knows how to obtain the VerifierInfo from the store you created in step 1.
The verifyUserChallenge(String, Object) method of the interface is only called if the
client SRPLoginModule configuration specifies the hasAuxChallenge option. This can be
used to integrate existing hardware token based schemes like SafeWord or
Radius into the SRP algorithm.
Step 3 is the creation of an MBean that makes the step 2 implementation of
the SRPVerifierStore interface available via JNDI, and exposes any configurable
parameters you need. In addition to the
defaultorg.jboss.security.srp.SRPVerifierStoreService example, the SRP example presented
later in this chapter provides a Java properties file
based SRPVerifierStore implementation. Between the two examples you should
have enough to integrate your security store.
8.5.2. Inside of the SRP algorithm
The appeal of the SRP algorithm is that is allows for mutual authentication of
client and server using simple text passwords without a secure communication
channel. You might be wondering how this is done. If you want the complete
details and theory behind the algorithm, refer to the SRP references
mentioned in a note earlier. There are six steps that are performed to
complete authentication:
1. The client side SRPLoginModule retrieves the SRPServerInterface instance
for the remote authentication server from the naming service.
2. The client side SRPLoginModule next requests the SRP parameters
associated with the username attempting the login. There are a number
of parameters involved in the SRP algorithm that must be chosen when
the user password is first transformed into the verifier form used by the
SRP algorithm. Rather than hard-coding the parameters (which could be
done with minimal security risk), the JBossSX implementation allows a
user to retrieve this information as part of the exchange protocol.
ThegetSRPParameters(username) call retrieves the SRP parameters for the
given username.
417 | P a g e
3. The client side SRPLoginModule begins an SRP session by creating
an SRPClientSession object using the login username, clear-text password,
and SRP parameters obtained from step 2. The client then creates a
random number A that will be used to build the private SRP session key.
The client then initializes the server side of the SRP session by invoking
the SRPServerInterface.init method and passes in the username and client
generated random number A. The server returns its own random
number B. This step corresponds to the exchange of public keys.
4. The client side SRPLoginModule obtains the private SRP session key that has
been generated as a result of the previous messages exchanges. This is
saved as a private credential in the login Subject. The server challenge
response M2 from step 4 is verified by invoking
the SRPClientSession.verify method. If this succeeds, mutual authentication of
the client to server, and server to client have been completed.The client
side SRPLoginModule next creates a challenge M1 to the server by
invokingSRPClientSession.response method passing the server random
number B as an argument. This challenge is sent to the server via
the SRPServerInterface.verify method and server's response is saved as M2.
This step corresponds to an exchange of challenges. At this point the
server has verified that the user is who they say they are.
5. The client side SRPLoginModule saves the login username and M1 challenge
into the LoginModule sharedState map. This is used as the Principal name
and credentials by the standard JBoss ClientLoginModule. The M1 challenge
is used in place of the password as proof of identity on any method
invocations on J2EE components. The M1 challenge is a
cryptographically strong hash associated with the SRP session. Its
interception via a third partly cannot be used to obtain the user's
password.
6. At the end of this authentication protocol, the SRPServerSession has
been placed into the SRPService authentication cache for subsequent
use by the SRPCacheLoginModule.
Although SRP has many interesting properties, it is still an evolving component
in the JBossSX framework and has some limitations of which you should be
aware. Issues of note include the following:
418 | P a g e
 Because of how JBoss detaches the method transport protocol from the
component container where authentication is performed, an
unauthorized user could snoop the SRP M1 challenge and effectively use
the challenge to make requests as the associated username. Custom
interceptors that encrypt the challenge using the SRP session key can be
used to prevent this issue.
 The SRPService maintains a cache of SRP sessions that time out after a
configurable period. Once they time out, any subsequent J2EE
component access will fail because there is currently no mechanism for
transparently renegotiating the SRP authentication credentials. You
must either set the authentication cache timeout very long (up to
2,147,483,647 seconds, or approximately 68 years), or handle re-
authentication in your code on failure.
 By default there can only be one SRP session for a given username.
Because the negotiated SRP session produces a private session key that
can be used for encryption/decryption between the client and server,
the session is effectively a stateful one. JBoss supports for multiple SRP
sessions per user, but you cannot encrypt data with one session key and
then decrypt it with another.
To use end-to-end SRP authentication for J2EE component calls, you need to
configure the security domain under which the components are secured to
use the org.jboss.security.srp.jaas.SRPCacheLoginModule. The SRPCacheLoginModule has a
single configuration option named cacheJndiName that sets the JNDI location of
the SRP authentication CachePolicy instance. This must correspond to
the AuthenticationCacheJndiName attribute value of the SRPService MBean.
TheSRPCacheLoginModule authenticates user credentials by obtaining the client
challenge from the SRPServerSession object in the authentication cache and
comparing this to the challenge passed as the user credentials. Figure 8.11, “A
sequence diagram illustrating the interaction of the SRPCacheLoginModule
with the SRP session cache.” illustrates the operation of the
SRPCacheLoginModule.login method implementation.
419 | P a g e
Figure 8.11. A sequence diagram illustrating the interaction of the
SRPCacheLoginModule with the SRP session cache.
8.5.2.1. An SRP example
We have covered quite a bit of material on SRP and now its time to
demonstrate SRP in practice with an example. The example demonstrates
client side authentication of the user via SRP as well as subsequent secured
access to a simple EJB using the SRP session challenge as the user credential.
The test code deploys an EJB JAR that includes a sar for the configuration of
the server side login module configuration and SRP services. As in the previous
examples we will dynamically install the server side login module
configuration using the SecurityConfig MBean. In this example we also use a
custom implementation of the SRPVerifierStore interface that uses an in memory
store that is seeded from a Java properties file rather than a serialized object
store as used by the SRPVerifierStoreService. This custom service
is org.jboss.chap8.ex3.service.PropertiesVerifierStore. The following shows the contents of
the JAR that contains the example EJB and SRP services.
420 | P a g e
[orb@toki examples]$ java -cp output/classes ListJar output/chap8/chap8-ex3.jar
output/chap8/chap8-ex3.jar
+- META-INF/MANIFEST.MF
+- META-INF/ejb-jar.xml
+- META-INF/jboss.xml
+- org/jboss/chap8/ex3/Echo.class
+- org/jboss/chap8/ex3/EchoBean.class
+- org/jboss/chap8/ex3/EchoHome.class
+- roles.properties
+- users.properties
+- chap8-ex3.sar (archive)
| +- META-INF/MANIFEST.MF
| +- META-INF/jboss-service.xml
| +- META-INF/login-config.xml
| +- org/jboss/chap8/ex3/service/PropertiesVerifierStore$1.class
| +- org/jboss/chap8/ex3/service/PropertiesVerifierStore.class
| +- org/jboss/chap8/ex3/service/PropertiesVerifierStoreMBean.class
| +- org/jboss/chap8/service/SecurityConfig.class
| +- org/jboss/chap8/service/SecurityConfigMBean.class
The key SRP related items in this example are the SRP MBean services
configuration, and the SRP login module configurations. The jboss-
service.xml descriptor of the chap8-ex3.sar is given in Example 8.18, “The chap8-
ex3.sar jboss-service.xml descriptor for the SRP services”, while Example 8.19,
“The client side standard JAAS configuration” and Example 8.20, “The server
side XMLLoginConfig configuration” give the example client side and server
side login module configurations.
Example 8.18. The chap8-ex3.sar jboss-service.xml descriptor for the SRP
services
<server>
<!-- The custom JAAS login configuration that installs
a Configuration capable of dynamically updating the
config settings -->
<mbean code="org.jboss.chap8.service.SecurityConfig"
name="jboss.docs.chap8:service=LoginConfig-EX3">
<attribute name="AuthConfig">META-INF/login-config.xml</attribute>
<attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute>
</mbean>
<!-- The SRP service that provides the SRP RMI server and server side
authentication cache -->
<mbean code="org.jboss.security.srp.SRPService"
name="jboss.docs.chap8:service=SRPService">
421 | P a g e
<attribute name="VerifierSourceJndiName">srp-test/chap8-ex3</attribute>
<attribute name="JndiName">srp-test/SRPServerInterface</attribute>
<attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute>
<attribute name="ServerPort">0</attribute>
<depends>jboss.docs.chap8:service=PropertiesVerifierStore</depends>
</mbean>
<!-- The SRP store handler service that provides the user password verifier
information -->
<mbean code="org.jboss.chap8.ex3.service.PropertiesVerifierStore"
name="jboss.docs.chap8:service=PropertiesVerifierStore">
<attribute name="JndiName">srp-test/chap8-ex3</attribute>
</mbean>
</server>
Example 8.19. The client side standard JAAS configuration
srp {
org.jboss.security.srp.jaas.SRPLoginModule required
srpServerJndiName="srp-test/SRPServerInterface"
;
org.jboss.security.ClientLoginModule required
password-stacking="useFirstPass"
;
};
Example 8.20. The server side XMLLoginConfig configuration
<application-policy name="chap8-ex3">
<authentication>
<login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
flag = "required">
<module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
</authentication>
</application-policy>
The example services are the ServiceConfig and
the PropertiesVerifierStore and SRPService MBeans. Note that the JndiName attribute of
the PropertiesVerifierStore is equal to the VerifierSourceJndiName attribute of
the SRPService, and that the SRPService depends on the PropertiesVerifierStore. This is
required because the SRPService needs an implementation of
422 | P a g e
the SRPVerifierStore interface for accessing user password verification
information.
The client side login module configuration makes use of the SRPLoginModule with
a srpServerJndiName option value that corresponds to the JBoss server
component SRPService JndiName attribute value(srp-test/SRPServerInterface). Also
needed is the ClientLoginModule configured with the password-
stacking="useFirstPass" value to propagate the user authentication credentials
generated by the SRPLoginModule to the EJB invocation layer.
There are two issues to note about the server side login module configuration.
First, note the cacheJndiName=srp-test/AuthenticationCache configuration option tells
the SRPCacheLoginModule the location of the CachePolicy that contains
theSRPServerSession for users who have authenticated against the SRPService. This
value corresponds to the SRPService AuthenticationCacheJndiName attribute value.
Second, the configuration includes a UsersRolesLoginModule with thepassword-
stacking=useFirstPass configuration option. It is required to use a second login
module with the SRPCacheLoginModule because SRP is only an authentication
technology. A second login module needs to be configured that accepts the
authentication credentials validated by the SRPCacheLoginModule to set the
principal's roles that determines the principal's permissions.
The UsersRolesLoginModule is augmenting the SRP authentication with properties
file based authorization. The user's roles are coming the roles.properties file
included in the EJB JAR.
Now, run the example 3 client by executing the following command from the
book examples directory:
[starksm@banshee examples]$ ant -Dchap=chap8 -Dex=3 run-example
Buildfile: build.xml
...
run-example3:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 5 seconds for deploy...
[java] Logging in using the 'srp' configuration
[java] Created Echo
[java] Echo.echo()#1 = This is call 1
[java] Echo.echo()#2 = This is call 2
423 | P a g e
In the examples/logs directory you will find a file called ex3-trace.log. This is a
detailed trace of the client side of the SRP algorithm. The traces show step-by-
step the construction of the public keys, challenges, session key and
verification.
Note that the client has taken a long time to run relative to the other simple
examples. The reason for this is the construction of the client's public key. This
involves the creation of a cryptographically strong random number, and this
process takes quite a bit of time the first time it occurs. If you were to log out
and log in again within the same VM, the process would be much faster. Also
note that Echo.echo()#2 fails with an authentication exception. The client code
sleeps for 15 seconds after making the first call to demonstrate the behavior
of the SRPService cache expiration. The SRPService cache policy timeout has been
set to a mere 10 seconds to force this issue. As stated earlier, you need to
make the cache timeout very long, or handle re-authentication on failure.
8.6. Running JBoss with a Java 2 security manager
By default the JBoss server does not start with a Java 2 security manager. If
you want to restrict privileges of code using Java 2 permissions you need to
configure the JBoss server to run under a security manager. This is done by
configuring the Java VM options in the run.bat or run.sh scripts in the JBoss server
distribution bin directory. The two required VM options are as follows:
 java.security.manager: This is used without any value to specify that
the default security manager should be used. This is the preferred
security manager. You can also pass a value to
the java.security.manager option to specify a custom security manager
implementation. The value must be the fully qualified class name of a
subclass of java.lang.SecurityManager. This form specifies that the policy file
should augment the default security policy as configured by the VM
installation.
 java.security.policy: This is used to specify the policy file that will
augment the default security policy information for the VM. This option
takes two
forms: java.security.policy=policyFileURL and java.security.policy==policyFileURL. The first
form specifies that the policy file should augment the default security
policy as configured by the VM installation. The second form specifies
424 | P a g e
that only the indicated policy file should be used. The policyFileURL value
can be any URL for which a protocol handler exists, or a file path
specification.
Example 8.21, “The modifications to the Win32 run.bat start script to run
JBoss with a Java 2 security manager.” illustrates a fragment of the standard
run.bat start script for Win32 that shows the addition of these two options to
the command line used to start JBoss.
Example 8.21. The modifications to the Win32 run.bat start script to run
JBoss with a Java 2 security manager.
...
set CONFIG=%1
@if "%CONFIG%" == "" set CONFIG=default
set PF=../conf/%CONFIG%/server.policy
set OPTS=-Djava.security.manager
set OPTS=%OPTS% -Djava.security.policy=%PF%
echo JBOSS_CLASSPATH=%JBOSS_CLASSPATH%
java %JAXP% %OPTS% -classpath "%JBOSS_CLASSPATH%" org.jboss.Main %*
Example 8.22, “The modifications to the UNIX/Linux run.sh start script to run
JBoss with a Java 2 security manager.” shows a fragment of the standard
run.sh start script for UNIX/Linux systems that shows the addition of these
two options to the command line used to start JBoss.
Example 8.22. The modifications to the UNIX/Linux run.sh start script to run
JBoss with a Java 2 security manager.
# ...
CONFIG=$1
if [ "$CONFIG" == "" ]; then CONFIG=default; fi
PF=../conf/$CONFIG/server.policy
OPTS=-Djava.security.manager
OPTS="$OPTS -Djava.security.policy=$PF"
echo JBOSS_CLASSPATH=$JBOSS_CLASSPATH
java $HOTSPOT $JAXP $OPTS -classpath $JBOSS_CLASSPATH org.jboss.Main $@
Both start scripts are setting the security policy file to the server.policy file
located in the JBoss configuration file set directory that corresponds to the
configuration name passed as the first argument to the script. This allows one
425 | P a g e
maintain a security policy per configuration file set without having to modify
the start script.
Enabling Java 2 security is the easy part. The difficult part of Java 2 security is
establishing the allowed permissions. If you look at the server.policy file that is
contained in the default configuration file set, you'll see that it contains the
following permission grant statement:
grant {
// Allow everything for now
permission java.security.AllPermission;
};
This effectively disables security permission checking for all code as it says any
code can do anything, which is not a reasonable default. What is a reasonable
set of permissions is entirely up to you.
The current set of JBoss specific java.lang.RuntimePermissions that are required
include:
TargetName What the permission allows Risks
org.jboss.security.SecurityAsso
ciation.getPrincipalInfo
Access to the
org.jboss.security.SecurityAssociatio
n getPrincipal() and getCredentials()
methods.
The ability to see the
current thread caller and
credentials.
org.jboss.security.SecurityAsso
ciation.setPrincipalInfo
Access to the
org.jboss.security.SecurityAssociatio
n setPrincipal() and setCredentials()
methods.
The ability to set the
current thread caller and
credentials.
org.jboss.security.SecurityAsso
ciation.setServer
Access to the
org.jboss.security.SecurityAssociatio
n setServer method.
The ability to enable or
disable multithread
storage of the caller
principal and credential.
org.jboss.security.SecurityAsso
ciation.setRunAsRole
Access to the
org.jboss.security.SecurityAssociatio
n pushRunAsRole and popRunAsRole
The ability to change the
current caller run-as role
426 | P a g e
TargetName What the permission allows Risks
methods. principal.
To conclude this discussion, here is a little-known tidbit on debugging security
policy settings. There are various debugging flag that you can set to determine
how the security manager is using your security policy file as well as what
policy files are contributing permissions. Running the VM as follows shows the
possible debugging flag settings:
[nr@toki bin]$ java -Djava.security.debug=help
all turn on all debugging
access print all checkPermission results
combiner SubjectDomainCombiner debugging
jar jar verification
logincontext login context results
policy loading and granting
provider security provider debugging
scl permissions SecureClassLoader assigns
The following can be used with access:
stack include stack trace
domain dumps all domains in context
failure before throwing exception, dump stack
and domain that didn't have permission
Note: Separate multiple options with a comma
Running with -Djava.security.debug=all provides the most output, but the output
volume is torrential. This might be a good place to start if you don't
understand a given security failure at all. A less verbose setting that helps
debug permission failures is to use -Djava.security.debug=access,failure. This is still
relatively verbose, but not nearly as bad as the all mode as the security
domain information is only displayed on access failures.
8.7. Using SSL with JBoss using JSSE
JBoss uses JSSE the Java Secure Socket Extension (JSSE). JSSE is bundled with
JBoss and it comes with JDK 1.4. For more information on JSSE
see: http://java.sun.com/products/jsse/index.html. A simple test that you can
427 | P a g e
use the JSSE as bundled with JBoss works is to run a program like the
following:
import java.net.*;
import javax.net.ServerSocketFactory;
import javax.net.ssl.*;
public class JSSE_install_check
{
public static void main(String[] args) throws Exception
{
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
ServerSocketFactory factory =
SSLServerSocketFactory.getDefault();
SSLServerSocket sslSocket = (SSLServerSocket)
factory.createServerSocket(12345);
String [] cipherSuites = sslSocket.getEnabledCipherSuites();
for(int i = 0; i < cipherSuites.length; i++) {
System.out.println("Cipher Suite " + i + " = " + cipherSuites[i]);
}
}
}
The book examples includes a testcase for this which can be run using the
following command. This will produce a lot of output as the -
Djavax.net.debug=all option is passed to the VM.
[nr@toki examples]$ ant -Dchap=chap8 -Dex=4a run-example
...
run-example4a:
run-example4a:
[echo] Testing JSSE availablility
[java] keyStore is :
[java] keyStore type is : jks
[java] init keystore
[java] init keymanager of type SunX509
[java] trustStore is: /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home
/lib/security/cacerts
[java] trustStore type is : jks
[java] init truststore
...
[java] init context
[java] trigger seeding of SecureRandom
[java] done seeding SecureRandom
[java] Cipher Suite 0 = SSL_RSA_WITH_RC4_128_MD5
[java] Cipher Suite 1 = SSL_RSA_WITH_RC4_128_SHA
[java] Cipher Suite 2 = TLS_RSA_WITH_AES_128_CBC_SHA
428 | P a g e
[java] Cipher Suite 3 = TLS_DHE_RSA_WITH_AES_128_CBC_SHA
[java] Cipher Suite 4 = TLS_DHE_DSS_WITH_AES_128_CBC_SHA
[java] Cipher Suite 5 = SSL_RSA_WITH_3DES_EDE_CBC_SHA
[java] Cipher Suite 6 = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
[java] Cipher Suite 7 = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
[java] Cipher Suite 8 = SSL_RSA_WITH_DES_CBC_SHA
[java] Cipher Suite 9 = SSL_DHE_RSA_WITH_DES_CBC_SHA
[java] Cipher Suite 10 = SSL_DHE_DSS_WITH_DES_CBC_SHA
[java] Cipher Suite 11 = SSL_RSA_EXPORT_WITH_RC4_40_MD5
[java] Cipher Suite 12 = SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
[java] Cipher Suite 13 = SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
[java] Cipher Suite 14 = SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
The JSSE jars include the jcert.jar, jnet.jar and jsse.jar in the JBOSS_DIST/client directory.
Once you have tested that JSSE runs, you need a public key/private key pair in
the form of an X509 certificate for use by the SSL server sockets. For the
purpose of this example we have created a self-signed certificate using the
JDK keytool and included the resulting keystore file in the chap8 source
directory as chap8.keystore. It was created using the following command and
input:
[nr@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore -v
alidity 3650
[orb@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore -
validity 3650
Enter keystore password: rmi+ssl
What is your first and last name?
[Unknown]: Chapter 8 SSL Example
What is the name of your organizational unit?
[Unknown]: JBoss Book
What is the name of your organization?
[Unknown]: JBoss, Inc.
What is the name of your City or Locality?
[Unknown]: Issaquah
What is the name of your State or Province?
[Unknown]: WA
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=Chapter 8 SSL Example, OU=JBoss Book, O="JBoss, Inc.", L=Issaquah, ST=WA, C=US corre
ct?
[no]: yes
Enter key password for <rmi+ssl>
(RETURN if same as keystore password):
429 | P a g e
This produces a keystore file called chap8.keystore. A keystore is a database of
security keys. There are two different types of entries in a keystore:
 key entries: each entry holds very sensitive cryptographic key
information, which is stored in a protected format to prevent
unauthorized access. Typically, a key stored in this type of entry is a
secret key, or a private key accompanied by the certificate chain for the
corresponding public key. The keytool and jarsigner tools only handle the
later type of entry, that is private keys and their associated certificate
chains.
 trusted certificate entries: each entry contains a single public key
certificate belonging to another party. It is called a trusted certificate
because the keystore owner trusts that the public key in the certificate
indeed belongs to the identity identified by the subject (owner) of the
certificate. The issuer of the certificate vouches for this, by signing the
certificate.
Listing the src/main/org/jboss/chap8/chap8.keystore examples file contents using the
keytool shows one self-signed certificate:
[nr@toki examples]$ keytool -list -v -keystore src/main/org/jboss/chap8/chap8.keystore
Enter keystore password: rmi+ssl
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: rmi+ssl
Creation date: Nov 8, 2001
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C=
US
Issuer: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C
=US
Serial number: 3beb5271
Valid from: Thu Nov 08 21:50:09 CST 2001 until: Sun Nov 06 21:50:09 CST 2011
Certificate fingerprints:
MD5: F6:1B:2B:E9:A5:23:E7:22:B2:18:6F:3F:9F:E7:38:AE
SHA1: F2:20:50:36:97:86:52:89:71:48:A2:C3:06:C8:F9:2D:F7:79:00:36
430 | P a g e
*******************************************
*******************************************
With JSSE working and a keystore with the certificate you will use for the JBoss
server, your are ready to configure JBoss to use SSL for EJB access. This is done
by configuring the EJB invoker RMI socket factories. The JBossSX framework
includes implementations of
the java.rmi.server.RMIServerSocketFactory and java.rmi.server.RMIClientSocketFactory interfaces
that enable the use of RMI over SSL encrypted sockets. The implementation
classes
areorg.jboss.security.ssl.RMISSLServerSocketFactory and org.jboss.security.ssl.RMISSLClientSocketFact
ory respectively. There are two steps to enable the use of SSL for RMI access to
EJBs. The first is to enable the use of a keystore as the database for the SSL
server certificate, which is done by configuring
an org.jboss.security.plugins.JaasSecurityDomain MBean. The jboss-service.xml descriptor in
the chap8/ex4 directory includes the JaasSecurityDomain definition shown
in Example 8.23, “A sample JaasSecurityDomain config for RMI/SSL”.
Example 8.23. A sample JaasSecurityDomain config for RMI/SSL
<!-- The SSL domain setup -->
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
name="jboss.security:service=JaasSecurityDomain,domain=RMI+SSL">
<constructor>
<arg type="java.lang.String" value="RMI+SSL"/>
</constructor>
<attribute name="KeyStoreURL">chap8.keystore</attribute>
<attribute name="KeyStorePass">rmi+ssl</attribute>
</mbean>
The JaasSecurityDomain is a subclass of the standard JaasSecurityManager class that
adds the notions of a keystore as well
JSSE KeyManagerFactory and TrustManagerFactory access. It extends the basic security
manager to allow support for SSL and other cryptographic operations that
require security keys. This configuration simply loads the chap8.keystore from
the example 4 MBean sar using the indicated password.
The second step is to define an EJB invoker configuration that uses the JBossSX
RMI socket factories that support SSL. To do this you need to define a custom
configuration for the JRMPInvoker we saw in Chapter 5, EJBs on JBoss as well as
an EJB setup that makes use of this invoker. The configuration required to
431 | P a g e
enable RMI over SSL access to stateless session bean is provided for you
in Example 8.24, “The jboss-service.xml configurations to enable SSL with the
example 4 stateless session bean.” andExample 8.25, “The jboss.xml
configuration to enable SSL with the example 4 stateless session bean.” The
top of the listing shows the jboss-service.xml descriptor that defines the
custom JRMPInovker, and the bottom shows the example 4 EchoBean4configuration
needed to use the SSL invoker. You will use this configuration in a stateless
session bean example.
Example 8.24. The jboss-service.xml configurations to enable SSL with the
example 4 stateless session bean.
<mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker
name="jboss:service=invoker,type=jrmp,socketType=SSL">
<attribute name="RMIObjectPort">14445</attribute>
<attribute name="RMIClientSocketFactory">
org.jboss.security.ssl.RMISSLClientSocketFactory
</attribute>
<attribute name="RMIServerSocketFactory">
org.jboss.security.ssl.RMISSLServerSocketFactory
</attribute>
<attribute name="SecurityDomain">java:/jaas/RMI+SSL</attribute>
<depends>jboss.security:service=JaasSecurityDomain,domain=RMI+SSL</depends>
</mbean>
Example 8.25. The jboss.xml configuration to enable SSL with the example 4 stateless session
bean.
<?xml version="1.0"?>
<jboss>
<enterprise-beans>
<session>
<ejb-name>EchoBean4</ejb-name>
<configuration-name>Standard Stateless SessionBean</configuration-name>
<home-invoker>jboss:service=invoker,type=jrmp,socketType=SSL</home-invoker>
<bean-invoker>jboss:service=invoker,type=jrmp,socketType=SSL</bean-invoker>
</session>
</enterprise-beans>
</jboss>
The example 4 code is located under the src/main/org/jboss/chap8/ex4 directory of
the book examples. This is another simple stateless session bean with an echo
method that returns its input argument. It is hard to tell when SSL is in use
unless it fails, so we'll run the example 4 client in two different ways to
432 | P a g e
demonstrate that the EJB deployment is in fact using SSL. Start the JBoss
server using the default configuration and then run example 4b as follows:
[nr@toki examples]$ ant -Dchap=chap8 -Dex=4b run-example
...
run-example4b:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 15 seconds for deploy...
[java] Exception in thread "main" java.rmi.ConnectIOException: error during JRMP conn
ection establishment; nested exception is:
[java] javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExcep
tion: No trusted certificate found
[java] at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:274)
...
[java] Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.Validat
orException: No trusted certificate found
[java] at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA12275)
...
[java] Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.Validat
orException: No trusted certificate found
[java] at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA12275)
...
The resulting exception is expected, and is the purpose of the 4b version of
the example. Note that the exception stack trace has been edited to fit into
the book format, so expect some difference. The key item to notice about the
exception is it clearly shows you are using the Sun JSSE classes to
communicate with the JBoss EJB container. The exception is saying that the
self-signed certificate you are using as the JBoss server certificate cannot be
validated as signed by any of the default certificate authorities. This is
expected because the default certificate authority keystore that ships with the
JSSE package only includes well known certificate authorities such as VeriSign,
Thawte, and RSA Data Security. To get the EJB client to accept your self-signed
certificate as valid, you need to tell the JSSE classes to use your chap8.keystore as
its truststore. A truststore is just a keystore that contains public key
certificates used to sign other certificates. To do this, run example 4 using -
Dex=4 rather than -Dex=4b to pass the location of the correct truststore using
the javax.net.ssl.trustStore system property:
[nr@toki examples]$ ant -Dchap=chap8 -Dex=4 run-example
...
run-example4:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 5 seconds for deploy...
433 | P a g e
[java] 0 [HandshakeCompletedNotify-Thread] DEBUG org.jboss.security.ssl.RMISSLClientS
ocketFactory - SSL handshakeCompleted, cipher=SSL_RSA_WITH_RC4_128_MD5, peerHost=127.0.0.
1
[java] Created Echo
[java] Echo.echo()#1 = This is call 1
This time the only indication that an SSL socket is involved is because of the SSL
handshakeCompleted message. This is coming from the RMISSLClientSocketFactory class as
a debug level log message. If you did not have the client configured to print
out log4j debug level messages, there would be no direct indication that SSL
was involved. If you note the run times and the load on your system CPU,
there definitely is a difference. SSL, like SRP, involves the use of
cryptographically strong random numbers that take time to seed the first time
they are used. This shows up as high CPU utilization and start up times.
One consequence of this is that if you are running on a system that is slower
than the one used to run the examples for the book, such as when running
example 4b, you may seen an exception similar to the following:
javax.naming.NameNotFoundException: EchoBean4 not bound
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer
at sun.rmi.transport.StreamRemoteCall.executeCall
at sun.rmi.server.UnicastRef.invoke
at org.jnp.server.NamingServer_Stub.lookup
at org.jnp.interfaces.NamingContext.lookup
at org.jnp.interfaces.NamingContext.lookup
at javax.naming.InitialContext.lookup
at org.jboss.chap8.ex4.ExClient.main(ExClient.java:29)
The problem is that the JBoss server has not finished deploying the example
EJB in the time the client allowed. This is due to the initial setup time of the
secure random number generator used by the SSL server socket. If you see
this issue, simply rerun the example again or increase the deployment wait
time in the chap8 build.xml Ant script.
8.8. Configuring JBoss for use Behind a Firewall
JBoss comes with many socket based services that open listening ports. In this
section we list the services that open ports that might need to be configured
to work when accessing JBoss behind a firewall. The following table shows the
ports, socket type, associated service for the services in the default
configuration file set. Table 8.2, “Additional ports in the all
434 | P a g e
configuration” shows the same information for the additional ports that exist
in the all configuration file set.
Table 8.1. The ports found in the default configuration
Port Type Service
1099 TCP org.jboss.naming.NamingService
1098 TCP org.jboss.naming.NamingService
1162 UDP org.jboss.jmx.adaptor.snmp.trapd.TrapdService
4444 TCP org.jboss.invocation.jrmp.server.JRMPInvoker
4445 TCP org.jboss.invocation.pooled.server.PooledInvoker
8009 TCP org.jboss.web.tomcat.tc4.EmbeddedTomcatService
8080 TCP org.jboss.web.tomcat.tc4.EmbeddedTomcatService
8083 TCP org.jboss.web.WebService
8090 TCP org.jboss.mq.il.oil.OILServerILService
8092 TCP org.jboss.mq.il.oil2.OIL2ServerILService
8093 TCP org.jboss.mq.il.uil2.UILServerILService
0[a]
TCP org.jboss.mq.il.rmi.RMIServerILService
0[b]
UDP org.jboss.jmx.adaptor.snmp.agent.SnmpAgentService
[a] This service binds to an anonymous TCP port and does not support configuration of
the port or bind interface.
[b] This service binds to an anonymous UDP port and does not support configuration of
the port or bind interface.
Table 8.2. Additional ports in the all configuration
435 | P a g e
Port Type Service
1100 TCP org.jboss.ha.jndi.HANamingService
0[a]
TCP org.jboss.ha.jndi.HANamingService
1102 UDP org.jboss.ha.jndi.HANamingService
3528 TCP org.jboss.invocation.iiop.IIOPInvoker
45566[b]
UDP org.jboss.ha.framework.server.ClusterPartition
[a] Currently anonymous but can be set via the RmiPort attribute.
[b] Plus two additional anonymous UDP ports, one can be set using the rcv_port, and the
other cannot be set.
8.9. How to Secure the JBoss Server
JBoss comes with several admin access points that need to be secured or
removed to prevent unauthorized access to admin functions in a deployment.
This section describes the various admin services and how to secure them.
8.9.1. The jmx-console.war
The jmx-console.war found in the deploy directory provides an html view into the
JMX microkernel. As such, it provides access to arbitrary admin type access
like shutting down the server, stopping services, deploying new services, etc. It
should either be secured like any other web application, or removed.
8.9.2. The web-console.war
The web-console.war found in the deploy/management directory is another web
application view into the JMX microkernel. This uses a combination of an
applet and a HTML view and provides the same level of access to admin
functionality as the jmx-console.war. As such, it should either be secured or
removed. The web-console.war contains commented out templates for basic
security in its WEB-INF/web.xml as well as commented out setup for a security
domain in WEB-INF/jboss-web.xml.
436 | P a g e
8.9.3. The http-invoker.sar
The http-invoker.sar found in the deploy directory is a service that provides
RMI/HTTP access for EJBs and the JNDI Naming service. This includes a servlet
that processes posts of marshalled org.jboss.invocation.Invocation objects that
represent invocations that should be dispatched onto the MBeanServer.
Effectively this allows access to MBeans that support the detached invoker
operation via HTTP since one could figure out how to format an approriate
HTTP post. To security this access point you would need to secure
the JMXInvokerServlet servlet found in the http-invoker.sar/invoker.war/WEB-
INF/web.xml descriptor. There is a secure mapping defined for
the /restricted/JMXInvokerServlet path by default, one would simply have to remove
the other paths and configure the http-invoker security domain setup in the http-
invoker.sar/invoker.war/WEB-INF/jboss-web.xml descriptor.
8.9.4. The jmx-invoker-adaptor-server.sar
The jmx-invoker-adaptor-server.sar is a service that exposes the JMX MBeanServer
interface via an RMI compatible interface using the RMI/JRMP detached
invoker service. The only way for this service to be secured currently would be
to switch the protocol to RMI/HTTP and secure the http-invoker.sar as described
in the previous section. In the future this service will be deployed as an
XMBean with a security interceptor that supports role based access checks. If
your so inclined this is a configuration that can setup today following the
proceedure demonstrated in XMBean example: Section 2.4.3.2.3, “Version 3,
Adding Security and Remote Access to the JNDIMap XMBean”.
Secure JMX Console (Authentication Only)
1.1. About the JMX Console
The jmx-console is the default console that is available with the JBoss Application Server. It
displays the various MBean Services that are running in a JBoss Application Server instance. A
user is able to get and set attributes and invoke operations on the various services. For more
information, please refer to the 'JBoss Application Server User or Administrator's Guide'. The
following wiki page has a good description of the JMX Console. http://
wiki.jboss.org/wiki/Wiki.jsp?page=JMXConsole
437 | P a g e
1.2. Simple Security for the JMX Console
If you want to have simple secured jmx console where the user/password and user/roles come
from properties files, then you can follow the following steps:
1. Locate the jmx-console.war directory in the deploy directory of your server
configuration. If you are just using the default configuration, then it will be under
JBOSS_DIR/server/default/deploy directory and you are using the clustered
configuration, then it will be under JBOSS_DIR/server/all/deploy directory.
2. Now edit the web.xml file under jmx-console.war/WEB-INF directory and uncomment
the security constraint block as shown below:
<!-- A security constraint that restricts access to the HTML JMX console
to users with the role JBossAdmin. Edit the roles to what you want and
uncomment the WEB-INF/jboss-web.xml/security-domain element to enable
secured access to the HTML JMX console. -->
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role JBossAdmin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>
3. Edit the jboss-web.xml file also and uncomment the security-domain element as shown
below:
<jboss-web>
JBoss 1.0 1
<!-- Uncomment the security-domain to enable security. You will
need to edit the htmladaptor login configuration to setup the
login modules used to authentication users. -->
<security-domain>java:/jaas/jmx-console</security-domain>
</jboss-web>
2. Now locate the two properties files called as jmx-console-users.properties and jmx-
console-roles.properties that will be in the conf directory of your server configuration
under the props sub-directory('default', 'all' or 'custom'). An example of the location will
be /server/default/conf/props.
3. In the jmx-console-users.properties, you can add/change the user/password
combination.
4. In the jmx-console-roles.properties, you will need to assign roles to the users you added
or changed in step.4.
4. Just remember to add JBossAdmin role to the users who will be using the jmx-console.
438 | P a g e
5. Now when you start JBoss and try to access the jmx-console, you should see a pop up
appear that will ask you to enter the username and password. You can use one of the
users/password combination that you configured in steps 4 and 5.
6. Secure JMX Console (Authentication Only)
Secure JMX Console (Access Control)
2.1. Need for Access Control on the JMX Console
The previous chapter talked about securing the jmx console. The security provided there applied
to the entire console
with no controls on what an user can do with reference to the various JMX operations possible
on the console.
2.2. Details
You will need to follow the following steps to enable access control on the jmx console.
1. Perform all the steps outlined in the earlier chapter to secure the jmx-console.
Edit the web.xml file of deploy/jmx-console.war/WEB-INF in the server configuration you are
using (default,
all, custom etc). You will need to uncomment the filter settings as shown here:
<!-- -->
<filter>
<filter-name>JmxOpsAccessControlFilter</filter-name>
<filter-class>org.jboss.jmx.adaptor.html.JMXOpsAccessControlFilter</filter-class>
<init-param>
<param-name>updateAttributes</param-name>
<param-value>UpdateAttributeRole</param-value>
<description>Comma-delimited Roles that define the JMX Operation denoting updation of Attributes</</init-param>
<init-param>
<param-name>invokeOp</param-name>
<param-value>InvokeOpRole</param-value>
<description>Comma-delimited Roles that define the JMX Operation denoting Invocation of Operations</</init-
param>
</filter>
<filter-mapping>
<filter-name>JmxOpsAccessControlFilter</filter-name>
<servlet-name>HtmlAdaptor</servlet-name>
</filter-mapping>
2. Now if an user is allowed to click the 'invoke' buttons on the various MBean services in the
jmx console
(action will invoke operations), then the user needs to have 'InvokeOpRole'. If the user is
allowed to click the
'Apply Changes' button(action will update the jmx attributes of the service), then the user needs
to have 'updateAttributeRole'.
For this to apply, you will need to update the jmx-console-roles.properties file. An example is
shown below:
# A sample roles.properties file for use with the UsersRolesLoginModule
admin=JBossAdmin,HttpInvoker,UpdateAttributeRole
439 | P a g e
JBoss 1.0 3
admin2=JBossAdmin,HttpInvoker,InvokeOpRole
2.3. Reference
http://wiki.jboss.org/wiki/Wiki.jsp?page=AccessControlForJMXConsole
Secure JMX Console (Access Control)
JBoss 1.0 4
Secure the JMX Invokers (Authentication Only)
3.1. Introduction
The JMX invokers are the entry points to the MBean Server. If there is a need to restrict external
access to the
MBean Server, then there is a need to secure the invokers.
3.2. Enable Authentication for the JMX Invoker
The JMX invoker can be made to authenticate against the JBoss Security JAAS framework like
the web or ejb layers.
3.2.1. Modifications Required
You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server
configuration (eg:
default configuration). Please uncomment the following section.
<operation>
<description>The detached invoker entry point</description>
<name>invoke</name>
<parameter>
<description>The method invocation context</description>
<name>invocation</name>
<type>org.jboss.invocation.Invocation</type>
</parameter>
<return-type>java.lang.Object</return-type>
<!-- Uncomment to require authenticated users -->
<descriptors>
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securityDomain="java:/jaas/jmx-console"/>
</interceptors>
</descriptors>
</operation>
The value of the security domain needs to be defined in the conf/login-config.xml. You can
resuse the security domain
used to restrict access to the jmx-console.
3.2.2. Troubleshooting
When you use JDK5+, you may see the following error:
440 | P a g e
org.jboss.deployment.DeploymentException?: No PropertyDescriptor? for attribute:securityDomain; -
nested throwable: (java.beans.IntrospectionException?: No PropertyDescriptor? for attribute:securityDomain)
JBoss 1.0 5
This is due to a change in how the jmx descriptor names are stored with case preserved. To work
around this isssue
simply use all lower case attribute names.
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securitydomain="java:/jaas/jmx-console"/>
</interceptors>
Secure the JMX Invokers (Authentication Only)
JBoss 1.0 6
Secure the JMX Invokers (Authorization/Access Control)
4.1. Introduction
In the last chapter, you enabled authentication on the JMX invoker. This would basically restrict
access to just the
actors that have identified themselves. There may need for fine-grained access control on the
JMX invoker. You
may want to restrict access to users who have certain roles.
4.2. Enable Access Control or Authorization for the JMX Invoker
The JMX invoker can be made to authorize all requests.
4.2.1. Modifications Required (Use Case 1)
You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server
configuration (eg:
default configuration). Please add an additional interceptor to look as follows:
<operation>
<description>The detached invoker entry point</description>
<name>invoke</name>
<parameter>
<description>The method invocation context</description>
<name>invocation</name>
<type>org.jboss.invocation.Invocation</type>
</parameter>
<return-type>java.lang.Object</return-type>
<!-- Uncomment to require authenticated users -->
<descriptors>
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securityDomain="java:/jaas/jmx-console"/>
<interceptor code="org.jboss.jmx.connector.invoker.AuthorizationInterceptor"
authorizingClass="org.jboss.jmx.connector.invoker.RolesAuthorization"/>
</interceptors>
</descriptors>
</operation>
441 | P a g e
The AuthorizationInterceptor will use the JAAS authenticated subject that has been created by
the Authentication-
Interceptor and will allow access to users who have a role called as "JBossAdmin".
4.2.2. Modifications Required (Use Case 2)
JBoss 1.0 7
You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server
configuration (eg:
default configuration). Please add an additional interceptor to look as follows:
<operation>
<description>The detached invoker entry point</description>
<name>invoke</name>
<parameter>
<description>The method invocation context</description>
<name>invocation</name>
<type>org.jboss.invocation.Invocation</type>
</parameter>
<return-type>java.lang.Object</return-type>
<!-- Uncomment to require authenticated users -->
<descriptors>
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securityDomain="java:/jaas/jmx-console"/>
<interceptor code="org.jboss.jmx.connector.invoker.AuthorizationInterceptor"
authorizingClass="org.jboss.jmx.connector.invoker.ExternalizableRolesAuthorization"/>
</interceptors>
</descriptors>
</operation>
This use case handles cases where you can configure the various roles that an user can have to
gain access. The
previous use case just handled the case when the users had a role called as "JBossAdmin".
In this case, you will need to provide a properties file called as "jmx-invoker-roles.properties" in
a jar file or place
442 | P a g e
Integrate security infrastructures with JBossSX
JBossSX uses JAAS to integrate application servers and security infrastructures
Summary
The current Enterprise JavaBean and Servlet specifications omit integration between the application
server and existing security infrastructures. This article describes how version 3.2.x of the open source
JBoss application server security extension project (JBossSX) uses Java Authentication and Authorization
Service (JAAS) login modules as its integration API. JAAS allows for integration without programming,
using security infrastructures that use Java Database Connectivity, the lightweight directory access
protocol (LDAP), or properties-based login modules bundled with JBoss. For security infrastructures that
do not support those access mechanisms, integration entails writing a simple custom login module.
key aspect of the Java 2 Platform, Enterprise Edition (J2EE) component models is a simple
declarative security model. The Enterprise JavaBean (EJB) 2.0 and Servlet 2.3 specifications support a
role-based declarative security model that externalizes security from application logic and decouples the
application security roles from the deployment environment's security implementation. At the application
level, the ejb-jar.xml and web.xml deployment descriptors define security. Although this model allows for
an independent, simple specification of the application server's security requirements, mapping the
application-defined security onto the deployment environment security's infrastructure is an application-
server-specific activity.
Thus, configuring a J2EE application's security requires proprietary application server APIs or tools. One
such tool is the Java Authentication and Authorization Service (JAAS). In this article, I describe how the
JBoss security extension, JBossSX, uses the standard JAAS to integrate with the deployment environment's
security infrastructure. By configuring the JAAS login modules bundled with JBoss, you can complete the
integration without custom programming. If the bundled login modules don't work with your security
infrastructure, you can simply write a custom login module that does; I'll show you how in this article.
The key topics that I cover here include:
 The J2EE declarative security model
 The key JAAS classes
 Details of how the JBossSX security manager uses JAAS in its implementation of the J2EE
declarative security model
 Details of how you can write a custom JAAS login module for JBoss
I also include a secure enterprise application example that demonstrates the declarative security model
and the configuration of JAAS login modules to integrate the deployment environment's security.
443 | P a g e
J2EE declarative security overview
The first step to securing a J2EE application is to specify the application security requirements via the
standard J2EE deployment descriptors. You secure access to EJBs and Web components in an enterprise
application by using the ejb-jar.xml and web.xml deployment descriptors. Figures 1 and 2 illustrate the
security-related elements in the EJB 2.0 and Servlet 2.2 deployment descriptors, respectively.
444 | P a g e
Figure 1. The EJB 2.0 deployment descriptor security elements
Together, these security elements define the bean author and application assembler's view of an
enterprise application's security requirements.
445 | P a g e
Figure 2. The Servlet 2.2 deployment descriptor security elements
So that you'll have sufficient background for the example presented later in this article, I'll first review the
security elements pictured in Figures 1 and 2.
Enterprise beans security references
As you can see in Figure 1, enterprise beans may declare one or more security-role-ref elements. An EJB
can access the caller principal and ask if the caller belongs to a role by name. The caller principal is
obtained from theEJBContext.getCallerPrincipal() method as a java.security.Principal instance. Using
the EJBContext.isCallerInRole(String) method, an EJB checks if a caller is in a role that has been declared
with a security-role-ref element. The role-name element value must link to a security role in the
assembly-descriptor section of ejb-jar.xml through the role-link element. You typically
use isCallerInRole() to perform a security check that cannot be defined using method permissions. See
section 21.2.5 of the EJB 2.0 Specification for more details on accessing the caller's security context.
446 | P a g e
Enterprise beans security identity
Figure 1 also shows that enterprise beans can optionally declare a security-identity element. New to EJB
2.0 is the ability to specify what identity an EJB should use when it invokes methods on other EJBs. The
application assembler uses the security-identity element to indicate that the current caller's identity
should be propagated by using a use-caller-identity element as security-identity's value. Alternatively, the
application assembler can use the run-as element with thesecurity-identity's value as role-name to specify
that EJB calls are performed with the security role given by the role-name value. Note that this does not
change the caller's identity as seen by EJBContext.getCallerPrincipal(). Rather, the caller's security roles
are set to the single role specified by the run-as/role-name element value. You can use a run-as identity to
keep external clients from accessing internal EJBs. To do that, assign the internal EJB method permissions
that restrict access to a role never assigned to an external client, and use the restricted role as the run-
as/role-name element value for EJBs that use the internal EJB.
Assembly descriptor security roles
The security role referenced by either security-role-ref or security-identity elements needs to map to one
of the application's declared roles. An application assembler defines logical security roles by
adding security-role elements to theassembly-descriptor element. In JBoss, a security-role is only used to
map an EJB security-role-ref/role-name to the logical role to which the EJB role name refers. The user's
assigned roles are a dynamic function of the application's security manager, as you will see when I discuss
the JBossSX implementation. JBoss does not require defined security-roles to identify method
permissions. Therefore, you should specify a security-role element for every role used in the method-
permission element for portability across application servers and for deployment descriptor maintenance.
Assembly descriptor method permissions
An application assembler can set the roles that are allowed to invoke an EJB's home and component
interface methods through method-permission elements. Each method-permission element contains one
or more role-name elements that define the logical roles allowed access to one or more EJB methods as
identified by method elements. With EJB 2.0, you can now specify the unchecked element instead of
the role-name element to declare that an authenticated user can access one or more methods. In
addition, you can declare that no one should have access to a method with the exclude-list element. For
method syntax, see section 21.3.2 of the EJB 2.0 Specification.
An example EJB deployment descriptor
The following ejb-jar.xml descriptor illustrates the use of EJB security elements and is the descriptor used
in the article example:
<ejb-jar>
<display-name>SecurityTests</display-name>
<enterprise-beans>
<session>
<description>A trivial stateless session echo bean</description>
<ejb-name>PublicSession</ejb-name>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
447 | P a g e
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-class>org.jboss.docs.jaas.howto.StatelessSessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<ejb-ref-name>ejb/PrivateSession</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-link>PrivateSession</ejb-link>
</ejb-ref>
<security-identity>
<run-as>
<role-name>InternalUser</role-name>
</run-as>
</security-identity>
</session>
<session>
<description>A trivial stateful session echo bean</description>
<ejb-name>PrivateSession</ejb-name>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-class>org.jboss.docs.jaas.howto.StatefulSessionBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<security-role>
<role-name>Coder</role-name>
</security-role>
<security-role>
<role-name>Echo</role-name>
</security-role>
<security-role>
<role-name>InternalUser</role-name>
</security-role>
<method-permission>
<role-name>Echo</role-name>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<role-name>InternalUser</role-name>
<method>
448 | P a g e
<ejb-name>PrivateSession</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<role-name>Coder</role-name>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>create</method-name>
</method>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>remove</method-name>
</method>
</method-permission>
<method-permission>
<unchecked/>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>noop</method-name>
</method>
</method-permission>
<exclude-list>
<description>Methods that cannot be used in this
deployment</description>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>restricted</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>
Web application security constraints
In a Web application, security is defined by the roles allowed access to content; a URL pattern identifies
the protected content. For example, the web.xml descriptor fragment below indicates that any URL lying
under the Web application's/restricted path requires an AuthorizedUser role:
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Content</web-resource-name>
<url-pattern>/restricted/*</ url-pattern></
<web-resource-collection>
<auth-constraint>
449 | P a g e
<role-name>AuthorizedUser</role-name>
</auth-constraint>
</security-constraint>
...
<security-role>
<description>The role required to access restricted content</description>
<role-name>AuthorizedUser</role-name>
</security-role>
</web-app>
The security-role-ref and security-role elements are equivalent to their EJB counterparts.
Specify the security domain in JBoss
The J2EE security elements I have covered describe only the security requirements from the application's
perspective. Since J2EE security elements declare logical roles, the application deployer maps the roles
from the application domain onto the deployment environment. The EJB specification omits these
application-server-specific details. In JBoss, mapping the application roles onto the deployment
environment entails specifying a security manager that implements the J2EE security model. Figure 3
shows the JBoss-specific EJB and Web application deployment descriptor's security-related elements.
450 | P a g e
Figure 3. The JBoss-specific EJB and Web deployment descriptor security elements
Use the security-domain element to identify the Java Naming and Directory Interface (JNDI) name of the
security manager interface implementation that JBoss uses for the EJB and Web containers. You may
specify security-domain as an EJB-level element to only set security for one or more EJBs when security-
domain is not a top-level element, or when security-domain is a top-level element and you want to
451 | P a g e
override it. The security-proxy element identifies a custom security interceptor that allows per-request
security checks outside the scope of the EJB declarative security model without embedding security logic
into the EJB implementation. I won't go into detail about that JBoss-specific feature, as this article focuses
on using JAAS to implement the standard declarative security model.
A JBoss security manager implementation requires
the org.jboss.security.EJBSecurityManager and org.jboss.security.RealmMapping interfaces presented in
Figure 4.
Figure 4. JBoss security manager interfaces
For the remainder of this article, I focus on the JBossSX org.jboss.security.plugins.JaasSecurityManager, a
JAAS-based implementation of the security manager interfaces. But first, I'll present a brief introduction
to JAAS.
452 | P a g e
What is JAAS?
The JAAS 1.0 API consists of a set of Java packages for the user authentication and authorization. It
implements a Java version of the standard Pluggable Authentication Module (PAM) framework and
compatibly extends the Java 2 Platform's access control architecture to support user-based authorization.
JAAS was first released as an extension package for JDK 1.3 and is bundled with the current JDK 1.4 beta.
As the JBossSX framework only uses the authentication aspect of JAAS to implement the declarative-role-
based J2EE security model, this introduction focuses only on that topic. For a more comprehensive
overview, see the JAAS material in Resources. I took much of this section's material from the JAAS 1.0
Developers Guide.
JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain
independent from underlying authentication technologies and allows the JBossSX security manager to
work in different security infrastructures. Integration with a security infrastructure can succeed without
changing the JBossSX security manager. Authentication consists of instantiating a LoginContext object,
which passes the name of a Configuration entry to determine which LoginModule will be created.
The LoginModules define the authentication technology. LoginModules often use a username and
password to verify identity, but any form of identity and identity verification will work.
The JAAS Core Classes
The JAAS core classes break down into three categories: common, authentication, and authorization. The
list below presents the common and authentication classes, since the JBossSX functionality covered in this
article uses only these classes.
 Common classes:
o Subject (javax.security.auth.Subject)
o Principal (java.security.Principal)
 Authentication classes:
o Callback (javax.security.auth.callback.Callback)
o CallbackHandler (javax.security.auth.callback.CallbackHandler)
o Configuration (javax.security.auth.login.Configuration)
o LoginContext (javax.security.auth.login.LoginContext)
o LoginModule (javax.security.auth.spi.LoginModule)
Subject and Principal
To authorize access to resources, applications first need to authenticate the request's source. The JAAS
framework defines the term Subject to represent the request's source. Subject is the key JAAS class; it
represents information for a single entity, such as a person or service. It encompasses the entity's
principals, public credentials, and private credentials. The JAAS APIs use the existing Java
2 java.security.Principal interface to represent a principal.
453 | P a g e
Once authenticated, a Subject is populated with associated identities, or Principals. A Subject may have
many Principals. For example, a person may have a name Principal (John Doe) and a social security
number Principal (123-45-6789), both of which help distinguish it from other Subjects. To retrieve
the Principals associated with a Subject, two methods are available:
public Set getPrincipals();
public Set getPrincipals(Class c);
The first method returns all Principals contained in the Subject. The second method only returns
those Principals that are instances of Class c or Class c's subclasses. An empty set will return if
the Subject has no associated Principals. Note that the java.security.acl.Group interface is a subinterface
of java.security.Principal, and so an instance in the Principals set may represent a logical grouping of other
principals or groups of principals.
Authentication classes
The following steps will authenticate a Subject:
1. An application instantiates a LoginContext.
2. The LoginContext consults a Configuration to load all the LoginModules configured for that
application.
3. The application invokes the LoginContext's login method.
4. The login method invokes all the loaded LoginModules. Each LoginModule attempts to
authenticate the Subject. Upon success, LoginModules associate relevant Principals and
credentials with the Subject.
5. The LoginContext returns the authentication status to the application.
6. If authentication succeeds, the application retrieves the authenticated Subject from
the LoginContext.
The LoginContext class provides the basic methods for authenticating Subjects and offers a way to
develop an application independent of the underlying authentication technology.
The LoginContext consults a Configuration to determine the authentication services -- or LoginModules --
configured for a particular application. Therefore, you can plug in different LoginModules under an
application without changing the application itself.
All LoginContext constructors share a common parameter: name. The LoginContext uses name to index
the login Configuration. Actual authentication occurs with a call to the following method:
public void login() throws LoginException;
When login() invokes, all the configured LoginModules' respective login methods invoke to perform
authentication. If authentication succeeds, the following method can retrieve the
authenticated Subject (which may now hold Principals, public credentials, and private credentials):
454 | P a g e
public Subject getSubject();
To log out a Subject and remove its authenticated Principals and credentials, use the method below:
public void logout() throws LoginException;
The following code sample demonstrates the calls necessary to authenticate a Subject using
the LoginModules configured under the name jwdomain:
// let the LoginContext instantiate a new Subject
LoginContext lc = new LoginContext("jwdomain");
try
{
// authenticate the Subject
lc.login();
System.out.println("authentication successful");
// get the authenticated Subject
Subject subject = lc.getSubject();
...
// all finished -- logout
lc.logout();
}
catch (LoginException le)
{
System.out.println("authentication unsuccessful");
le.printStackTrace();
}
With the LoginModule interface, developers can implement different authentication technologies that
can be plugged under an application. For example, one LoginModule may perform username/password-
based authentication, while others may interface to hardware devices such as smart card readers or
biometric authenticators. To instantiate a LoginModule, a LoginContext expects each LoginModule to
provide a public constructor that takes no arguments. Then, to initialize aLoginModule with the relevant
information, a LoginContext calls the LoginModule's initialize() method. The subject argument is
guaranteed to be nonnull. The signature of the initialize() method is:
void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options);
The login() method starts authentication; its signature is:
455 | P a g e
boolean login() throws LoginException;
An example method implementation might prompt the user for a username and password, and then
verify the information against data stored in a naming service such as NIS or LDAP. Alternative
implementations might interface to smart cards and biometric devices or simply extract user information
from the underlying operating system. The validation of user identity by each LoginModule is considered
Phase 1 of JAAS authentication. Authentication completes when theLoginContext calls:
boolean commit() throws LoginException;
If Phase 1 succeeds, then the commit() method continues with Phase 2: associating relevant Principals,
public credentials, or private credentials with the Subject. If Phase 1 fails, then boolean commit() throws
LoginException; removes any previously stored authentication state, such as usernames or passwords.
The following method halts authentication:
boolean abort() throws LoginException;
Typical implementations of that method also clean up previously stored authentication state.
The following method logs out a Subject:
boolean logout() throws LoginException;
That method removes the Principals and credentials originally associated with the Subject during the
commit operation. Credentials should be destroyed upon removal.
When a LoginModule must communicate with the user to obtain authentication information, it uses
a CallbackHandler. Applications implement the CallbackHandler interface and pass it to the LoginContext,
which forwards it directly to the underlying LoginModules. LoginModules use the CallbackHandler both to
gather input from users (such as a password or smart-card PIN number) and to supply information to
users (such as status information). By allowing the application to specify the CallbackHandler,
underlying LoginModules remain independent from the different ways applications interact with users.
For example, a CallbackHandler's implementation for a GUI application might display a window to solicit
user input. On the other hand, a CallbackHandler's implementation for a non-GUI environment, such as an
application server, might simply obtain credential information using an application server API.
The CallbackHandler interface has one method to implement:
void handle(Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException;
456 | P a g e
The last authentication class I will cover is the Callback interface. It is a tagging interface that features
several implementations, including NameCallback and PasswordCallback. LoginModules use a Callback to
request information required by the authentication mechanism the LoginModule encapsulates.
LoginModules pass an array of Callbacks directly to the CallbackHandler's handle method during the
authentication's login phase.
Inside the JBossSX JaasSecurityManager
Now let's return to the JBossSX security manager implementation. I'll start with an overview of how the
JBoss security components interact. Figure 5 shows the main components and how the security domain
assigned in the JBoss EJB and Web deployment descriptors ties them together.
457 | P a g e
Figure 5. Security component interaction overview
Figure 5 depicts an enterprise application that contains both EJBs and Web content secured under the
security domain jwdomain. The EJB and Web containers have a request interceptor architecture that
includes a security interceptor, which enforces the container security model. At deployment time, the
security domain in the jboss.xml and jboss-web.xml descriptors is used to obtain the security manager
instance associated with the container and used by the security interceptor. When a secured component
is requested, the security interceptor delegates security checks to the security manager instance
associated with the container.
458 | P a g e
For the JBossSX default security manager implementation, shown in Figure 5 as
the JaasSecurityMgr component, security checks are based on the information associated with
the javax.security.auth.Subject instance. That instance results from executing the JAAS login modules
configured under the name matching the security-domain element value. We will drill into
the JaasSecurityManager implementation and its use of JAAS in the following sections.
The JAAS in JaasSecurityManager
The default JBossSX security manager
implementation org.jboss.security.plugins.JaasSecurityManager uses the JAAS packages to implement its
behavior. In particular, its behavior derives from the login module (javax.security.auth.spi.LoginModule)
whose configuration entry name matches the security domain to which the JaasSecurityManager has
been assigned. The login module implements the security domain's principal authentication and role-
mapping behavior. Hence, you can use the JaasSecurityManager across different security domains simply
by plugging in different login module configurations for the domains.
The security check
Consider a client that invokes a method on an EJB configured to use a JaasSecurityManager instance for
security. Figure 6 illustrates some components involved in the security check; the security check's key
steps are outlined below the figure.
459 | P a g e
Figure 6. EJB access authentication procedure
1. The client first has to perform a JAAS login to establish the principal and credentials for
authentication, which is how clients establish their login identities in JBoss. Support for
presenting the login information via the JNDIInitialContext properties is not provided. A JAAS
login entails creating a javax.security.auth.login.LoginContext instance and passing the
configuration's name to use. In Figure 6, the configuration name is other. This one-time login
associates the login principal and credentials with all subsequent EJB method invocations. Note
that the process might not authenticate the user. The nature of the client-side login depends on
the login module configuration that the client uses. In Figure 6, the other client-side login
configuration entry is set up to use
the ClientLoginModule (org.jboss.security.ClientLoginModule); that module does not perform
client-side authentication, but simply binds the username and password to the JBoss EJB
invocation layer for later authentication on the server.
2. Later, the client obtains an EJB's home interface and attempts to create a bean, resulting in a
home interface method invocation sent to the JBoss server. The invocation includes the method
arguments passed by the client along with the user identity and credentials from the client-side
JAAS login.
3. On the server side, the security check first requires authentication of the user invoking the call,
which, as on the client side, involves a JAAS login. The security domain under which the EJB is
secured determines the choice of login modules. The security domain's name is used as the login
configuration entry name passed to the LoginContext constructor. In Figure 6, the EJB security
460 | P a g e
domain is jwdomain. If the JAAS login authenticates the user, a JAAS Subject is created that
contains the following in its PrincipalsSet:
o A java.security.Principal that corresponds to the client identity.
o A java.security.acl.Group named Roles that contains the role names from the application
domain to which the user has been assigned. org.jboss.security.SimplePrincipal objects
are used to represent the role names; SimplePrincipalis a simple string-based
implementation of Principal. These roles are used to validate the roles assigned to
methods in ejb-jar.xml and the EJBContext.isCallerInRole(String) method.
o An optional java.security.acl.Group named CallerPrincipal, which contains a
single org.jboss.security.SimplePrincipal that corresponds to the identity of the
application domain's caller. The CallerPrincipal sole group member is the value returned
by the EJBContext.getCallerPrincipal() method. The purpose of this mapping is to allow
a Principal known in the deployment security environment to map to a Principal with a
name known to the application. In the absence of a CallerPrincipal mapping the
deployment security environment, Principal returns.
4. The final step of the security check is to verify the authenticated user has permission to invoke
the requested method. Doing this requires the following steps:
1. Obtain the names of the roles allowed to access the EJB method from the EJB container.
The names are ejb-jar.xml descriptor role-name elements of all method-
permission elements containing the invoked method.
2. If no roles have been assigned, then access to the method is denied. Otherwise,
the JaasSecurityManager.doesUserHaveRole(Principal, Set) method invokes to see if the
caller principal has one of the assigned role names. The method iterates through the
role names and checks if the user javax.security.auth.Subject's Roles group contains
a SimplePrincipal with the assigned role name. Access is allowed if any role name is a
member of the Roles group; access is denied if none of the role names are members.
3. If the EJB was configured with a custom security proxy, the method invocation is
delegated to it. If the security proxy wants to deny access to the caller, it will throw
a SecurityException. If no SecurityException is thrown, access to the EJB method is
allowed; the SecurityInterceptor passes the method invocation to the next container
interceptor.
Note that you can configure the JaasSecurityManager to use a cache of authentication information so that
a JAAS login is not performed on every method invocation. If no cache is specified in
the JaasSecurityManager's configuration, a timed cache is used by default.
JBossSX custom login modules
As shown above, the JBossSX security manager relies on the JAAS login modules for a security domain for
authentication and authorization. The security manager authorizes users with the information stored in
the Subject. If theLoginModules that ship with the JBoss server do not integrate into your existing security
infrastructure, you can write a custom LoginModule that does. Writing a custom login module entails
mapping your security infrastructure information onto a javax.security.auth.Subject using the usage
pattern expected by JBossSX.
461 | P a g e
JBossSX Subject usage patterns
The JBossSX security manager inside the JBoss application server executes the login modules used by a
security domain. Since these modules run inside the JBoss server, they are called server-side login
modules. When you write a custom LoginModule, you write a server-side login module. To understand
how server-side login modules are used in JBoss, you need to understand the JAAS Subject class's
information storage features. You can obtain security information associated with a Subject in six ways:
 java.util.Set getPrincipals()
 java.util.Set getPrincipals(java.lang.Class c)
 java.util.Set getPrivateCredentials()
 java.util.Set getPrivateCredentials(java.lang.Class c)
 java.util.Set getPublicCredentials()
 java.util.Set getPublicCredentials(java.lang.Class c)
For Subject identities and roles, JBossSX has selected the most natural choice: the PrincipalsSet obtained
via getPrincipals() and getPrincipals(java.lang.Class). The usage pattern follows:
User identities (username, social security number, employee ID, and so on) are stored
as java.security.Principal objects in the Subject Principals set. The assigned user roles are also stored in
the Principals set, but in named role sets usingjava.security.acl.Group instances. The Group interface -- a
collection of Principals and/or Groups -- is a subinterface of java.security.Principal. Any number of role
sets can be assigned to a Subject. Currently, the JBossSX framework uses two well-known role
sets: Roles and CallerPrincipal. The Roles set is the Principal set for the named roles as known in the
application domain under which the Subject has been authenticated. This role set is used by methods like
theEJBContext.isCallerInRole(String), which EJBs use to see if the current caller belongs to the named
application domain role. The security interceptor logic that performs method permission checks also uses
the role set. The CallerPrincipal role set consists of the single Principal identity assigned to the user in the
application domain. The EJBContext.getCallerPrincipal() method uses CallerPrincipal to allow the
application domain to map from the operation environment identity to a user identity suitable for the
application. If a Subject does not have a CallerPrincipal role set, the application identity is the operational
environment identity.
Support for the Subject usage pattern
To simplify correct implementation of the Subject usage patterns described in the preceding section,
JBossSX includes an abstract login module that handles the population of the authenticated Subject with a
template pattern. Theorg.jboss.security.auth.spi.AbstractLoginModule class provides concrete
implementations of the javax.security.auth.spi.LoginModule interface and offers abstract methods for the
key tasks specific to an operation environment security infrastructure. The key details of the class are:
package org.jboss.security.auth.spi;
/** This class implements the common functionality required for a JAAS
server-side LoginModule and implements the JBossSX standard Subject usage
pattern of storing identities and roles. Subclass this module to create your
own custom LoginModule and override the login(), getRoleSets(), and getIdentity()
462 | P a g e
methods.
*/
public abstract class AbstractServerLoginModule
implements javax.security.auth.spi.LoginModule
{
protected Subject subject;
protected CallbackHandler callbackHandler;
protected Map sharedState;
protected Map options;
...
/** Initialize the login module. This stores the subject, callbackHandler
and sharedState, and options for the login session. Subclasses should override
if they need to process their own options. A call to super.initialize(...)
must be made in the case of an override.
@param subject, the Subject to update after a successful login.
@param callbackHandler, the CallbackHandler that will be used to obtain the
the user identity and credentials.
@param sharedState, a Map shared between all configured login module instances
@param options,
@option password-stacking: if true, the login identity will be taken from the
javax.security.auth.login.name value of the sharedState map, and
the proof of identity from the javax.security.auth.login.password
value of the sharedState map.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options)
{
...
}
/** Looks for javax.security.auth.login.name and javax.security.auth.login.password
values in the sharedState map if the useFirstPass option was true and returns
true if they exist. If they do not or are null, this method returns false.
Subclasses should override to perform the required credential validation steps.
*/
public boolean login() throws LoginException
{
...
}
/** Overridden by subclasses to return the Principal that corresponds to
the user primary identity.
*/
abstract protected Principal getIdentity();
/** Overridden by subclasses to return the Groups that correspond
to the role sets assigned to the user. Subclasses should create at
least a Group named "Roles" that contains the roles assigned to the user.
A second common group is "CallerPrincipal," which provides the application
identity of the user rather than the security domain identity.
463 | P a g e
@return Group[] containing the sets of roles
*/
abstract protected Group[] getRoleSets() throws LoginException;
}
As an alternate base login module, the UsernamePasswordLoginModule further simplifies custom login
module implementation by using the string-based username as the user identity and the char[] password
as the authentication credential. It also maps anonymous users (indicated by a null username and
password) to a Principal. You would typically support anonymous users by setting
the Principal that EJBContext.getCallerPrincipal() returns when an unsecure servlet or JavaServer Page
(JSP) calls an EJB. The key methods of UsernamePasswordLoginModule are:
package org.jboss.security.auth.spi;
/** An abstract subclass of AbstractServerLoginModule that imposes a
an identity == String username, credentials == String password view on
the login process. Subclasses override the getUsersPassword()
and getUsersRoles() methods to return the expected password and roles
for the user.
*/
public abstract class UsernamePasswordLoginModule
extends AbstractServerLoginModule
{
/** The login identity */
private Principal identity;
/** The proof of login identity */
private char[] credential;
/** The principal to use when a null username and password are seen */
private Principal unauthenticatedIdentity;
...
/** Override the superclass method to look for an unauthenticatedIdentity
property. This method first invokes the super version.
@param options,
@option unauthenticatedIdentity: the name of the principal to assign
and authenticate when a null username and password are seen.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options)
{
super.initialize(subject, callbackHandler, sharedState, options);
// Check for unauthenticatedIdentity option.
String name = (String) options.get("unauthenticatedIdentity");
if( name != null )
unauthenticatedIdentity = new SimplePrincipal(name);
}
464 | P a g e
...
/** A hook that allows subclasses to change the validation of the input
password against the expected password. This version checks that
neither inputPassword or expectedPassword are null and that
inputPassword.equals(expectedPassword) is true;
@return true if the inputPassword is valid, false otherwise.
*/
protected boolean validatePassword(String inputPassword, String expectedPassword)
{
if( inputPassword == null || expectedPassword == null )
return false;
return inputPassword.equals(expectedPassword);
}
/** Get the expected password for the current username available via
the getUsername() method. This is called from within the login()
method after the CallbackHandler has returned the username and
candidate password.
@return the valid password String
*/
abstract protected String getUsersPassword() throws LoginException;
}
Write a custom login module
When writing a custom login module that integrates with your security infrastructure, you should start by
subclassing org.jboss.security.auth.spi.AbstractLoginModule or one of its subclasses to ensure that your
login module provides the authenticated Principal information in the form expected by the JBossSX
security manager. When subclassing the AbstractLoginModule, you need to override:
 void initialize(Subject, CallbackHandler, Map, Map) if you have custom options to parse.
 boolean login() to perform the authentication activity.
 Principal getIdentity() to return the Principal object for the user authenticated by the log() step.
 Group[] getRoleSets() to return at least a Group named Roles that contains the roles assigned to
the Principal authenticated during login(). A second common group is CallerPrincipal; it provides,
if necessary, the user's application identity rather than the security domain identity.
When subclassing the UsernamePasswordLoginModule, a subclass of AbstractLoginModule, write:
 void initialize(Subject, CallbackHandler, Map, Map) if you have custom options to parse.
 String getUsersPassword() to return the expected password for the current username available
via the getUsername() method. The getUsersPassword() method is called from
within login() after the CallbackHandler returns the username and candidate password.
 Group[] getRoleSets() to return at least a Group named Roles that contains the roles assigned to
the Principal authenticated during login(). A second group CallerPrincipal provides, if necessary,
the user's application identity instead of the security domain identity.
465 | P a g e
An example
Want to see the security features in action? The source code for the example is included in the article
archive in the jw-0831-jaas/example directory and I'll walk you through it. You will set up and deploy the
example to a JBoss/Tomcat 3.2.1 bundle. You'll also look at the application from the secure and
unsecured servlet accessing a secured EJB to demonstrate many of the security features presented in this
article. To deploy the example application:
 You need the Ant build tool. If you don't already have it, see the Ant homepage. I am using 1.5.4.
 Next, download the JBoss/Tomcat 3.2.3 bundle from SourceForge and unarchive it. At the time of
this writing, the current JBoss/Tomcat bundle is jboss-3.2.3.zip and it unarchives to create
a jboss-3.2.3 directory.
 The examples are located in the jw-0831-jaas/example subdirectory of this archive.
 Edit the jboss.dist property that specifies the JBoss/Tomcat bundle location in the build.xml file,
or override the property on the command line to Ant by creating an ant.properties file in the
examples root directory. The default location is /tmp/jboss-3.2.3, so if you unarchive the
JBoss/Tomcat bundle in your /tmp directory, you're ready to go.
 Build and deploy the example ears by running Ant within the example directory. Your output
should look something like this:
[starksm@dedicated74 example]$ ant
Buildfile: build.xml
validate:
fail_if_not_valid:
init:
[echo] Using jboss.dist=/tmp/jboss-3.2.3
[echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss-
3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes
compile:
[mkdir] Created dir: /tmp/jaashowto/example/output/classes
[javac] Compiling 7 source files to /tmp/jaashowto/example/output/classes
jar1:
[mkdir] Created dir: /tmp/jaashowto/example/output/META-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[jar] Building jar: /tmp/jaashowto/example/output/ssbean1.jar
war1:
[mkdir] Created dir: /tmp/jaashowto/example/output/web/WEB-
INF/classes/org/jboss/docs/jaas/howto
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-
466 | P a g e
INF/classes/org/jboss/docs/jaas/howto
[jar] Building jar: /tmp/jaashowto/example/output/tutorial1.war
ear1:
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[jar] Building jar: /tmp/jaashowto/example/output/tutorial1.ear
jar2:
[delete] Deleting directory /tmp/jaashowto/example/output/META-INF
[mkdir] Created dir: /tmp/jaashowto/example/output/META-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[jar] Building jar: /tmp/jaashowto/example/output/ssbean2.jar
war2:
[delete] Deleting directory /tmp/jaashowto/example/output/web
[mkdir] Created dir: /tmp/jaashowto/example/output/web/WEB-
INF/classes/org/jboss/docs/jaas/howto
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF
[copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-
INF/classes/org/jboss/docs/jaas/howto
[jar] Building jar: /tmp/jaashowto/example/output/tutorial2.war
ear2:
[copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF
[jar] Building jar: /tmp/jaashowto/example/output/tutorial2.ear
ears:
[mkdir] Created dir: /tmp/jboss-3.2.3/server/jaas_howto
[copy] Copying 130 files to /tmp/jboss-3.2.3/server/jaas_howto
[copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/conf
[copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/deploy
[copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/deploy
BUILD SUCCESSFUL
Total time: 4 secondsTotal time: 2 seconds
 If you see something similar to this:
[starksm@banshee example]$ ant
Buildfile: build.xml
validate:
fail_if_not_valid:
BUILD FAILED
467 | P a g e
file:/tmp/jaashowto/example/build.xml:28: jboss.dist=/tmp/jboss-3.2.3 is not a valid JBoss dist
directory
you need to correct the jboss.dist property's value in the Ant build.xml file in the example
directory as indicated in the previous step.
<>Now start the JBoss server with the jaas_howto configuration, which contains the JAAS login
configuration file and was created by the Ant build process. To start JBoss, go to the jboss-
3.2.3/bin directory and execute the run.sh orrun.bat script as appropriate for your operating
system, passing in the jaas_howto config name. Here's an example from a Linux system with key
output emphasized: <>
[starksm@dedicated74 bin]$ ./run.sh -c jaas_howto
===============================================================================
=
JBoss Bootstrap Environment
JBOSS_HOME: /tmp/jboss-3.2.3
JAVA: /usr/java/j2sdk1.4.2_04/bin/java
JAVA_OPTS: -server -Dprogram.name=run.sh
CLASSPATH: /tmp/jboss-3.2.3/bin/run.jar:/usr/java/j2sdk1.4.2_04/lib/tools.jar
===============================================================================
=
23:19:41,847 INFO [Server] Starting JBoss (MX MicroKernel)...
23:19:41,849 INFO [Server] Release ID: JBoss [WonderLand] 3.2.3 (build: CVSTag=JBoss_3_2_3
date=200311301445)
23:19:41,850 INFO [Server] Home Dir: /tmp/jboss-3.2.3
23:19:41,850 INFO [Server] Home URL: file:/tmp/jboss-3.2.3/
23:19:41,850 INFO [Server] Library URL: file:/tmp/jboss-3.2.3/lib/
23:19:41,851 INFO [Server] Patch URL: null
23:19:41,852 INFO [Server] Server Name: jaas_howto
23:19:41,852 INFO [Server] Server Home Dir: /tmp/jboss-3.2.3/server/jaas_howto
23:19:41,852 INFO [Server] Server Home URL: file:/tmp/jboss-3.2.3/server/jaas_howto/
23:19:41,853 INFO [Server] Server Data Dir: /tmp/jboss-3.2.3/server/jaas_howto/data
23:19:41,853 INFO [Server] Server Temp Dir: /tmp/jboss-3.2.3/server/jaas_howto/tmp
23:19:41,854 INFO [Server] Server Config URL: file:/tmp/jboss-3.2.3/server/jaas_howto/conf/
23:19:41,854 INFO [Server] Server Library URL: file:/tmp/jboss-3.2.3/server/jaas_howto/lib/
23:19:41,854 INFO [Server] Root Deployment Filename: jboss-service.xml
468 | P a g e
23:19:41,860 INFO [Server] Starting General Purpose Architecture (GPA)...
23:19:42,276 INFO [ServerInfo] Java version: 1.4.2_04,Sun Microsystems Inc.
23:19:42,276 INFO [ServerInfo] Java VM: Java HotSpot(TM) Server VM 1.4.2_04-b05,Sun
Microsystems Inc.
23:19:42,276 INFO [ServerInfo] OS-System: Linux 2.4.20-9smp,i386
23:19:42,323 INFO [ServiceController] Controller MBean online
23:19:42,417 INFO [MainDeployer] Started jboss.system:service=MainDeployer
...
23:20:00,702 INFO [MainDeployer] Starting deployment of package: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial1.ear
23:20:00,704 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial1.ear
23:20:01,478 INFO [EjbModule] Deploying PublicSession
23:20:01,579 INFO [JaasSecurityManagerService] Created
securityMgr=org.jboss.security.plugins.JaasSecurityManager@490342
23:20:01,580 INFO [JaasSecurityManagerService] setCachePolicy,
c=org.jboss.util.TimedCachePolicy@1751a9e
23:20:01,581 INFO [JaasSecurityManagerService] Added example1,
org.jboss.security.plugins.SecurityDomainContext@126ba64 to map
23:20:01,688 INFO [EjbModule] Deploying PrivateSession
23:20:01,934 INFO [StatelessSessionInstancePool] Started
jboss.j2ee:jndiName=example1/PublicSession,plugin=pool,service=EJB
23:20:01,935 INFO [StatelessSessionContainer] Started
jboss.j2ee:jndiName=example1/PublicSession,service=EJB
23:20:01,945 INFO [StatefulSessionInstancePool] Started
jboss.j2ee:jndiName=example1/PrivateSession,plugin=pool,service=EJB
23:20:01,945 INFO [StatefulSessionFilePersistenceManager] Started null
23:20:01,945 INFO [StatefulSessionContainer] Started
jboss.j2ee:jndiName=example1/PrivateSession,service=EJB
23:20:01,946 INFO [EjbModule] Started jboss.j2ee:module=ssbean1.jar,service=EjbModule
23:20:01,946 INFO [EJBDeployer] Deployed: file:/tmp/jboss-
3.2.3/server/jaas_howto/tmp/deploy/tmp29859tutorial1.ear-contents/ssbean1.jar
23:20:02,144 INFO [EmbeddedTomcatService] deploy, ctxPath=/jaas-example1,
warUrl=file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29859tutorial1.ear-
contents/tutorial1.war/
23:20:02,475 INFO [Engine] SingleSignOnContextConfig[/jaas-example1]: Added certificates ->
request attribute Valve
23:20:02,476 INFO [Engine] SingleSignOnContextConfig[/jaas-example1]: Configured an
authenticator for method BASIC
23:20:02,502 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on class
loader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@a937cd
23:20:02,502 INFO [Engine] StandardManager[/jaas-example1]: Seeding random number
generator class java.security.SecureRandom
469 | P a g e
23:20:02,503 INFO [Engine] StandardManager[/jaas-example1]: Seeding of random number
generator has been completed
23:20:02,504 INFO [Engine] StandardWrapper[/jaas-example1:default]: Loading container
servlet default
23:20:02,505 INFO [Engine] StandardWrapper[/jaas-example1:invoker]: Loading container
servlet invoker
23:20:03,020 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial1.ear
23:20:03,020 INFO [MainDeployer] Deployed package: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial1.ear
23:20:03,021 INFO [MainDeployer] Starting deployment of package: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial2.ear
23:20:03,022 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial2.ear
23:20:03,387 INFO [EjbModule] Deploying PublicSession
23:20:03,408 INFO [JaasSecurityManagerService] Created
securityMgr=org.jboss.security.plugins.JaasSecurityManager@a6d35
23:20:03,409 INFO [JaasSecurityManagerService] setCachePolicy,
c=org.jboss.util.TimedCachePolicy@87d472
23:20:03,409 INFO [JaasSecurityManagerService] Added example2,
org.jboss.security.plugins.SecurityDomainContext@18ca663 to map
23:20:03,413 INFO [EjbModule] Deploying PrivateSession
23:20:03,449 INFO [StatelessSessionInstancePool] Started
jboss.j2ee:jndiName=example2/PublicSession,plugin=pool,service=EJB
23:20:03,449 INFO [StatelessSessionContainer] Started
jboss.j2ee:jndiName=example2/PublicSession,service=EJB
23:20:03,461 INFO [StatefulSessionInstancePool] Started
jboss.j2ee:jndiName=example2/PrivateSession,plugin=pool,service=EJB
23:20:03,462 INFO [StatefulSessionFilePersistenceManager] Started null
23:20:03,462 INFO [StatefulSessionContainer] Started
jboss.j2ee:jndiName=example2/PrivateSession,service=EJB
23:20:03,462 INFO [EjbModule] Started jboss.j2ee:module=ssbean2.jar,service=EjbModule
23:20:03,463 INFO [EJBDeployer] Deployed: file:/tmp/jboss-
3.2.3/server/jaas_howto/tmp/deploy/tmp29860tutorial2.ear-contents/ssbean2.jar
23:20:03,614 INFO [EmbeddedTomcatService] deploy, ctxPath=/jaas-example2,
warUrl=file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29860tutorial2.ear-
contents/tutorial2.war/
23:20:04,011 INFO [Engine] SingleSignOnContextConfig[/jaas-example2]: Added certificates ->
request attribute Valve
23:20:04,011 INFO [Engine] SingleSignOnContextConfig[/jaas-example2]: Configured an
authenticator for method BASIC
23:20:04,034 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on class
loader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@2264da
23:20:04,034 INFO [Engine] StandardManager[/jaas-example2]: Seeding random number
470 | P a g e
generator class java.security.SecureRandom
23:20:04,035 INFO [Engine] StandardManager[/jaas-example2]: Seeding of random number
generator has been completed
23:20:04,037 INFO [Engine] StandardWrapper[/jaas-example2:default]: Loading container
servlet default
23:20:04,038 INFO [Engine] StandardWrapper[/jaas-example2:invoker]: Loading container
servlet invoker
23:20:04,520 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial2.ear
23:20:04,521 INFO [MainDeployer] Deployed package: file:/tmp/jboss-
3.2.3/server/jaas_howto/deploy/tutorial2.ear
...
23:20:04,805 INFO [Server] JBoss (MX MicroKernel) [3.2.3 (build: CVSTag=JBoss_3_2_3
date=200311301445)] Started in 22s:945ms

The tutorial1.ear contents
tutorial1.ear consists of a single Webpage, a secured servlet, an unsecured servlet, and two secured
stateless session beans. As the servlet and session bean code is trivial, I'll leave its inspection as an
exercise for you. The interesting aspect of the example is the deployment descriptors' security-related
elements and the configuration of the JAAS login module associated with the security
domain. tutorial1.ear's contents are shown below with the security-related filesemphasized:
tutorial1.ear
+ META-INF
|-- MANIFEST.MF
|-- application.xml
+ ssbean1.jar
|-- + META-INF
|----- ejb-jar.xml
|----- jboss.xml
|-- + org/jboss/docs/jaas/howto
|----- Session.class
|----- SessionHome.class
|----- PrivateSessionBean.class
|----- PublicSessionBean.class
|-- roles.properties
|-- users.properties
+ tutorial1.war
|-- + WEB-INF
|----- web.xml
|----- jboss-web.xml
|----+ classes/org/jboss/docs/jaas/howto
471 | P a g e
|------ EJBServlet.class
|-- index.html
We'll look at each file in turn.
The tutorial1.ear/ssbean1.jar/META-INF/ejb-jar.xml descriptor
The following ejb-jar.xml deployment descriptor declares the tutorial EJBs and their security
requirements:
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE ejb-jar
PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<display-name>SecurityTests</display-name>
<enterprise-beans>
<session>
<description>A trivial stateless session echo bean</description>
<ejb-name>PublicSession</ejb-name>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-class>org.jboss.docs.jaas.howto.PublicSessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<ejb-ref-name>ejb/PrivateSession</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-link>PrivateSession</ejb-link>
</ejb-ref>
<security-role-ref>
<role-name>EchoUser</role-name>
<role-link>Echo</role-link>
</security-role-ref>
<security-identity>
<run-as>
<role-name>InternalUser</role-name>
</run-as>
</security-identity>
</session>
<session>
<description>A trivial stateful session echo bean</description>
<ejb-name>PrivateSession</ejb-name>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
472 | P a g e
<remote>org.jboss.docs.jaas.howto.Session</remote>
<ejb-class>org.jboss.docs.jaas.howto.PrivateSessionBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
<security-role-ref>
<role-name>InternalUser</role-name>
<role-link>InternalUser</role-link>
</security-role-ref>
</session>
</enterprise-beans>
<assembly-descriptor>
<security-role>
<role-name>Coder</role-name>
</security-role>
<security-role>
<role-name>Echo</role-name>
</security-role>
<security-role>
<role-name>InternalUser</role-name>
</security-role>
<method-permission>
<role-name>Echo</role-name>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<role-name>InternalUser</role-name>
<method>
<ejb-name>PrivateSession</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<role-name>Coder</role-name>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>create</method-name>
</method>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>remove</method-name>
</method>
</method-permission>
<method-permission>
<unchecked/>
<method>
473 | P a g e
<ejb-name>PublicSession</ejb-name>
<method-name>noop</method-name>
</method>
</method-permission>
<exclude-list>
<description>Methods that cannot be used in this
deployment</description>
<method>
<ejb-name>PublicSession</ejb-name>
<method-name>restricted</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>
Items of note include:
 The security-role-ref element is where the PublicSession bean declares an EchoUser role name,
which links to the Echo role name. That element indicates that the PublicSession bean queries
the EJBContext.isCallerInRole with a EchoUser role name string.
 The security-identity/run-as/role-name InternalUser declaration indicates that a principal with a
role named InternalUser handles any EJB calls made by the PublicSession bean.
 The PrivateSession bean declares an InternalUser role name to indicate that the bean queries
the EJBContext.isCallerInRole with an InternalUser role name string.
 In the assembly-descriptor section, logical roles of Echo, Coder, and InternalUser are declared
using security-role elements.
 The Echo role receives permission to access any method in the PublicSession bean in the
first method-permission element.
 The InternalUser role receives permission to access any PrivateSession bean method in the
second method-permission element.
 The fourth method-permission element indicates that any authenticated user can call
the PublicSession noop method with the unchecked element instead of a role-name element.
 The exclude-list element declares that no one can call the PublicSession restricted method.
The tutorial1.ear/ssbean1.jar/META-INF/jboss.xml descriptor
The code below is the JBoss-server-specific EJB deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<jboss>
<!-- All bean containers use this security manager by default -->
<security-domain>java:/jaas/example1</security-domain>
<enterprise-beans>
<session>
<ejb-name>PublicSession</ejb-name>
<jndi-name>example1/PublicSession</jndi-name>
474 | P a g e
</session>
<session>
<ejb-name>PrivateSession</ejb-name>
<jndi-name>example1/PrivateSession</jndi-name>
</session>
</enterprise-beans>
</jboss>
This descriptor indicates that the security manager located at the JNDI name java:/jaas/example1 secures
all EJBs in the ssbean1.jar. The JNDI name's final component (example1) determines which login modules
are associated with the security domain.
The tutorial1.ear/ssbean1.jar/roles.properties, users.properties files
The org.jboss.security.auth.spi.UsersRolesLoginModule custom JAAS login module shipped with the
JBossSX framework uses the roles.properties and users.properties files. This simple login module uses Java
properties format files for mapping usernames to passwords and usernames to roles names.
The roles.properties file maps a username to one or more role names using the
format username[.RoleGroup]=role1_name[,role2_name,...]. A RoleGroup names the Group that will be
created to hold given roles. With no specified RoleGroup, it defaults to Roles. Here's
the roles.properties file for the example:
# roles.properties
java=Echo
duke=Java,Coder
java.CallerPrincipal=caller_java
duke.CallerPrincipal=caller_duke
The code above maps the username java to the role name Echo under the Roles RoleGroup, and the role
name caller_java under the CallerPrincipal RoleGroup. The users.properties file maps a username to a
user password. Here's theusers.properties file for the example:
# users.properties
java=echoman
duke=javaman
The above code maps the username java to the password echoman.
The tutorial1.ear/tutorial1.war/WEB-INF/web.xml descriptor
The following web.xml deployment descriptor declares the tutorial servlets and their EJB references and
security requirements:
475 | P a g e
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<!-- ### Filters -->
<filter>
<filter-name>JaasLoginFilter</filter-name>
<description>A filter that does a JAAS login to establish the
identity to use for subsequent ejb calls.
</description>
<filter-class>org.jboss.docs.jaas.howto.JaasLoginFilter</filter-class>
<init-param>
<param-name>configName</param-name>
<param-value>client-login</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>java</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>echoman</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>JaasLoginFilter</filter-name>
<url-pattern>/UnsecureServletWithLogin/*</url-pattern>
</filter-mapping>
<!-- ### Servlets -->
<servlet>
<servlet-name>SecureServlet</servlet-name>
<servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UnsecureServlet</servlet-name>
<servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class>
<run-as>
<description>The anoymous user role</description>
<role-name>nobody</role-name>
</run-as>
</servlet>
<servlet>
<servlet-name>UnsecureServletWithLogin</servlet-name>
<description>A servlet whose mapping does not exist under the /restricted
context that </description>
476 | P a g e
<servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SecureServlet</servlet-name>
<url-pattern>/restricted/SecureServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UnsecureServlet</servlet-name>
<url-pattern>/UnsecureServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UnsecureServletWithLogin</servlet-name>
<url-pattern>/UnsecureServletWithLogin</url-pattern>
</servlet-mapping>
<!-- ### Security -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted</web-resource-name>
<description>Declarative security tests</description>
<url-pattern>/restricted/*</url-pattern>
<http-method>HEAD</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Echo</role-name>
</auth-constraint>
<user-data-constraint>
<description>no description</description>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>JAAS Tutorial Servlets</realm-name>
</login-config>
<security-role>
<description>A user allowed to invoke echo methods</description>
<role-name>Echo</role-name>
</security-role>
<security-role>
<description>A user with no permissions</description>
<role-name>nobody</role-name>
</security-role>
477 | P a g e
<!-- ### EJB References (java:comp/env/ejb) -->
<ejb-ref>
<ejb-ref-name>ejb/SecuredEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
</ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/PrivateEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>org.jboss.docs.jaas.howto.SessionHome</home>
<remote>org.jboss.docs.jaas.howto.Session</remote>
</ejb-ref>
</web-app>
The security items of note include:
 The security-constraint/web-resource-collection/url-pattern element declaration indicates that
all content under /restricted must be secured for the indicated HTTP methods.
 The auth-constraint/role-name element indicates that only users with an Echo role can access
the content under /restricted.
 The login-config/auth-method element with the BASIC value indicates that BASIC
HTTP authorization will authenticate users attempting to access content under /restricted.
 The SecureServlet requires authenticated access, since its servlet-mapping/url-pattern element is
under the /restricted path.
 The JaasLoginFilter servlet filter does a JAAS login to establish the caller identity given the the
filter's username/passowrd init-param values using the JAAS login module configuration named
by the configName init-param.
The tutorial1.ear/tutorial1.war/WEB-INF/jboss-web.xml descriptor
Here is the JBoss-server-specific Web application deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>java:/jaas/example1</security-domain>
<ejb-ref>
<ejb-ref-name>ejb/SecuredEJB</ejb-ref-name>
<jndi-name>example1/PublicSession</jndi-name>
</ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/PrivateEJB</ejb-ref-name>
<jndi-name>example1/PrivateSession</jndi-name>
</ejb-ref>
</jboss-web>
478 | P a g e
This code indicates that the security manager located at the JNDI name java:/jaas/example1 handles
security for all secured Web content. Since the security-domain element matches that used by
the jboss.xml deployment descriptor, the same security manager secures the ear EJBs and Web content.
The jboss-3.2.3/server/jaas_howto/conf/login-config.xml login configuration file
The final security-related file is outside of tutorial1.ear. The login-config.xml file in the JBoss server
configuration directory is the JAAS login configuration file. That file consists of named login configuration
entries. Here's the version oflogin-config.xml that we will use for the tutorial:
<!-- The JBoss server side JAAS login config file for the examples -->
<policy>
<!-- Used by clients within the application server VM such as
mbeans and servlets that access EJBs.
-->
<application-policy name = "client-login">
<authentication>
<login-module code = "org.jboss.security.ClientLoginModule"
flag = "required">
</login-module>
</authentication>
</application-policy>
<application-policy name = "example1">
<authentication>
<!-- A properties file LoginModule that supports CallerPrincipal mapping
-->
<login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
</login-module>
</authentication>
</application-policy>
<application-policy name = "example2">
<authentication>
<!-- A JDBC based LoginModule
LoginModule options:
dsJndiName: The name of the DataSource of the database containing the Principals, Roles tables
principalsQuery: The prepared statement query equivalent to:
"select Password from Principals where PrincipalID=?"
rolesQuery: The prepared statement query equivalent to:
"select Role, RoleGroup from Roles where PrincipalID=?"
-->
<login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule"
flag = "required">
<module-option name = "dsJndiName">java:/DefaultDS</module-option>
<module-option name = "principalsQuery">select Password from Principals where
479 | P a g e
PrincipalID=?</module-option>
<module-option name = "rolesQuery">select Role, RoleGroup from Roles where
PrincipalID=?</module-option>
</login-module>
</authentication>
</application-policy>
<!-- The security domain for the HSQLDB -->
<application-policy name = "HsqlDbRealm">
<authentication>
<login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule"
flag = "required">
<module-option name = "principal">sa</module-option>
<module-option name = "userName">sa</module-option>
<module-option name = "password"></module-option>
<module-option name =
"managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
In the example file above, there are three entries, example1, example2 and HsqlDbRealm.
The example1 entry contains a single login module whose class name
is org.jboss.security.auth.spi.UsersRolesLoginModule, which is required for successful
authentication. The UsersRolesLoginModule login module uses the users.properties and
roles.properties files included in the ear as discussed earlier. The example2 entry contains a
single login module whose class name isorg.jboss.security.auth.spi.DatabaseServerLoginModule.
The DatabaseServerLoginModule configuration includes three login module options:
 dsJndiName: gives the JNDI name of the javax.sql.DataSource binding for the database
to use
 principalsQuery: the sql query used to obtain the principal, password value
 rolesQuery: the sql query used to obtain the princpal to role, role group name mapping.
The role group name for the declarative roles must be 'Roles'.
The HsqlDbRealm configuration defines how access to database connections are authorized.
This configuration specifies that a fixed username and password are used by the JCA connection
pools.
Test the tutorial1.ear deployment from Web Client
The example's final step is to test that the security constraints do in fact work. If your browser runs on the
same host as the JBoss server, launch your Web browser and open the Web application index.html file
located athttp://localhost:8080/jaas-example1/index.html. Figure 7 shows what the Webpage should look
480 | P a g e
like. Each link is a test case, with the expected result shown as [PASS] or [FAIL] based on the specified
security. We'll walk through links 1 and 4 to verify both a passing and failing test.
Figure 7. The tutorial1.ear index.html page
The first link corresponds to the call sequence illustrated in Figure 8. Each access or method invocation
lists the role that the caller must possess for the access to be granted.
481 | P a g e
Figure 8. The tutorial1.ear index.html page
Traverse Link 1 to invoke the SecureServlet and enter java for the username and echoman as the
password in the login dialog. Figure 9 shows the browser result.
Figure 9. The expected browser result
The JBoss server console should display the following output:
16:09:15,431 INFO [Engine] Authenticator[/jaas-example1]: Security checking request GET /jaas-
example1/restricted/SecureServlet
16:09:15,441 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint
[Restricted]' against GET /restricted/SecureServlet --> true
16:09:15,461 INFO [Engine] Authenticator[/jaas-example1]: Subject to constraint SecurityConstraint
[Restricted]
16:09:15,481 INFO [Engine] Authenticator[/jaas-example1]: Calling checkUserData()
16:09:15,491 INFO [Engine] Authenticator[/jaas-example1]: User data constraint has no restrictions
482 | P a g e
16:09:15,511 INFO [Engine] Authenticator[/jaas-example1]: Calling authenticate()
16:09:15,711 INFO [Engine] Authenticator[/jaas-example1]: Failed authenticate() test
16:09:20,108 INFO [Engine] Authenticator[/jaas-example1]: Security checking request GET /jaas-
example1/restricted/SecureServlet
16:09:20,128 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint
[Restricted]' against GET /restricted/SecureServlet --> true
16:09:20,148 INFO [Engine] Authenticator[/jaas-example1]: Subject to constraint SecurityConstraint
[Restricted]
16:09:20,168 INFO [Engine] Authenticator[/jaas-example1]: Calling checkUserData()
16:09:20,178 INFO [Engine] Authenticator[/jaas-example1]: User data constraint has no restrictions
16:09:20,188 INFO [Engine] Authenticator[/jaas-example1]: Calling authenticate()
16:09:20,228 INFO [Engine] Authenticator[/jaas-example1]: Authenticated 'java' with type 'BASIC'
16:09:20,238 INFO [Engine] Authenticator[/jaas-example1]: Calling accessControl()
16:09:20,258 INFO [Engine] Authenticator[/jaas-example1]: Successfully passed all security constraints
16:09:20,268 INFO [Engine] StandardContext[/jaas-example1]: Mapping contextPath='/jaas-example1' wi
th requestURI='/jaas-example1/restricted/SecureServlet' and relativeURI='/restricted/SecureServlet'
16:09:20,288 INFO [Engine] StandardContext[/jaas-example1]: Trying exact match
16:09:20,298 INFO [Engine] StandardContext[/jaas-example1]: Mapped to servlet 'SecureServlet' with
servlet path '/restricted/SecureServlet' and path info 'null' and update=true
16:09:20,398 INFO [STDOUT] PublicSessionBean.ejbCreate() called
16:09:20,408 INFO [STDOUT] PublicSessionBean.echo, arg=Hello
16:09:20,418 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java
16:09:20,428 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true
16:09:20,438 INFO [STDOUT] PrivateSessionBean.ejbCreate() called
16:09:20,448 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession
16:09:20,458 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello
16:09:20,468 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java
16:09:20,478 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false
The first Failed authenticate() test. line results because Tomcat tried to determine whether the servlet
request had a remote user associated with it. That caused a query to the security manager with a null
username and password, because the browser was not asked to provide any login information. The null
username and password is rejected and this results in a 401 error which causes the browser to display the
basic auth login dialog. The following Authenticated 'java' with type 'BASIC' line is the result of the HTTP
BASIC authorization login.
Note that PrivateSessionBean.echo() method's check to see if the caller has the InternalUser role returns
false. This seemingly incorrect result is in accord with our interpretation of the EJB 2.0 spec, which states
on page 439:
Note that isCallerInRole(String roleName) tests the principal that represents the caller of the enterprise
bean, not the principal that corresponds to the run-as security identity for the bean, if any.
Now follow Link 4 to try to access the PrivateSession bean's echo method from the SecureServlet. That
should fail, since only the PublicSession has been configured to run as the InternalUser role. You should
see a 500 error and a root cause exception with the message:
java.lang.SecurityException: Insufficient method permissions, principal=java, method=create,
483 | P a g e
interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo]
at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:214)
This message verifies that the method-permission element, which required a InternalUser role, is
enforced.
The links under the 'JBoss Unsecured Servlet with JAAS Login filter to EJB Tests' heading are to the
UnsecureServletWithLogin mapping of the EJBServlet. These mappings use the JaasLoginFilter to perform
a JAAS login at that start of the request using a username of java and a password of echoman, and a
logout when the request completes.
Test the tutorial1.ear deployment from Java Client
There are three Ant targets for running test of a Java client accessing the session EJB:
1. example1-test0 this tests access with a valid username and password with a user who can access
the PublicSession bean.
2. example1-test1 this tests access with a valid username and password with a user who does not
have the correct roles to access the PublicSession bean.
3. example1-test2 this tests access with an invalid password.
All testcases run the org.jboss.docs.jaas.howto.SessionClient which does a JAAS login, and then creates a
PublicSession instance and invokes the echo method on it. Next the SessionClient attempts to create an
instance of the PrivateSession and asserts that this fails. The core code is shown here:
try
{
AppCallbackHandler handler = new AppCallbackHandler(name, password);
LoginContext lc = new LoginContext("TestClient", handler);
System.out.println("Created LoginContext");
lc.login();
}
catch (LoginException le)
{
System.out.println("Login failed");
le.printStackTrace();
}
try
{
InitialContext iniContext = new InitialContext();
SessionHome home = (SessionHome) iniContext.lookup(example + "/PublicSession");
System.out.println("Found PublicSession home");
Session bean = home.create();
System.out.println("Created PublicSession");
System.out.println("Bean.echo('Hello') -> " + bean.echo("Hello"));
484 | P a g e
bean.remove();
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
InitialContext iniContext = new InitialContext();
SessionHome home = (SessionHome) iniContext.lookup(example + "/PrivateSession");
System.out.println("Found PrivateSession home");
Session bean = home.create();
throw new IllegalStateException("Was able to create PrivateSession");
}
catch (Exception e)
{
System.out.println("Failed to create PrivateSession as expected");
}
example1-test0
The test example1-test0 accesses the PublicSession bean with a valid username and password
with a user with the correct permissions. The expected client side output is shown here:
[starksm@dedicated74 example]$ ant example1-test0
Buildfile: build.xml
example1-test0:
validate:
fail_if_not_valid:
init:
[echo] Using jboss.dist=/tmp/jboss-3.2.3
[echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss-
3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes
compile:
client-test0:
[java] +++ Running SessionClient with username=java, password=echoman,
485 | P a g e
example=example1
[java] Created LoginContext
[java] Found PublicSession home
[java] Created PublicSession
[java] Bean.echo('Hello') -> Hello
[java] Found PrivateSession home
[java] Failed to create PrivateSession as expected
BUILD SUCCESSFUL
The corresponding server side console output is:
07:41:47,762 INFO [STDOUT] PublicSessionBean.echo, arg=Hello
23:23:09,120 INFO [STDOUT] PublicSessionBean.ejbCreate() called
23:23:09,123 INFO [STDOUT] PublicSessionBean.echo, arg=Hello
23:23:09,124 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java
23:23:09,125 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true
23:23:09,131 INFO [STDOUT] PrivateSessionBean.ejbCreate() called
23:23:09,134 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession
23:23:09,143 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello
23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java
23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false
23:23:09,171 ERROR [SecurityInterceptor] Insufficient method permissions, principal=java,
method=create, interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo]
23:23:09,175 ERROR [LogInterceptor] EJBException, causedBy:
java.lang.SecurityException: Insufficient method permissions, principal=java, method=create,
interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo]
at
org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:229)
at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:81)
at
org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invokeHome(CachedConn
ectionInterceptor.java:214)
at
org.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invokeHome(StatefulSessionInstanceInt
erceptor.java:126)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:88)
at
org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98)
486 | P a g e
at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120)
at
org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderIntercepto
r.java:93)
at
org.jboss.ejb.StatefulSessionContainer.internalInvokeHome(StatefulSessionContainer.java:404)
at org.jboss.ejb.Container.invoke(Container.java:720)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at
org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546)
at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:367)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261)
at sun.rmi.transport.Transport$1.run(Transport.java:148)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:144)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
at java.lang.Thread.run(Thread.java:534)
Exploring
I encourage you to try the additional test cases in the tutorial1.ear example and investigate the
second example, tutorial2.ear, which was created and deployed during the examples build. The
tutorial2.ear example differs from tutorial1.ear only in its choice of security domain name and
thus login module configuration. tutorial2.ear uses a Java Database Connectivity-based login
module to demonstrate how to access security information from a database. The entry point for
the tutorial2 web application ishttp://localhost:8080/jaas-example2/index.html.
Note 1: Before you can use the tutorial2 web application successfully you must create the
password and roles database. To do this, run the buildDB ant target with JBoss running the
jaas_howto configuration. The JBoss server must NOT be running because the HSQLDB
487 | P a g e
embedded database bundled with JBoss is configured to use a file only mode and the file would
be locked if JBoss was running. Running the buildDB target should result in:
[starksm@banshee example]$ ant buildDB
Buildfile: build.xml
validate:
fail_if_not_valid:
init:
[echo] Using jboss.dist=/tmp/jboss-3.2.3
[echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss-
3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes
compile:
buildDB:
[sql] Executing commands
[sql] 11 of 11 SQL statements executed successfully
BUILD SUCCESSFUL
Secure your J2EE apps
Although the mapping of application security roles onto a application server deployment
environment is currently a nonportable, application-server-specific task, this article has
demonstrated how the standard JAAS security could be used to implement the J2EE declarative
security model using a simple Subject-based usage pattern. Hopefully, future versions of J2EE will
extend the portability of security closer to the deployment layer using similar techniques based
on JAAS or equivalent standards-based APIs. This article has peered into the JBossSX security
manager implementation of the J2EE declarative security model used by the JBoss EJB and Web
containers. It focused on how the JAAS login modules configured for a security domain provide
the security information via a Subject usage pattern. I also covered the steps required to create a
custom login module for security infrastructures not supported by bundled JBossSX login
modules. With this information, you can secure your enterprise applications either by
configuring the login modules bundled with JBoss or by writing your own.
488 | P a g e
Resources
 The EJB 2.0 Specification provides the guidelines that any EJB 2.0-compliant application server
must follow:
http://java.sun.com/products/ejb/docs.html
 You will find a complete listing of the Java Authentication and Authorization Service (JAAS)
documents at the JAAS homepage:
http://java.sun.com/products/jaas/index-10.html
 Java Authentication and Authorization Service (JAAS) 1.0 Developer's Guide:
http://java.sun.com/security/jaas/doc/api.html
 "PAM: Making Login Services Independent of Authentication Technologies," Vipin Samar and
Charlie Lai (Java.sun.com):
http://java.sun.com/security/jaas/doc/pam.html
 You will find details of the JBossSX architecture in this online documentation:
http://www.jboss.org/index.html?module=html&op=userdisplay&id=docs/index
 Ant is a Java-based build tool used by many open source Java projects:
http://jakarta.apache.org/ant/index.html
 "Automate Your Build Process Using Java and Ant," Michael Cymerman (JavaWorld, October
2000):
http://www.javaworld.com/javaworld/jw-10-2000/jw-1020-ant.html
 "Benefit from Platform-Independent Builds," Sanjay Mahapatra (JavaWorld, August 2000):
http://www.javaworld.com/javaworld/jw-08-2000/jw-0804-builds.html
 The JBoss project code is housed at Sourceforge. You can obtain JBoss releases from the Files
section of the project page:
http://sourceforge.net/projects/jboss
 For more articles on Java Security, browse our Topical Index:
http://www.javaworld.com/channel_content/jw-security-index.shtml
 To read more about Enterprise JavaBeans, browse our Topical Index:
http://www.javaworld.com/channel_content/jw-ejbs-index.shtml
 Sign up for the JavaWorld This Week free weekly email newsletter to learn what's new
on JavaWorld:
http://www.idg.net/jw-subscribe
You'll find a wealth of IT-related articles from our sister publications at IDG.net
Removing the Invokers
HTTP Invokers
If you want to remove the HTTP invokers (which are used if you 'tunnel' your requests through
HTTP) simply remove the according deployments/directories from the .../deploy/ directory.
Please be aware that HTTP invokers are something different than the Tomcat HTTP Connector
(the HTTP invokers need the HTTP connector but the HTTP connector does not need the HTTP
invokers).
489 | P a g e
HTTPInvoker for JNDI, EJB and JMX
Simply remove the .../deploy/http-invoker.sar/ directory from your configuration all together.
HTTPInvoker for JMS
Remove the .../deploy/jms/jbossmq-httpil.sar directory completly.
Other invokers
There are a lot of other invokers bound to different ports. If you don't need them you may
remove them. Otherwise secure them if they are reachable by folks you don't fully trust.
SecureTheInvokers
Enabling authentication to the RMIAdaptor service
FIXME: this article is about securing Invoker Access to the JMX. Not the general invoker security.
Since 3.2.4, the JMX Detached Invoker Service which provides the RMIAdaptor interface into the
MBeanServer has supported JAAS authentication of callers.
Note, there is a bug in the 4.0.x implementation that is fixed in 4.0.5 GA.
To enable this:
- in JBossAS 5.0x, see Technical Paper in SecureTheJmxConsole
- in JBossAS 4.0.x, edit jmx-invoker-service.xml
- in JBossAS 3.2.x, edit jmx-invoker-adaptor-server.sar/META-INF/jboss-service.xml
and uncomment the descriptors section of the invoke operation:
<operation>
<description>The detached invoker entry point</description>
<name>invoke</name>
<parameter>
<description>The method invocation context</description>
490 | P a g e
<name>invocation</name>
<type>org.jboss.invocation.Invocation</type>
</parameter>
<return-type>java.lang.Object</return-type>
<!-- Uncomment to require authenticated users -->
<descriptors>
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securityDomain="java:/jaas/jmx-console"></interceptor>
</interceptors>
</descriptors>
</operation>
The value of the securityDomain attribute maps to the security domain name found in the
conf/login-config.xml definitions the same way as the jboss.xml, jboss-web.xml security-domain
elements do. In this case the jmx-console security domain configuration is being used.
Note, in some version of jboss when running under java5+, you may see an error like the
following:
. This is due to a change in how the jmx descriptor names are stored with case preserved. To
work around this isssue simply use all lower case attribute names:
...
<descriptors>
<interceptors>
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor"
securitydomain="java:/jaas/jmx-console"></interceptor>
</interceptors>
</descriptors>
This still works under jdk14.
Enabling authorization to the RMIAdaptor service
Along the lines of the AuthenticationInterceptor, an AuthorizationInterceptor is available in
JBoss. The interceptor should be placed after the AuthenticationInterceptor and has the
following configuration.
 authorizingClass : Fully Qualified Name of a class that does the authorization and which
contains a method with the following signature
"public void authorize( Principal caller, Subject subject, String objectname,String
opname)" that can throw a java.lang.SecurityException
An example of an authorizing class is available in JBoss. It is
theorg.jboss.jmx.connector.invoker.RolesAuthorization, which looks for an hardcoded
"JBossAdmin" role in the authenticated subject.
<descriptors>
<interceptors>

More Related Content

PDF
Automatic detction of web apps vulnerability
PDF
Secure Software Development with 3rd Party Dependencies
PPTX
Why Johnny Still Can’t Pentest: A Comparative Analysis of Open-source Black-...
PPTX
Managing Security in External Software Dependencies
PDF
Routine Detection Of Web Application Defence Flaws
PDF
vulnerability scanning and reporting tool
PDF
Talking About SSRF,CRLF
PDF
A26001006
Automatic detction of web apps vulnerability
Secure Software Development with 3rd Party Dependencies
Why Johnny Still Can’t Pentest: A Comparative Analysis of Open-source Black-...
Managing Security in External Software Dependencies
Routine Detection Of Web Application Defence Flaws
vulnerability scanning and reporting tool
Talking About SSRF,CRLF
A26001006

What's hot (20)

PDF
Web Application Security Guide by Qualys 2011
PDF
PROP - P ATRONAGE OF PHP W EB A PPLICATIONS
PPTX
SSRF exploit the trust relationship
PDF
IRJET- Testing Web Application using Vulnerability Scan
PDF
website vulnerability scanner and reporter research paper
PDF
Injection attacks
PPTX
Why Johnny Still Can’t Pentest: A Comparative Analysis of Open-source Black-b...
PDF
WAF Deployment proposal
PDF
Web Application Penetration Tests - Vulnerability Identification and Details ...
PDF
PHP SuperGlobals - Supersized Trouble
PDF
Analysis of XSS attack Mitigation techniques based on Platforms and Browsers
PDF
Sql injection bypassing hand book blackrose
PDF
Web Application Penetration Tests - Reporting
PDF
Software Security - Vulnerability&Attack
PPTX
Patch Tuesday Analysis - June 2016
PDF
Prevention Against CSRF Attack using Client Server Mutual Authentication Tech...
PDF
The Value of Shared Threat Intelligence
PDF
Don’t let Your Website Spread Malware – a New Approach to Web App Security
PPTX
Hardening Enterprise Apache
PDF
Nii sample pt_report
Web Application Security Guide by Qualys 2011
PROP - P ATRONAGE OF PHP W EB A PPLICATIONS
SSRF exploit the trust relationship
IRJET- Testing Web Application using Vulnerability Scan
website vulnerability scanner and reporter research paper
Injection attacks
Why Johnny Still Can’t Pentest: A Comparative Analysis of Open-source Black-b...
WAF Deployment proposal
Web Application Penetration Tests - Vulnerability Identification and Details ...
PHP SuperGlobals - Supersized Trouble
Analysis of XSS attack Mitigation techniques based on Platforms and Browsers
Sql injection bypassing hand book blackrose
Web Application Penetration Tests - Reporting
Software Security - Vulnerability&Attack
Patch Tuesday Analysis - June 2016
Prevention Against CSRF Attack using Client Server Mutual Authentication Tech...
The Value of Shared Threat Intelligence
Don’t let Your Website Spread Malware – a New Approach to Web App Security
Hardening Enterprise Apache
Nii sample pt_report
Ad

Viewers also liked (20)

PDF
Java secure development part 3
PDF
Implementing and auditing security controls part 2
PDF
Java secure development part 1
PDF
Implementing and auditing security controls part 1
PDF
Ciso back to the future - network vulnerabilities
PDF
Issa security in a virtual world
PDF
Cyber attacks 101
PDF
Siem &amp; log management
PDF
Darknet
PDF
Cyber crime
PDF
Totally Excellent Tips for Righteous Local SEO
PPTX
Endocarditis
PPTX
Agriculture connectée 4.0
PPTX
The Next Tsunami AI Blockchain IOT and Our Swarm Evolutionary Singularity
PDF
Beyond the Gig Economy
PDF
Recovery: Job Growth and Education Requirements Through 2020
PPTX
3 hard facts shaping higher education thinking and behavior
PDF
African Americans: College Majors and Earnings
PDF
The Online College Labor Market
PDF
Game Based Learning for Language Learners
Java secure development part 3
Implementing and auditing security controls part 2
Java secure development part 1
Implementing and auditing security controls part 1
Ciso back to the future - network vulnerabilities
Issa security in a virtual world
Cyber attacks 101
Siem &amp; log management
Darknet
Cyber crime
Totally Excellent Tips for Righteous Local SEO
Endocarditis
Agriculture connectée 4.0
The Next Tsunami AI Blockchain IOT and Our Swarm Evolutionary Singularity
Beyond the Gig Economy
Recovery: Job Growth and Education Requirements Through 2020
3 hard facts shaping higher education thinking and behavior
African Americans: College Majors and Earnings
The Online College Labor Market
Game Based Learning for Language Learners
Ad

Similar to Java secure development part 2 (20)

PPTX
Outpost24 webinar - Understanding the 7 deadly web application attack vectors
PPTX
Edgescan vulnerability stats report 2019 - h-isac-2-2-2019
PDF
Rational Unified Treatment for Web Application Vulnerability Assessment
PPTX
IISF-March2023.pptx
PDF
IRJET- Bug Hunting using Web Application Penetration Testing Techniques.
PPT
How PCI And PA DSS will change enterprise applications
PDF
Qg was guide
PPTX
Radware - WAF (Web Application Firewall)
PPTX
PCI & Serverless - Everything you need to know
PDF
PDF
Clear Pci Vulnerability Scans Web2
PDF
Managing Software Risk with CAST
PPTX
Continuous Application Security at Scale with IAST and RASP -- Transforming D...
PPT
Bank One App Sec Training
PDF
Vulnerabilities are bugs, Let's Test For Them!
PDF
Vulnerabilities are bugs, Let's test for them!
PDF
example of sql injection
PDF
owasp-top-10 presentation dhs ad health .
PPT
Secure SDLC for Software
PPTX
Evento - Fintech Districht - Pierguido Iezzi - SWASCAN
Outpost24 webinar - Understanding the 7 deadly web application attack vectors
Edgescan vulnerability stats report 2019 - h-isac-2-2-2019
Rational Unified Treatment for Web Application Vulnerability Assessment
IISF-March2023.pptx
IRJET- Bug Hunting using Web Application Penetration Testing Techniques.
How PCI And PA DSS will change enterprise applications
Qg was guide
Radware - WAF (Web Application Firewall)
PCI & Serverless - Everything you need to know
Clear Pci Vulnerability Scans Web2
Managing Software Risk with CAST
Continuous Application Security at Scale with IAST and RASP -- Transforming D...
Bank One App Sec Training
Vulnerabilities are bugs, Let's Test For Them!
Vulnerabilities are bugs, Let's test for them!
example of sql injection
owasp-top-10 presentation dhs ad health .
Secure SDLC for Software
Evento - Fintech Districht - Pierguido Iezzi - SWASCAN

More from Rafel Ivgi (14)

PDF
Hacker techniques, exploit and incident handling
PDF
Top 10 mistakes running a windows network
PDF
Advanced web application hacking and exploitation
PDF
Firmitas Cyber Solutions - Inforgraphic - Mirai Botnet - A few basic facts on...
PDF
Firmitas Cyber Solutions - Inforgraphic - ICS & SCADA Vulnerabilities
PDF
United States O1 Visa Approval
PDF
Comptia Security+ CE Certificate
PDF
ISACA Membership
PDF
CISSP
PDF
PDF
LPIC-1
PDF
CRISC
PDF
Iso 27001 Pecb Ismsla 100193 Rafel Ivgi
PDF
Webapplicationsecurity05 2010 100601100553 Phpapp02
Hacker techniques, exploit and incident handling
Top 10 mistakes running a windows network
Advanced web application hacking and exploitation
Firmitas Cyber Solutions - Inforgraphic - Mirai Botnet - A few basic facts on...
Firmitas Cyber Solutions - Inforgraphic - ICS & SCADA Vulnerabilities
United States O1 Visa Approval
Comptia Security+ CE Certificate
ISACA Membership
CISSP
LPIC-1
CRISC
Iso 27001 Pecb Ismsla 100193 Rafel Ivgi
Webapplicationsecurity05 2010 100601100553 Phpapp02

Recently uploaded (20)

PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Transform Your Business with a Software ERP System
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
medical staffing services at VALiNTRY
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
System and Network Administration Chapter 2
PPTX
L1 - Introduction to python Backend.pptx
PDF
Digital Strategies for Manufacturing Companies
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Design an Analysis of Algorithms I-SECS-1021-03
Transform Your Business with a Software ERP System
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Reimagine Home Health with the Power of Agentic AI​
Understanding Forklifts - TECH EHS Solution
Softaken Excel to vCard Converter Software.pdf
How Creative Agencies Leverage Project Management Software.pdf
medical staffing services at VALiNTRY
Odoo Companies in India – Driving Business Transformation.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
wealthsignaloriginal-com-DS-text-... (1).pdf
System and Network Administration Chapter 2
L1 - Introduction to python Backend.pptx
Digital Strategies for Manufacturing Companies
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx

Java secure development part 2

  • 1. 245 | P a g e If we consider vulnerability origin as a whole (according to classification in Appendix 2) we’ll see that vulnerabilities caused by insufficient administration are 20% more frequent (P. 5). At the same time, there are up to 4 issues per site caused by administration flaws and up to 8 vulnerabilities caused by design errors (T. 2). T. 2 The probability to detect vulnerabilities depending on vulnerability origin No. of Vulns No. of Sites % Vulns % Sites No. Vulns on Site Vulnerability in administration 41859 10347 42.91% 84.91% 4.05 Vulnerability in code 55695 7023 57.09% 57.63% 7.93 Less than 60% of vulnerabilities are in code
  • 2. 246 | P a g e P. 5 The probability to detect vulnerabilities depending on their origin Detailed web application analysis by black box and white box methods shows that appreciable percent of sites are vulnerable to Content Spoofing and Path Traversal (P. 6), and the probability to detect a vulnerability of SQL Injection type reaches 19% in this approach (P. 7). P. 6 The most widespread vulnerabilities in web applications (% Vulns BlackBox & WhiteBox)
  • 3. 247 | P a g e P. 7 The probability to detect the most widespread vulnerabilities in web applications (% Sites BlackBox & WhiteBox) P. 8 Percent of vulnerabilities out of total number of vulnerabilities (% Vulns BlackBox & WhiteBox) If we consider the prevalence of high risk level vulnerabilities in detailed web application analysis (P. 9) we’ll see that the most widespread is Credential/Session Prediction errors. SQL Injection, Path Traversal
  • 4. 248 | P a g e and implementation and configuration errors in authentication and authorization systems are also widespread. P. 9 The probability to detect the most risky vulnerabilities in Web applications (% Sites BlackBox & WhiteBox) If we consider the probability to detect vulnerabilities in terms of web resource visitors and web server impact (according to classification in appendix 2), the server-side vulnerabilities are the most widespread (P. 10). But the vulnerability distribution by impact type per site is irregular and greatly depends on used vulnerability search method (P. 11).
  • 5. 249 | P a g e P. 10 The probability to detect vulnerability by impact type Whitebox approach (dynamic or static) is Required to catch vulnerabilities
  • 6. 250 | P a g e P. 11.Vulnerabilities per site by different search methods (No. Vulns on Site) T. 3 Vulnerabilities by impact No. of Vulns No. of Sites % Vulns % Sites No. Vulns on Site ALL Stat (Server-Side) 50856 10125 52.13% 83.09% 5.02 ALL Stat (Client-Side) 46698 7580 47.87% 62.20% 6.16 Scans (Server-Side) 19746 8922 55.60% 85.40% 2.21 Scans (Client-Side) 15767 6607 44.40% 63.24% 2.39 BlackBox (Server-Side) 4260 804 23.77% 76.86% 5.30 BlackBox (Client-Side) 13665 747 76.23% 71.41% 18.29 WhiteBox (Server-Side) 17700 145 63.73% 96.67% 122.07 WhiteBox (Client-Side) 10072 117 36.27% 78.00% 86.09
  • 7. 251 | P a g e Data analysis according to PCI DSS requirements If we consider data sets about vulnerable Web applications according to PCI DSS requirements, we can easily sort (T. 4) those that are about certain vulnerability elimination in Web applications. In addition, PCI DSS Technical and Operational Requirements for Approved Scanning Vendors (ASVs) includes similar requirements but affects only ASV scanning by PCI (T. 5). T. 4 PCI DSS requirements for Web application security PCI DSS v.1.2 requirements Procedure 6.5 Develop all web applications (internal and external, and including web administrative access to application) based on secure coding guidelines such as the Open Web Application Security Project Guide. Cover prevention of common coding vulnerabilities in software development processes, to include the following: - 6.5.1 Cross-site scripting (XSS) 6.5.1 Cross-site scripting (XSS) (Validate all parameters before inclusion.) 6.5.2 Injection flaws, particularly SQL injection. Also consider LDAP and Xpath injection flaws as well as other injection flaws. 6.5.2 Injection flaws, particularly SQL injection (Validate input to verify user data cannot modify meaning of commands and queries.) 6.5.3 Malicious file execution 6.5.3 Malicious file execution (Validate input to verify application does not accept filenames or files from users.) 6.5.5 Cross-site request forgery (CSRF) 6.5.5 Cross-site request forgery (CSRF) (Do not reply on authorization credentials and tokens automatically submitted by browsers.) 6.5.6 Information leakage and improper 6.5.6 Information leakage and improper error
  • 8. 252 | P a g e error handling handling (Do not leak information via error messages or other means.) 6.5.7 Broken authentication and session management 6.5.7 Broken authentication and session management (Properly authenticate users and protect account credentials and session tokens.) 6.5.9 Insecure communications 6.5.9 Insecure communications (Properly encrypt all authenticated and sensitive communications.) 6.6 For public-facing web applications, address new threats and vulnerabilities on an ongoing basis and ensure these applications are protected against known attacks by either of the following methods: - Reviewing public-facing web applications via manual or automated application vulnerability security assessment tools or methods, at least annually and after any changes - Installing a web-application firewall in front of public-facing web applications - T. 5 PCI DSS Technical and Operational Requirements for Approved Scanning Vendors (ASVs) for WEB Technical and Operational Requirements for Approved Scanning Vendors (ASVs) v.1.1 Procedure Web Server Check The ASV scanning solution must be able to test for all known vulnerabilities and configuration issues on web servers. New exploits are routinely discovered in web server products. The ASV scanning solution must be able to detect and report known exploits.
  • 9. 253 | P a g e Browsing of directories on a web server is not a good practice. The ASV scanning solution must be able to scan the web site and verify that directory browsing is not possible on the server. The ASV scanning solution must be able to detect all known CGI vulnerabilities. Custom Web Application Check The ASV scanning solution must be able to detect the following application vulnerabilities and configuration issues: • Unvalidated parameters which lead to SQL injection attacks • Cross-site scripting (XSS) flaws Assessing collected data statistics by criteria from T. 4 and T. 5, we conclude the following (see T. 6 and P. 12 – 14). T. 6 % of sites which are not complaint to PCI DSS requirements in Web application scanning methods PCI DSS v.1.2 requirement Non compliant. ALL (% Sites) Non compliant. Scans (% Sites) Non compliant. BlackBox (% Sites) Non compliant. WhiteBox (% Sites) 6.5.1 Cross-site scripting (XSS) 38.45% 37.66% 56.41% 58.67% 6.5.2 Injection flaws. particularly SQL injection. Also consider LDAP and Xpath injection flaws as well as other injection flaws. 14.55% 12.70% 19.31% 64.00% 6.5.3 Malicious file execution 0.94% 0.08% 1.05% 8.67% 6.5.5 Cross-site request forgery (CSRF) 1.32% 0.02% 7.93% 0.67% 6.5.6 Information leakage and improper error handling 66.67% 74.05% 38.24% 54.00%
  • 10. 254 | P a g e 6.5.7 Broken authentication and session management 7.62% 0.52% 30.98% 71.33% 6.5.9 Insecure communications 34.42% 39.96% 0.00%* 17.33% Technical and Operational Requirements for Approved Scanning Vendors (ASVs) v.1.1 Web Server Check Inapplicable 5.73% Inapplicable Inapplicable Custom Web Application Check Inapplicable 44.92% Inapplicable Inapplicable * Vulnerability of this class are not incuded into reports during web application security assessment by black box method. P 12. The distribution of sites non compliant to PCI DSS
  • 11. 255 | P a g e P 13.Compliance level of Web application to PCI DSS (QSA) requirements P 14. Compliance level of Web application to PCI DSS (ASV) requirements
  • 12. 256 | P a g e Thus, more than 48 % of scanned Web applications are not compliant to PCI DSS requirements by ASV scanning. Meanwhile, deeper analysis shows that 99% of Web applications are not complaint to the standard requirements. APPENDIX 1: RISK ASSESSMENT METHODOLOGY T. 8 Risk level assessment routine Threat Classification Basic CVSS Score PCI DSS Risk Abuse of Functionality 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium Brute Force Attack 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical Buffer Overflow 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Content Spoofing 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High Credential/Session Prediction 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical Cross-Site Scripting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical Cross-Site Request Forgery 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High Denial of Service 7.8 (AV:N/AC:L/Au:N/C:N/I:N/A:C) High Format String Attack 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent HTTP Request Splitting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical HTTP Response Splitting 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical HTTP Request Smuggling 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical HTTP Response Smuggling 6.4 (AV:N/AC:L/Au:N/C:P/I:P/A:N) Critical Integer Overflow 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent LDAP Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Mail Command Injection 5 (AV:N/AC:L/Au:N/C:N/I:P/A:N) High OS Commanding 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Path Traversal 7.8 (AV:N/AC:L/Au:N/C:C/I:N/A:N) Critical Predictable Resource Location 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High Remote File Inclusion 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent
  • 13. 257 | P a g e Routing Detour 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High SOAP Array Abuse 7.8 (AV:N/AC:L/Au:N/C:N/I:N/A:C) High SSI Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Session Fixation 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical SQL Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent URL Redirectors 2.6 (AV:N/AC:H/Au:N/C:N/I:P/A:N) Medium XPath Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent XML Attribute Blowup 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High XML External Entity 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High XML Entity Expansion 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High XML Injection 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P) Critical XQuery Injection 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Application Misconfiguration 5.1 (AV:N/AC:H/Au:N/C:P/I:P/A:P) Medium Directory Indexing 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High Fingerprinting 0 (AV:N/AC:L/Au:N/C:N/I:N/A:N) Low Improper Parsing 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Improper Permissions 10 (AV:N/AC:L/Au:N/C:C/I:C/A:C) Urgent Information leakage 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High Insecure Indexing 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High Insufficient Anti-automation 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium Insufficient Authentication 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical Insufficient Authorization 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical Insufficient Data Protection 5 (AV:N/AC:L/Au:N/C:P/I:N/A:N) High Insufficient Process Validation 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium Insufficient Session Expiration 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P) Critical Insufficient Transport Layer Protection 4 (AV:N/AC:H/Au:N/C:P/I:P/A:N) Medium Server Misconfiguration 5.1 (AV:N/AC:H/Au:N/C:P/I:P/A:P) Medium
  • 14. 258 | P a g e APPENDIX 2: ADDITIONAL VULNERABILITY CLASSIFICATION T. 9 Vulnerability classification by origin and impact Threat Classification Vulnerability in Impact Abuse of Functionality code server-side Brute Force Attack administration server-side Buffer Overflow code server-side Content Spoofing code client-side Credential/Session Prediction code server-side Cross-Site Scripting code client-side Cross-Site Request Forgery code client-side Denial of Service administration server-side Format String Attack code server-side HTTP Request Splitting code client-side HTTP Response Splitting code client-side HTTP Request Smuggling administration client-side HTTP Response Smuggling administration client-side Integer Overflow code server-side LDAP Injection code server-side Mail Command Injection code server-side OS Commanding code server-side Path Traversal code server-side Predictable Resource Location administration server-side Remote File Inclusion code server-side Routing Detour code server-side SOAP Array Abuse code server-side SSI Injection code server-side
  • 15. 259 | P a g e Session Fixation code server-side SQL Injection code server-side URL Redirectors code client-side XPath Injection code server-side XML Attribute Blowup code server-side XML External Entity code server-side XML Entity Expansion code server-side XML Injection code server-side XQuery Injection code server-side Application Misconfiguration administration server-side Directory Indexing administration server-side Fingerprinting administration server-side Improper Parsing code server-side Improper Permissions administration server-side Information leakage administration server-side Insecure Indexing administration server-side Insufficient Anti-automation code server-side Insufficient Authentication code server-side Insufficient Authorization code server-side Insufficient Data Protection administration server-side Insufficient Process Validation code server-side Insufficient Session Expiration code server-side Insufficient Transport Layer Protection administration client-side Server Misconfiguration administration server-side APPENDIX 3: STATISTICS Overall Data T. 10 General statistics Threat Classification
  • 16. 260 | P a g e Threat Classification N of Vulns N of Sites Vulns% Sites% Abuse of Functionality 153 83 0.16% 0.68% Brute Force Attack 79 51 0.08% 0.42% Buffer Overflow 537 84 0.55% 0.69% Content Spoofing 1564 304 1.60% 2.49% Credential/Session Prediction 794 147 0.81% 1.21% Cross-Site Scripting 37624 4686 38.57% 38.45% Cross-Site Request Forgery 285 161 0.29% 1.32% Denial of Service 42 36 0.04% 0.30% Format String Attack 52 43 0.05% 0.35% HTTP Request Splitting 311 162 0.32% 1.33% HTTP Response Splitting 2592 161 2.66% 1.32% HTTP Request Smuggling 0 0 0.00% 0.00% HTTP Response Smuggling 0 0 0.00% 0.00% Integer Overflow 79 46 0.08% 0.38% LDAP Injection 41 16 0.04% 0.13% Mail Command Injection 1 1 0.00% 0.01% OS Commanding 76 30 0.08% 0.25% Path Traversal 1563 139 1.60% 1.14% Predictable Resource Location 1507 295 1.54% 2.42% Remote File Inclusion 99 44 0.10% 0.36% Routing Detour 0 0 0.00% 0.00% SOAP Array Abuse 2 1 0.00% 0.01% SSI Injection 157 33 0.16% 0.27% Session Fixation 137 123 0.14% 1.01% SQL Injection 6345 1555 6.50% 12.76% URL Redirectors 5 4 0.01% 0.03%
  • 17. 261 | P a g e XPath Injection 64 19 0.07% 0.16% XML Attribute Blowup 0 0 0.00% 0.00% XML External Entity 0 0 0.00% 0.00% XML Entity Expansion 0 0 0.00% 0.00% XML Injection 0 0 0.00% 0.00% XQuery Injection 0 0 0.00% 0.00% Application Misconfiguration 85 60 0.09% 0.49% Directory Indexing 370 184 0.38% 1.51% Fingerprinting 3663 3604 3.75% 29.57% Improper Parsing 1464 524 1.50% 4.30% Improper Permissions 4 4 0.00% 0.03% Information leakage 31527 7942 32.32% 65.17% Insecure Indexing 8 7 0.01% 0.06% Insufficient Anti-automation 108 36 0.11% 0.30% Insufficient Authentication 806 304 0.83% 2.49% Insufficient Authorization 615 286 0.63% 2.35% Insufficient Data Protection 64 21 0.07% 0.17% Insufficient Process Validation 52 34 0.05% 0.28% Insufficient Session Expiration 169 71 0.17% 0.58% Insufficient Transport Layer Protection 4317 4195 4.43% 34.42% Server Misconfiguration 193 113 0.20% 0.93% Total 97554 12186 T. 11 Vulnerabilities distribution by risk Threat rank Threat rank N of Vulns N of Sites Vulns% % Sites Urgent 8918 2287 9.14% 18.77% Critical 44669 5511 45.79% 45.22% High 35375 8807 36.26% 72.27%
  • 18. 262 | P a g e Medium 4908 4455 5.03% 36.56% Low 3663 3618 3.75% 29.69% Automatic scans T. 12 General statistics Threat Classification Threat Classification N of Vulns N of Sites Vulns% Sites% Abuse of Functionality 1 1 0.00% 0.01% Brute Force Attack 5 5 0.01% 0.05% Buffer Overflow 6 3 0.02% 0.03% Content Spoofing 29 22 0.08% 0.21% Credential/Session Prediction 9 9 0.03% 0.09% Cross-Site Scripting 11230 3934 31.62% 37.66% Cross-Site Request Forgery 2 2 0.01% 0.02% Denial of Service 30 25 0.08% 0.24% Format String Attack 0 0 0.00% 0.00% HTTP Request Splitting 311 162 0.88% 1.55% HTTP Response Splitting 0 0 0.00% 0.00% HTTP Request Smuggling 0 0 0.00% 0.00% HTTP Response Smuggling 0 0 0.00% 0.00% Integer Overflow 0 0 0.00% 0.00% LDAP Injection 0 0 0.00% 0.00% Mail Command Injection 0 0 0.00% 0.00% OS Commanding 28 5 0.08% 0.05% Path Traversal 82 56 0.23% 0.54% Predictable Resource Location 16 15 0.05% 0.14% Remote File Inclusion 86 36 0.24% 0.34% Routing Detour 0 0 0.00% 0.00%
  • 19. 263 | P a g e SOAP Array Abuse 0 0 0.00% 0.00% SSI Injection 157 33 0.44% 0.32% Session Fixation 3 3 0.01% 0.03% SQL Injection 2969 1217 8.36% 11.65% URL Redirectors 1 1 0.00% 0.01% XPath Injection 0 0 0.00% 0.00% XML Attribute Blowup 0 0 0.00% 0.00% XML External Entity 0 0 0.00% 0.00% XML Entity Expansion 0 0 0.00% 0.00% XML Injection 0 0 0.00% 0.00% XQuery Injection 0 0 0.00% 0.00% Application Misconfiguration 48 37 0.14% 0.35% Directory Indexing 12 11 0.03% 0.11% Fingerprinting 3604 3587 10.15% 34.34% Improper Parsing 1463 523 4.12% 5.01% Improper Permissions 2 2 0.01% 0.02% Information leakage 11134 7593 31.35% 72.68% Insecure Indexing 8 7 0.02% 0.07% Insufficient Anti-automation 0 0 0.00% 0.00% Insufficient Authentication 24 15 0.07% 0.14% Insufficient Authorization 14 14 0.04% 0.13% Insufficient Data Protection 10 10 0.03% 0.10% Insufficient Process Validation 12 11 0.03% 0.11% Insufficient Session Expiration 1 1 0.00% 0.01% Insufficient Transport Layer Protection 4194 4175 11.81% 39.96% Server Misconfiguration 22 22 0.06% 0.21% Total 35513 10447
  • 20. 264 | P a g e T. 13 Vulnerabilities distribution by risk Threat rank Threat rank N of Vulns N of Sites Vulns% % Sites Urgent 4711 1745 13.27% 16.70% Critical 11679 4100 32.89% 39.25% High 11257 7636 31.70% 73.09% Medium 4294 4199 12.09% 40.19% Low 3625 3599 10.21% 34.45% Black Box T. 14 General statistics Threat Classification Threat Classification N of Vulns N of Sites Vulns% Sites% Abuse of Functionality 135 75 0.75% 7.17% Brute Force Attack 34 29 0.19% 2.77% Buffer Overflow 0 0 0.00% 0.00% Content Spoofing 1110 241 6.19% 23.04% Credential/Session Prediction 15 12 0.08% 1.15% Cross-Site Scripting 11768 590 65.65% 56.41% Cross-Site Request Forgery 185 83 1.03% 7.93% Denial of Service 9 8 0.05% 0.76% Format String Attack 2 2 0.01% 0.19% HTTP Request Splitting 0 0 0.00% 0.00% HTTP Response Splitting 601 77 3.35% 7.36% HTTP Request Smuggling 0 0 0.00% 0.00% HTTP Response Smuggling 0 0 0.00% 0.00% Integer Overflow 9 6 0.05% 0.57% LDAP Injection 0 0 0.00% 0.00% Mail Command Injection 0 0 0.00% 0.00%
  • 21. 265 | P a g e OS Commanding 16 11 0.09% 1.05% Path Traversal 29 20 0.16% 1.91% Predictable Resource Location 855 155 4.77% 14.82% Remote File Inclusion 3 3 0.02% 0.29% Routing Detour 0 0 0.00% 0.00% SOAP Array Abuse 0 0 0.00% 0.00% SSI Injection 0 0 0.00% 0.00% Session Fixation 83 79 0.46% 7.55% SQL Injection 1556 169 8.68% 16.16% URL Redirectors 1 1 0.01% 0.10% XPath Injection 59 17 0.33% 1.63% XML Attribute Blowup 0 0 0.00% 0.00% XML External Entity 0 0 0.00% 0.00% XML Entity Expansion 0 0 0.00% 0.00% XML Injection 0 0 0.00% 0.00% XQuery Injection 0 0 0.00% 0.00% Application Misconfiguration 31 20 0.17% 1.91% Directory Indexing 104 42 0.58% 4.02% Fingerprinting 1 1 0.01% 0.10% Improper Parsing 1 1 0.01% 0.10% Improper Permissions 2 2 0.01% 0.19% Information leakage 745 399 4.16% 38.15% Insecure Indexing 0 0 0.00% 0.00% Insufficient Anti-automation 6 4 0.03% 0.38% Insufficient Authentication 158 90 0.88% 8.60% Insufficient Authorization 312 155 1.74% 14.82% Insufficient Data Protection 2 2 0.01% 0.19% Insufficient Process Validation 5 5 0.03% 0.48%
  • 22. 266 | P a g e Insufficient Session Expiration 30 27 0.17% 2.58% Insufficient Transport Layer Protection 0 0 0.00% 0.00% Server Misconfiguration 58 38 0.32% 3.63% Total 17925 1046 T. 15 Vulnerabilities distribution by risk Threat rank Threat rank N of Vulns N of Sites Vulns% % Sites Urgent 1648 206 9.19% 19.69% Critical 13030 782 72.69% 74.76% High 3011 612 16.80% 58.51% Medium 235 126 1.31% 12.05% Low 1 1 0.01% 0.10% White Box T. 16 General statistics Threat Classification Threat Classification N of Vulns N of Sites Vulns% Sites% Abuse of Functionality 7 4 0.03% 2.67% Brute Force Attack 15 11 0.05% 7.33% Buffer Overflow 421 1 1.52% 0.67% Content Spoofing 0 0 0.00% 0.00% Credential/Session Prediction 695 66 2.50% 44.00% Cross-Site Scripting 8006 88 28.83% 58.67% Cross-Site Request Forgery 2 1 0.01% 0.67% Denial of Service 3 3 0.01% 2.00% Format String Attack 2 1 0.01% 0.67% HTTP Request Splitting 0 0 0.00% 0.00% HTTP Response Splitting 1941 54 6.99% 36.00%
  • 23. 267 | P a g e HTTP Request Smuggling 0 0 0.00% 0.00% HTTP Response Smuggling 0 0 0.00% 0.00% Integer Overflow 0 0 0.00% 0.00% LDAP Injection 0 0 0.00% 0.00% Mail Command Injection 1 1 0.00% 0.67% OS Commanding 29 12 0.10% 8.00% Path Traversal 1450 59 5.22% 39.33% Predictable Resource Location 15 13 0.05% 8.67% Remote File Inclusion 3 2 0.01% 1.33% Routing Detour 0 0 0.00% 0.00% SOAP Array Abuse 0 0 0.00% 0.00% SSI Injection 0 0 0.00% 0.00% Session Fixation 1 1 0.00% 0.67% SQL Injection 898 59 3.23% 39.33% URL Redirectors 0 0 0.00% 0.00% XPath Injection 0 0 0.00% 0.00% XML Attribute Blowup 0 0 0.00% 0.00% XML External Entity 0 0 0.00% 0.00% XML Entity Expansion 0 0 0.00% 0.00% XML Injection 0 0 0.00% 0.00% XQuery Injection 0 0 0.00% 0.00% Application Misconfiguration 1 1 0.00% 0.67% Directory Indexing 2 2 0.01% 1.33% Fingerprinting 8 6 0.03% 4.00% Improper Parsing 0 0 0.00% 0.00% Improper Permissions 0 0 0.00% 0.00% Information leakage 13598 81 48.96% 54.00% Insecure Indexing 0 0 0.00% 0.00%
  • 24. 268 | P a g e Insufficient Anti-automation 2 2 0.01% 1.33% Insufficient Authentication 324 45 1.17% 30.00% Insufficient Authorization 89 6 0.32% 4.00% Insufficient Data Protection 52 9 0.19% 6.00% Insufficient Process Validation 5 3 0.02% 2.00% Insufficient Session Expiration 78 28 0.28% 18.67% Insufficient Transport Layer Protection 123 26 0.44% 17.33% Server Misconfiguration 1 1 0.00% 0.67% Total 27772 150 T. 17 Vulnerabilities distribution by risk Threat rank Threat rank N of Vulns N of Sites Vulns% % Sites Urgent 1353 75 4.87% 50.00% Critical 12599 138 45.37% 92.00% High 13673 93 49.23% 62.00% Medium 139 36 0.50% 24.00% Low 8 6 0.03% 4.00%
  • 25. 269 | P a g e OWASP Application Security Verification Standard (ASVS) Types of security verification  In addition, in ASVS  level 3 is “Design Verification” (manual)  level 4 is “Internal Verification” (manual) ASVS  High-level requirements  Detailed requirements
  • 26. 270 | P a g e  Reporting requirements  “Tools are an important part of every ASVS level. At higher levels in ASVS, the use of tools is encouraged. But to be effective, the tools must be heavily tailored and configured to the application and framework in use. And, at all levels, tool results must be manually verified.” ASVS Detailed requirements  V1. Security Architecture  V2. Authentication  V3. Session Management  V4. Access Control  V5. Input Validation  V6. Output Encoding/Escaping  V7. Cryptography  V8. Error Handling and Logging  V9. Data Protection  V10. Communication Security  V11. HTTP Security  V12. Security Configuration  V13. Malicious Code Search  V14. Internal Security
  • 27. 271 | P a g e ASVS Verification Requirements Matrix
  • 28. 272 | P a g e Quasi-scientific quantitative matrix analysis Examples of what requirements CAN be verified by automatic code scan  [V5.2] Verify that a positive validation pattern is defined and applied to all input.  [V6.1] Verify that all untrusted data that are output to HTML (including HTML elements, HTML attributes, JavaScript data values, CSS blocks, and URI attributes) are properly escaped for the applicable context.  [V8.1] Verify that that the application does not output error messages containing sensitive data that could assist an attacker, including session id and personal information.  [V11.2] Verify that the application accepts only a defined set of HTTP request methods, such as GET and POST. Examples of what requirements CANNOT be verified using automated code scan
  • 29. 273 | P a g e  [V2.5] Verify that all authentication controls (including libraries that call external authentication services) have a centralized implementation.  [V2.13] Verify that account passwords are salted using a salt that is unique to that account (e.g., internal user ID, account creation) and hashed before storing.  [V4.4] Verify that direct object references are protected, such that only authorized objects are  accessible to each user. (This can be of course checked dynamically.)  [V5.7] Verify that all input validation failures are logged.  [V8.6] Verify that each log event includes: 1. a time stamp from a reliable source, 2. severity level of the event […] and 7. a description of the event.  [V9.2] Verify that the list of sensitive data processed by this application is identified, and that there is an explicit policy for how access to this data must be controlled, and when this data must be encrypted (both at rest and in transit). Verify that this policy is properly enforced.  [V14.2] Verify that security control interfaces are simple enough to use that developers are likely to use them correctly. (This is a level 4 requirement.) Problems in automatic source code scan  A static analyzer cannot step back and look at the big picture, e.g. architectural layers  Evaluating non-functional security is almost impossible, e.g. robustness against DoS attack  Logic flaws (e.g. in authorization) or missing security requirements cannot be detected  Significant parts of the code may be missed completely, e.g. when in a different language or IoC/plugin code  Configuration analysis may be problematic as Well Mixing automation and manual work  Manual code review on paper is pain!  Tools are of great value, e.g.:  An IDE for traversing code (esp. jumping between caller and callee)  Grep or similar to quickly get pointers to interesting places and getting overview of technology used  Manual testing is good match for manual code review, and for that good tools (e.g. browser plugins) are essential
  • 30. 274 | P a g e From manual review to automation  Build automated checks for manual findings  Doing this statically is not easy without proper tools  Dynamic approach may be easier, e.g. targeted  automated scan or unit tests Conclusion  When, where and how to use automated tools?  Web portals implemented on a known and robust platform using systematic access control may be very good candidates:  Typical findings would be injection problems  Probably not much privacy or business assets to protect  Complex business web application (e.g. extranet application) could be harder to verify: o Logical checks, privacy more delicate o Scalability and transactions to think of  Choice of verification methodology based on risk analysis  Automatic code scan can give a rough measurement of a system even when run un- configured  Automatic code scanning is best combined with manual inspection, and/or as part of development build cycle  Scanner needs to be properly configured, though
  • 31. 275 | P a g e Using Automatic Tools to Discover Java Security & Reliability Vulnerabilities Fortify 360:
  • 32. 276 | P a g e
  • 33. 277 | P a g e Another Example:
  • 34. 278 | P a g e
  • 35. 279 | P a g e
  • 36. 280 | P a g e
  • 37. 281 | P a g e Weak XML Schema: Type Any
  • 38. 282 | P a g e
  • 39. 283 | P a g e Weak XML Schema: Lax Processing
  • 40. 284 | P a g e
  • 41. 285 | P a g e Passwords stored in clear text/base64 in code:
  • 42. 286 | P a g e Unreleased Resource Streams
  • 43. 287 | P a g e
  • 44. 288 | P a g e
  • 45. 289 | P a g e Null Dereference
  • 46. 290 | P a g e
  • 47. 291 | P a g e Path Manipulation
  • 48. 292 | P a g e
  • 49. 293 | P a g e Most Common False Positive: Real Case:
  • 50. 294 | P a g e Log Forging
  • 51. 295 | P a g e
  • 52. 296 | P a g e
  • 53. 297 | P a g e Command Injection
  • 54. 298 | P a g e
  • 55. 299 | P a g e Often Misused: Authentication
  • 56. 300 | P a g e
  • 57. 301 | P a g e Unreleased Resource: Database
  • 58. 302 | P a g e
  • 59. 303 | P a g e New object is created on each for loop iteration object is never closed
  • 60. 304 | P a g e Denial Of Service
  • 61. 305 | P a g e
  • 62. 306 | P a g e
  • 63. 307 | P a g e Password Management: Hardcoded Password
  • 64. 308 | P a g e
  • 65. 309 | P a g e SQL Injection: iBatis Data Map
  • 66. 310 | P a g e
  • 67. 311 | P a g e Common Java Code Security Pitfalls FindBugs (1.2.1-dev-20070506) Analysis for jdk1.7.0-b12 Bug Summary Analysis Information List bugs by bug category List bugs 1. Bad practice (954: 118/836/0/0) 1.1. BC: Bad casts of object references (5: 1/4/0/0) 1.2. Equals method should not assume anything about the type of its argument (4: 0/4/0/0) 2. Random object created and used only once (1: 1/0/0/0) 3. CN: Bad implementation of cloneable idiom (50: 0/50/0/0) 4. Class implements Cloneable but does not define or use clone method (14: 0/14/0/0) 5. clone method does not call super.clone() (36: 0/36/0/0) 6. Co: Problems with compareTo() (1: 0/1/0/0) 7. Covariant compareTo() method defined (1: 0/1/0/0) 8. DE: Dropped or ignored exception (50: 3/47/0/0) 9. Method might ignore exception (50: 3/47/0/0) 10. Dm: Dubious method used (3: 0/3/0/0) 11. Method invokes System.exit(...) (3: 0/3/0/0) 12. Eq: Problems with equals() (20: 1/19/0/0) 13. Class defines compareTo(...) and uses Object.equals() (14: 0/14/0/0) 14. Covariant equals() method defined, Object.equals(Object) inherited (6: 1/5/0/0) 15. ES: Checking String equality using == or != (133: 42/91/0/0) 16. Comparison of String parameter using == or != (92: 42/50/0/0) 17. Comparison of String objects using == or != (41: 0/41/0/0)
  • 68. 312 | P a g e 18. FI: Incorrect use of finalizers (12: 0/12/0/0) 19. Empty finalizer should be deleted (2: 0/2/0/0) 20. Finalizer does not call superclass finalizer (1: 0/1/0/0) 21. Finalizer nullifies superclass finalizer (9: 0/9/0/0) 22. HE: Equal objects must have equal hashcodes (200: 22/178/0/0) 23. Class defines equals() but not hashCode() (6: 0/6/0/0) 24. Class defines equals() and uses Object.hashCode() (41: 22/19/0/0) 25. Class inherits equals() and uses Object.hashCode() (153: 0/153/0/0) 26. It: Incorrect definition of Iterator (2: 0/2/0/0) 27. Iterator next() method can't throw NoSuchElement exception (2: 0/2/0/0) 28. Nm: Confusing method name (101: 0/101/0/0) 29. Class names should start with an upper case letter (8: 0/8/0/0) 30. Class is not derived from an Exception, even though it is named as such (9: 0/9/0/0) 31. Field names should start with an lower case letter (1: 0/1/0/0) 32. Method names should start with an lower case letter (69: 0/69/0/0) 33. Very confusing method names (but intentional) (14: 0/14/0/0) 34. NP: Null pointer dereference (16: 0/16/0/0) 35. Clone method may return null (4: 0/4/0/0) 36. equals() method does not check for null argument (10: 0/10/0/0) 37. toString method may return null (2: 0/2/0/0) 38. NS: Suspicious use of non-short-circuit boolean operator (1: 0/1/0/0) 39. Questionable use of non-short-circuit logic (1: 0/1/0/0) 40. OS: Stream not closed on all paths (14: 0/14/0/0) 41. Method may fail to close stream (14: 0/14/0/0) 42. RR: Method ignores results of InputStream.read() (29: 0/29/0/0) 43. Method ignores results of InputStream.read() (10: 0/10/0/0) 44. Method ignores results of InputStream.skip() (19: 0/19/0/0) 45. Se: Incorrect definition of Serializable class (275: 49/226/0/0) 46. Non-transient non-serializable instance field in serializable class (206: 20/186/0/0) 47. Non-serializable class has a serializable inner class (3: 0/3/0/0) 48. Non-serializable value stored into instance field of a serializable class (8: 2/6/0/0) 49. Comparator doesn't implement Serializable (11: 0/11/0/0) 50. Class is Serializable but its superclass doesn't define a void constructor (6: 6/0/0/0) 51. Class is Externalizable but doesn't define a void constructor (2: 0/2/0/0) 52. Transient field that isn't set by deserialization. (39: 21/18/0/0) 53. SnVI: Serializable class with no Version ID (42: 0/42/0/0) 53.1. Class is Serializable, but doesn't define serialVersionUID (42: 0/42/0/0) 54. Correctness (249: 81/168/0/0) 55. BC: Bad casts of object references (4: 1/3/0/0) 56. Impossible cast (1: 1/0/0/0)
  • 69. 313 | P a g e 57. instanceof will always return false (3: 0/3/0/0) 58. Bx: Questionable Boxing of primitive value (1: 0/1/0/0) 59. Primitive value is unboxed and coerced for ternary operator (1: 0/1/0/0) 60. DMI: Dubious method invocation (17: 0/17/0/0) 61. Invocation of toString on an array (17: 0/17/0/0) 62. EC: Suspicious equals() comparison (3: 2/1/0/0) 63. Call to equals() with null argument (1: 0/1/0/0) 64. Call to equals() comparing different types (2: 2/0/0/0) 65. FE: Test for floating point equality (6: 6/0/0/0) 66. Doomed test for equality to NaN (6: 6/0/0/0) 67. ICAST: Casting from integer values (5: 5/0/0/0) 68. int value cast to double and then passed to Math.ceil (3: 3/0/0/0) 69. int value cast to float and then passed to Math.round (2: 2/0/0/0) 70. IP: Ignored parameter (2: 0/2/0/0) 71. A parameter is dead upon entry to a method but overwritten (2: 0/2/0/0) 72. MF: Masked Field (16: 8/8/0/0) 73. Class defines field that masks a superclass field (16: 8/8/0/0) 74. Nm: Confusing method name (3: 2/1/0/0) 75. Class defines hashcode(); should it be hashCode()? (1: 1/0/0/0) 76. Apparent method/constructor confusion (1: 0/1/0/0) 77. Very confusing method names (1: 1/0/0/0) 78. NP: Null pointer dereference (69: 17/52/0/0) 79. Null pointer dereference (4: 4/0/0/0) 80. Null value is guaranteed to be dereferenced (5: 3/2/0/0) 81. A known null value is checked to see if it is an instance of a type (3: 0/3/0/0) 82. Possible null pointer dereference (22: 5/17/0/0) 83. Possible null pointer dereference in method on exception path (14: 0/14/0/0) 84. Method call passes null for unconditionally dereferenced parameter (13: 4/9/0/0) 85. Non-virtual method call passes null for unconditionally dereferenced parameter (1: 1/0/0/0) 86. Read of unwritten field (7: 0/7/0/0) 87. NS: Suspicious use of non-short-circuit boolean operator (4: 4/0/0/0) 88. Potentially dangerous use of non-short-circuit logic (4: 4/0/0/0) 89. RC: Suspicious reference comparison (8: 0/8/0/0) 90. Suspicious reference comparison (8: 0/8/0/0) 91. RCN: Redundant comparison to null (35: 10/25/0/0) 92. Nullcheck of value previously dereferenced (35: 10/25/0/0) 93. RV: Bad use of return value from method (7: 3/4/0/0) 94. Method ignores return value (7: 3/4/0/0) 95. SA: Useless self-operation (14: 12/2/0/0)
  • 70. 314 | P a g e 96. Double assignment of field (1: 0/1/0/0) 97. Self assignment of field (1: 0/1/0/0) 98. Self comparison of value with itself (12: 12/0/0/0) 99. SF: Switch case falls through (3: 3/0/0/0) 100. Dead store due to switch statement fall through (3: 3/0/0/0) 101. UCF: Useless control flow (1: 1/0/0/0) 102. Useless control flow to next line (1: 1/0/0/0) 103. UMAC: Uncallable method of anonymous class (6: 6/0/0/0) 104. Uncallable method defined in anonymous class (6: 6/0/0/0) 105. UR: Uninitialized read of field in constructor (5: 0/5/0/0) 106. Uninitialized read of field in constructor (5: 0/5/0/0) 107. UwF: Unwritten field (40: 1/39/0/0) 107.1.1. Field only ever set to null (6: 1/5/0/0) 107.1.2. Unwritten field (34: 0/34/0/0) 108. Multithreaded correctness (272: 1/271/0/0) 108.1. DC: Possible double check of field (76: 0/76/0/0) 108.2. Possible double check of field (76: 0/76/0/0) 108.3. IS: Inconsistent synchronization (121: 0/121/0/0) 108.4. Inconsistent synchronization (121: 0/121/0/0) 108.5. LI: Unsynchronized Lazy Initialization (1: 0/1/0/0) 108.6. Incorrect lazy initialization of static field (1: 0/1/0/0) 108.7. ML: Synchronization on updated field (Mutable Lock) (3: 0/3/0/0) 108.8. Method synchronizes on an updated field (3: 0/3/0/0) 108.9. MWN: Mismatched wait() or notify() (1: 0/1/0/0) 108.10. Mismatched wait() (1: 0/1/0/0) 108.11. NN: Naked notify (9: 0/9/0/0) 108.12. Naked notify (9: 0/9/0/0) 108.13. RS: Class's readObject() method is synchronized (9: 0/9/0/0) 108.14. Class's readObject() method is synchronized (9: 0/9/0/0) 108.15. Ru: Method invokes run() (1: 0/1/0/0) 108.16. Invokes run on a thread (did you mean to start it instead?) (1: 0/1/0/0) 108.17. SC: Constructor invokes Thread.start() (4: 0/4/0/0) 108.18. Constructor invokes Thread.start() (4: 0/4/0/0) 108.19. SWL: Sleep with lock held (2: 0/2/0/0) 108.20. Method calls Thread.sleep() with a lock held (2: 0/2/0/0) 108.21. TLW: Wait with two locks held (1: 1/0/0/0) 108.22. Wait with two locks held (1: 1/0/0/0) 108.23. UG: Unsynchronized get method, synchronized set method (25: 0/25/0/0) 108.24. Unsynchronized get method, synchronized set method (25: 0/25/0/0)
  • 71. 315 | P a g e 108.25. UL: Lock not released on all paths (3: 0/3/0/0) 108.26. Method does not release lock on all exception paths (3: 0/3/0/0) 108.27. UW: Unconditional wait (6: 0/6/0/0) 108.28. Unconditional wait (6: 0/6/0/0) 108.29. VO: Use of volatile (2: 0/2/0/0) 108.29.1. A volatile reference to an array doesn't treat the array elements as volatile (2: 0/2/0/0) 108.30. Wa: Wait not in loop (8: 0/8/0/0) 108.31. Wait not in loop (8: 0/8/0/0) 109. Performance (1772: 7/1765/0/0) 109.1. Bx: Questionable Boxing of primitive value (1095: 0/1095/0/0) 109.2. Primitive value is boxed then unboxed to perform primative coercion (1: 0/1/0/0) 109.3. Method invokes inefficient Number constructor; use static valueOf instead (1094: 0/1094/0/0) 109.4. Dm: Dubious method used (153: 7/146/0/0) 109.5. Method invokes inefficient Boolean constructor; use Boolean.valueOf(...) instead (65: 0/65/0/0) 109.6. Explicit garbage collection; extremely dubious except in benchmarking code (1: 1/0/0/0) 109.7. Method invokes inefficient new String(String) constructor (65: 0/65/0/0) 109.8. Method invokes toString() method on a String (11: 0/11/0/0) 109.9. Method invokes inefficient new String() constructor (5: 0/5/0/0) 109.10. The equals and hashCode methods of URL are blocking (6: 6/0/0/0) 109.11. SBSC: String concatenation in loop using + operator (40: 0/40/0/0) 109.12. Method concatenates strings using + in a loop (40: 0/40/0/0) 109.13. SIC: Inner class could be made static (144: 0/144/0/0) 109.14. Should be a static inner class (144: 0/144/0/0) 109.15. SS: Unread field should be static (54: 0/54/0/0) 109.16. Unread field: should this field be static? (54: 0/54/0/0) 109.17. UPM: Private method is never called (19: 0/19/0/0) 109.18. Private method is never called (19: 0/19/0/0) 109.19. UrF: Unread field (216: 0/216/0/0) 109.20. Unread field (216: 0/216/0/0) 109.21. UuF: Unused field (43: 0/43/0/0) 109.22. Unused field (43: 0/43/0/0) 109.23. WMI: Wrong Map Iterator (8: 0/8/0/0) 109.23.1. Inefficient use of keySet iterator instead of entrySet iterator (8: 0/8/0/0) 110. Dodgy (654: 52/602/0/0)
  • 72. 316 | P a g e 110.1. BC: Bad casts of object references (32: 1/31/0/0) 110.2. Unchecked/unconfirmed cast (24: 1/23/0/0) 110.3. instanceof will always return true (8: 0/8/0/0) 110.4. DB: Duplicate Branches (13: 0/13/0/0) 110.5. Method uses the same code for two branches (13: 0/13/0/0) 110.6. DLS: Dead local store (283: 27/256/0/0) 110.7. Dead store to local variable (283: 27/256/0/0) 110.8. DMI: Dubious method invocation (9: 0/9/0/0) 110.9. Code contains a hard coded reference to an absolute pathname (2: 0/2/0/0) 110.10. Non serializable object written to ObjectOutput (3: 0/3/0/0) 110.11. Invocation of substring(0), which returns the original value (4: 0/4/0/0) 110.12. FE: Test for floating point equality (8: 7/1/0/0) 110.13. Test for floating point equality (8: 7/1/0/0) 110.14. IC: Initialization circularity (10: 0/10/0/0) 110.15. Initialization circularity (10: 0/10/0/0) 110.16. ICAST: Casting from integer values (12: 0/12/0/0) 110.17. int division result cast to double or float (8: 0/8/0/0) 110.18. Result of integer multiplication cast to long (3: 0/3/0/0) 110.19. Unsigned right shift cast to short/byte (1: 0/1/0/0) 110.20. IM: Questionable integer math (28: 0/28/0/0) 110.21. Computation of average could overflow (21: 0/21/0/0) 110.22. Check for oddness that won't work for negative numbers (7: 0/7/0/0) 110.23. INT: Suspicious integer expression (1: 0/1/0/0) 110.24. Vacuous comparison of integer value (1: 0/1/0/0) 110.25. NP: Null pointer dereference (52: 0/52/0/0) 110.26. Immediate dereference of the result of readLine() (2: 0/2/0/0) 110.27. Load of known null value (43: 0/43/0/0) 110.28. Possible null pointer dereference due to return value of called method (7: 0/7/0/0) 110.29. RCN: Redundant comparison to null (21: 0/21/0/0) 110.30. Redundant comparison of two null values (2: 0/2/0/0) 110.31. Redundant nullcheck of value known to be non-null (14: 0/14/0/0) 110.32. Redundant nullcheck of value known to be null (5: 0/5/0/0) 110.33. REC: RuntimeException capture (90: 0/90/0/0) 110.34. Exception is caught when Exception is not thrown (90: 0/90/0/0) 110.35. SF: Switch case falls through (51: 3/48/0/0) 110.36. Switch statement found where one case falls through to the next case (51: 3/48/0/0) 110.37. ST: Misuse of static fields (44: 14/30/0/0) 110.38. Write to static field from instance method (44: 14/30/0/0)
  • 73. 317 | P a g e
  • 74. 318 | P a g e OWASP ESASPI 2 http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html svn checkout http://owasp-esapi-java.googlecode.com/svn/trunk/ owasp-esapi-java-read-only ESAPI 2.0.1 API Packages org.owasp.esapi The ESAPI interfaces and Exception classes model the most important security functions to enterprise web applications. org.owasp.esapi.codecs This package contains codecs for application layer encoding/escaping schemes that can be used for both canonicalization and output encoding. org.owasp.esapi.crypto This package contains ESAPI cryptography-related classes used throughout ESAPI. org.owasp.esapi.errors A set of exception classes designed to model the error conditions that frequently arise in enterprise web applications and web services. org.owasp.esapi.filters This package contains several filters that demonstrate ways of using the ESAPI security controls in front of your application. org.owasp.esapi.reference This package contains reference implementations of the ESAPI interfaces. org.owasp.esapi.reference.accesscontrol
  • 75. 319 | P a g e org.owasp.esapi.reference.accesscontrol.policyloader org.owasp.esapi.reference.crypto This package contains the reference implementation for some of the ESAPI cryptography-related classes used throughout ESAPI. org.owasp.esapi.reference.validation This package contains data format- specific validation rule functions. org.owasp.esapi.tags This package contains sample JSP tags that demonstrate how to use the ESAPI functions to protect an application from within a JSP page. org.owasp.esapi.util This package contains ESAPI utility classes used throughout the reference implementation of ESAPI but may also be directly useful. org.owasp.esapi.waf This package contains the ESAPI Web Application Firewall (WAF). org.owasp.esapi.waf.actions This package contains the Action objects that are executed after a Rule subclass executes. org.owasp.esapi.waf.configuration This package contains the both the configuration object model and the utility class to create that object model from an existing policy file. org.owasp.esapi.waf.internal This package contains all HTTP-related classes used internally by the WAF for the implementation of its rules. org.owasp.esapi.waf.rules This package contains all of the Rule subclasses that correspond to policy file
  • 76. 320 | P a g e entries.
  • 77. 321 | P a g e Java & OpenSSO Harden OpenSSO By Disabling ssoadm.jsp Notwithstanding that it is still a secret, we've just added a property that allows you to disable the ssoadm.jsp to harden your system and reduce attack vectors. The property is ssoadm.disabled and can be added with a value of true to the Advanced properties. Log into the OpenSSO console as administrator. Click the Configuration tab. Click the Servers and Sites tab. Click the Server name in the Servers table. Click the Advanced tab. Click Add in the Advanced Properties table. Enter ssoadm.disabled as the Property Name and true as the Property Value. Click Save. You can also add this property as a default setting for future server configurations by clicking the Default Server Settings button under the Servers and Sites tab. Importing the Root CA Certificate for Secure OpenSSO Rainbow Connections When configuring OpenSSO for a scenario that involves a secure connection (SSL or LDAPS) and multiple JVMs, you need to import the root CA certificate into the JVM trust store (by default JAVA_HOME/jre/lib/security/cacerts) and restart the OpenSSO web container before performing any configurations. For example, to configure a second instance of OpenSSO in a defined Site (when the first instance of OpenSSO is SSL-enabled), the root Certificate Authority (CA) certificate for the first OpenSSO server certificate must be imported into the JVM key store of the web container in which the second instance of OpenSSO is deployed. (Restart the web container of the second instance after the import.) An example of a command to import a root CA certificate to this key store is: keytool -import -v -alias alias -keystore JAVA_HOME/jre/lib/security/cacerts -storepass changeit -file CAcert.crt Use the following command to verify that the root CA certificate was imported correctly.
  • 78. 322 | P a g e keytool -list -keystore JAVA_HOME/jre/lib/security/cacerts -storepass changeit RedHat Security JBoss Software & Platform Provider
  • 79. 323 | P a g e
  • 80. 324 | P a g e
  • 81. 325 | P a g e
  • 82. 326 | P a g e
  • 83. 327 | P a g e
  • 84. 328 | P a g e
  • 85. 329 | P a g e
  • 86. 330 | P a g e
  • 87. 331 | P a g e
  • 88. 332 | P a g e
  • 89. 333 | P a g e
  • 90. 334 | P a g e
  • 91. 335 | P a g e JBOSS Security What is JBoss JBoss Application Server (or JBoss AS) is a free software/open-source Java EE-based application server. An important distinction for this class of software is that it not only implements a server that runs on Java, but it actually implements the Java EE part of Java. Because it is Java-based, the JBoss application server operates cross-platform: usable on any operating system that supports Java. JBoss AS was developed by JBoss, now a division of Red Hat. J2EE Security Configuration and Architecture Security is a fundamental part of any enterprise application. You need to be able to restrict who is allowed to access your applications and control what operations application users may perform. The J2EE specifications define a simple role-based security model for EJBs and web components. The JBoss component framework that handles security is the JBossSX extension
  • 92. 336 | P a g e framework. The JBossSX security extension provides support for both the role- based declarative J2EE security model as well as integration of custom security via a security proxy layer. The default implementation of the declarative security model is based on Java Authentication and Authorization Service (JAAS) login modules and subjects. The security proxy layer allows custom security that cannot be described using the declarative model to be added to an EJB in a way that is independent of the EJB business object. Before getting into the JBoss security implementation details, we will revie EJB and Servlet specification security models as well as JAAS to establish the foundation for these details. 8.1. J2EE Declarative Security Overview The security model advocated by the J2EE specification is a declarative model. It is declarative in that you describe the security roles and permissions using a standard XML descriptor rather than embedding security into your business component. This isolates security from business-level code because security tends to be a more a function of where the component is deployed, rather than an inherent aspect of the component's business logic. For example, consider an ATM component that is to be used to access a bank account. The security requirements, roles and permissions will vary independent of how one accesses the bank account based on what bank is managing the account, where the ATM machine is deployed, and so on. Securing a J2EE application is based on the specification of the application security requirements via the standard J2EE deployment descriptors. You secure access to EJBs and web components in an enterprise application by using the ejb-jar.xml and web.xml deployment descriptors. Figure 8.1, “A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.” and Figure 8.2, “A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements.” illustrate the security-related elements in the EJB 2.0 and Servlet 2.2 deployment descriptors, respectively.
  • 93. 337 | P a g e Figure 8.1. A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.
  • 94. 338 | P a g e Figure 8.2. A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements. The purpose and usage of the various security elements given in Figure 8.1, “A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.” and Figure 8.2, “A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements.” is discussed in the following subsections.
  • 95. 339 | P a g e 8.1.1. Security References Both EJBs and servlets may declare one or more security-role-ref elements. This element is used to declare that a component is using the role-name value as an argument to the isCallerInRole(String) method. Using the isCallerInRole method, a component can verify if the caller is in a role that has been declared with a security-role-ref/role-name element. The role-name element value must link to a security-role element through the role-link element. The typical use ofisCallerInRole is to perform a security check that cannot be defined using the role based method- permissions elements. However, use of isCallerInRole is discouraged because this results in security logic embedded inside of the component code. Example descriptor fragments that illustrate the security-role-ref element usage are presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage.” and Example 8.5, “An example web.xml descriptor fragment which illustrate the security-role element usage.”. Example 8.1. An example ejb-jar.xml descriptor fragments which illustrate the security-role-ref element usage. <!-- A sample ejb-jar.xml fragment --> <ejb-jar> <enterprise-beans> <session> <ejb-name>ASessionBean</ejb-name> ... <security-role-ref> <role-name>TheRoleICheck</role-name> <role-link>TheApplicationRole</role-link> </security-role-ref> </session> </enterprise-beans> ... </ejb-jar> Example 8.2. An example web.xml descriptor fragments which illustrate the security-role-ref element usage. <web-app> <servlet> <servlet-name>AServlet</servlet-name> ... <security-role-ref>
  • 96. 340 | P a g e <role-name>TheServletRole</role-name> <role-link>TheApplicationRole</role-link> </security-role-ref> </servlet> ... </web-app> 8.1.2. Security Identity EJBs can optionally declare a security-identity element. New to EJB 2.0 is the capability to specify what identity an EJB should use when it invokes methods on other components. The invocation identity can be that of the current caller, or a specific role. The application assembler uses the security-identity element with a use-caller-identity child element to indicate the current caller's identity should be propagated as the security identity for method invocations made by the EJB. Propagation of the caller's identity is the default used in the absence of an explicit security-identity element declaration. Alternatively, the application assembler can use the run-as/role-name child element to specify that a specific security role given by the role-name value should be used as the security identity for method invocations made by the EJB. Note that this does not change the caller's identity as seen by EJBContext.getCallerPrincipal(). Rather, the caller's security roles are set to the single role specified by the run-as/role-name element value. One use case for the run-as element is to prevent external clients from accessing internal EJBs. This is accomplished by assigning the internal EJB method-permission elements that restrict access to a role never assigned to an external client. EJBs that need to use internal EJB are then configured with a run-as/role-nameequal to the restricted role. An example descriptor fragment that illustrates security- identity element usage is presented in Example 8.3, “An example ejb-jar.xml descriptor fragment which illustrates the security-identity element usage.”. Example 8.3. An example ejb-jar.xml descriptor fragment which illustrates the security-identity element usage. <!-- A sample ejb-jar.xml fragment --> <ejb-jar> <enterprise-beans> <session> <ejb-name>ASessionBean</ejb-name> <!-- ... -->
  • 97. 341 | P a g e <security-identity> <use-caller-identity/> </security-identity> </session> <session> <ejb-name>RunAsBean</ejb-name> <!-- ... --> <security-identity> <run-as> <description>A private internal role</description> <role-name>InternalRole</role-name> </run-as> </security-identity> </session> </enterprise-beans> <!-- ... --> </ejb-jar> 8.1.3. Security roles The security role name referenced by either the security-role-ref or security- identity element needs to map to one of the application's declared roles. An application assembler defines logical security roles by declaring security- role elements. Therole-name value is a logical application role name like Administrator, Architect, SalesManager, etc. What is a role? The J2EE specifications note that it is important to keep in mind that the security roles in the deployment descriptor are used to define the logical security view of an application. Roles defined in the J2EE deployment descriptors should not be confused with the user groups, users, principals, and other concepts that exist in the target enterprise's operational environment. The deployment descriptor roles are application constructs with application domain specific names. For example, a banking application might use role names like BankManager, Teller, and Customer. In JBoss, a security-role is only used to map security-role-ref/role-name values to the logical role that the component role referenced. The user's assigned roles are a dynamic function of the application's security manager, as you will see when we discuss the JBossSX implementation details. JBoss does not require the definition of security-roles in order to declare method permissions. Therefore, the specification of security-role elements is simply a good practice to ensure portability across application servers and for deployment descriptor
  • 98. 342 | P a g e maintenance. Example descriptor fragments that illustrate security-role usage are presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage.”and Example 8.5, “An example web.xml descriptor fragment which illustrate the security-role element usage.”. Example 8.4. An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage. <!-- A sample ejb-jar.xml fragment --> <ejb-jar> <!-- ... --> <assembly-descriptor> <security-role> <description>The single application role</description> <role-name>TheApplicationRole</role-name> </security-role> </assembly-descriptor> </ejb-jar> Example 8.5. An example web.xml descriptor fragment which illustrate the security-role element usage. <!-- A sample web.xml fragment --> <web-app> <!-- ... --> <security-role> <description>The single application role</description> <role-name>TheApplicationRole</role-name> </security-role> </web-app> 8.1.4. EJB method permissions An application assembler can set the roles that are allowed to invoke an EJB's home and remote interface methods through method-permission element declarations. Each method-permission element contains one or more role-name child elements that define the logical roles allowed access the EJB methods as identified by method child elements. As of EJB 2.0, you can now specify an unchecked element instead of the role-name element to declare that any authenticated user can access the methods identified by method child elements. In addition, you can declare that no one should have access to a method with the exclude-list element. If an EJB has methods that have not been
  • 99. 343 | P a g e declared as accessible by a role using a method-permission element, the EJB methods default to being excluded from use. This is equivalent to defaulting the methods into the exclude-list. There are three supported styles of method element declarations.  Style 1 is used for referring to all of the home and component interface methods of the named enterprise bean. <method> <ejb-name>EJBNAME</ejb-name> <method-name>*</method-name> </method>  Style 2 is used for referring to a specified method of the home or component interface of the named enterprise bean. If there are multiple methods with the same overloaded name, this style refers to all of the overloaded methods. <method> <ejb-name>EJBNAME</ejb-name> <method-name>METHOD</method-name> </method>  Style 3 is used to refer to a specified method within a set of methods with an overloaded name. The method must be defined in the specified enterprise bean's home or remote interface. The method-param element values are the fully qualified name of the corresponding method parameter type. If there are multiple methods with the same overloaded signature, the permission applies to all of the matching overloaded methods. <method> <ejb-name>EJBNAME</ejb-name> <method-name>METHOD</method-name> <method-params> <method-param>PARAMETER_1</method-param> <!-- ... --> <method-param>PARAMETER_N</method-param> </method-params> </method>
  • 100. 344 | P a g e The optional method-intf element can be used to differentiate methods with the same name and signature that are defined in both the home and remote interfaces of an enterprise bean. Example 8.6, “An example ejb-jar.xml descriptor fragment which illustrates the method-permission element usage.” provides examples of the method-permission element usage. Example 8.6. An example ejb-jar.xml descriptor fragment which illustrates the method-permission element usage. <ejb-jar> <assembly-descriptor> <method-permission> <description>The employee and temp-employee roles may access any method of the EmployeeService bean </description> <role-name>employee</role-name> <role-name>temp-employee</role-name> <method> <ejb-name>EmployeeService</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <description>The employee role may access the findByPrimaryKey, getEmployeeInfo, and the updateEmployeeInfo(String) method of the AardvarkPayroll bean </description> <role-name>employee</role-name> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>findByPrimaryKey</method-name> </method> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>getEmployeeInfo</method-name> </method> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>updateEmployeeInfo</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </method> </method-permission> <method-permission> <description>The admin role may access any method of the EmployeeServiceAdmin bean </description> <role-name>admin</role-name> <method>
  • 101. 345 | P a g e <ejb-name>EmployeeServiceAdmin</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <description>Any authenticated user may access any method of the EmployeeServiceHelp bean</description> <unchecked/> <method> <ejb-name>EmployeeServiceHelp</ejb-name> <method-name>*</method-name> </method> </method-permission> <exclude-list> <description>No fireTheCTO methods of the EmployeeFiring bean may be used in this deployment</description> <method> <ejb-name>EmployeeFiring</ejb-name> <method-name>fireTheCTO</method-name> </method> </exclude-list> </assembly-descriptor> </ejb-jar> 8.1.5. Web Content Security Constraints In a web application, security is defined by the roles allowed access to content by a URL pattern that identifies the protected content. This set of information is declared using the web.xml security-constraint element. The content to be secured is declared using one or more web-resource-collection elements. Each web-resource- collection element contains an optional series of url-pattern elements followed by an optional series of http-method elements. The url-pattern element value specifies a URL pattern against which a request URL must match for the request to correspond to an attempt to access secured content. The http-method element value specifies a type of HTTP request to allow. The optional user-data-constraint element specifies the requirements for the transport layer of the client to server connection. The requirement may be for content integrity (preventing data tampering in the communication process) or for confidentiality (preventing reading while in transit). The transport- guarantee element value specifies the degree to which communication between client and server should be protected. Its values are NONE, INTEGRAL, or CONFIDENTIAL. A value of NONE means that the application does not require any transport guarantees. A value of INTEGRAL means that the application requires
  • 102. 346 | P a g e the data sent between the client and server be sent in such a way that it can't be changed in transit. A value of CONFIDENTIAL means that the application requires the data be transmitted in a fashion that prevents other entities from observing the contents of the transmission. In most cases, the presence of the INTEGRAL or CONFIDENTIAL flag indicates that the use of SSL is required. The optional login-config is used to configure the authentication method that should be used, the realm name that should be used for this application, and the attributes that are needed by the form login mechanism. The auth- method child element specifies the authentication mechanism for the web application. As a prerequisite to gaining access to any web resources that are protected by an authorization constraint, a user must have authenticated using the configured mechanism. Legal values for auth-method areBASIC, DIGEST, FORM, or CLIENT-CERT. The realm-name child element specifies the realm name to use in HTTP basic and digest authorization. The form-login- config child element specifies the log in as well as error pages that should be used in form-based login. If the auth-method value is not FORM, form-login-config and its child elements are ignored. As an example, the web.xml descriptor fragment given in Example 8.7, “ A web.xml descriptor fragment which illustrates the use of the security- constraint and related elements.” indicates that any URL lying under the web application /restricted path requires an AuthorizedUser role. There is no required transport guarantee and the authentication method used for obtaining the user identity is BASIC HTTP authentication. Example 8.7. A web.xml descriptor fragment which illustrates the use of the security-constraint and related elements. <web-app> <!-- ... --> <security-constraint> <web-resource-collection> <web-resource-name>Secure Content</web-resource-name> <url-pattern>/restricted/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>AuthorizedUser</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee>
  • 103. 347 | P a g e </user-data-constraint> </security-constraint> <!-- ... --> <login-config> <auth-method>BASIC</auth-method> <realm-name>The Restricted Zone</realm-name> </login-config> <!-- ... --> <security-role> <description>The role required to access restricted content </description> <role-name>AuthorizedUser</role-name> </security-role> </web-app> 8.1.6. Enabling Declarative Security in JBoss The J2EE security elements that have been covered describe only the security requirements from the application's perspective. Since J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The J2EE specifications omit these application-server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model using JBoss server specific deployment descriptors. We will avoid discussion the details of this step for now. The details behind the security configuration will be discussed when we describe the generic JBoss server security interfaces in Section 8.3, “The JBoss Security Model”. 8.2. An Introduction to JAAS The default implementation of the JBossSX framework is based on the JAAS API. It is important that you understand the basic elements of the JAAS API to understand the implementation details of JBossSX. This section provides an introduction to JAAS to prepare you for the JBossSX architecture discussion. Additional details on the JAAS package can be found at the JAAS home page at: http://java.sun.com/products/jaas/.
  • 104. 348 | P a g e 8.2.1. What is JAAS? The JAAS 1.0 API consists of a set of Java packages designed for user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with JDK 1.4+. Because the JBossSX framework uses only the authentication capabilities of JAAS to implement the declarative role-based J2EE security model, this introduction focuses on only that topic. Much of this section's material is derived from the JAAS 1.0 Developers Guide, so if you are familiar with its content you can skip ahead to the JBossSX architecture discussion in Section 8.4, “The JBoss Security Extension Architecture” JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can be achieved without changing the JBossSX security manager implementation. All that needs to change is the configuration of the authentication stack that JAAS uses. 8.2.1.1. The JAAS Core Classes The JAAS core classes can be broken down into three categories: common, authentication, and authorization. The following list presents only the common and authentication classes because these are the specific classes used to implement the functionality of JBossSX covered in this chapter. Common classes:  Subject (javax.security.auth.Subject)  Principal (java.security.Principal) Authentication classes:
  • 105. 349 | P a g e  Callback (javax.security.auth.callback.Callback)  CallbackHandler (javax.security.auth.callback.CallbackHandler)  Configuration (javax.security.auth.login.Configuration)  LoginContext (javax.security.auth.login.LoginContext)  LoginModule (javax.security.auth.spi.LoginModule) 8.2.1.1.1. Subject and Principal To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term subject to represent a request's source. The Subject class is the central class in JAAS. A Subject represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 java.security.Principal interface to represent a principal, which is essentially just a typed name. During the authentication process, a subject is populated with associated identities, or principals. A subject may have many principals. For example, a person may have a name principal (John Doe), a social security number principal (123-45-6789), and a username rincipal (johnd), all of which help distinguish the subject from other subjects. To retrieve the principals associated with a swubject, two methods are available: public Set getPrincipals() {...} public Set getPrincipals(Class c) {...} The first method returns all princiaps contained in the subject. The second method only returns those principals that are instances of Class c or one of its subclasses. An empty set will be returned if the subject has no matching principals. Note that thejava.security.acl.Group interface is a subinterface of java.security.Principal, and so an instance in the principals set may represent a logical grouping of other principals or groups of principals. 8.2.1.1.2. Authentication of a Subject Authentication of a subject requires a JAAS login. The login procedure consists of the following steps:
  • 106. 350 | P a g e  An application instantiates a LoginContext passing in the name of the login configuration and a CallbackHandler to populate the Callback objects as required by the configuration LoginModules.  The LoginContext consults a Configuration to load all of the LoginModules included in the named login configuration. If no such named configuration exists the other configuration is used as a default.  The application invokes the LoginContext.login method.  The login method invokes all the loaded LoginModules. As each LoginModule attempts to authenticate the subject, it invokes the handle method on the associated CallbackHandler to obtain the information required for the authentication process. The required information is passed to the handle method in the form of an array of Callback objects. Upon success, the LoginModules associate relevant principals and credentials with the subject.  The LoginContext returns the authentication status to the application. Success is represented by a return from the login method. Failure is represented through a LoginException being thrown by the login method.  If authentication succeeds, the application retrieves the authenticated subject using the LoginContext.getSubject method.  After the scope of the subject authentication is complete, all principals and related information associated with the subject by the login method may be removed by invoking the LoginContext.logout method. The LoginContext class provides the basic methods for authenticating subjects and offers a way to develop an application independent of the underlying authentication technology. The LoginContext consults a Configuration to determine the authentication services configured for a particular application. LoginModule classes represent the authentication services. Therefore, you can plug in different login modules into an application without changing the application itself. Example 8.8, “An illustration of the steps of the authentication process from the application perspective.” provides code fragments that illustrate the steps required by an application to authenticate a subject. Example 8.8. An illustration of the steps of the authentication process from the application perspective.
  • 107. 351 | P a g e CallbackHandler handler = new MyHandler(); LoginContext lc = new LoginContext("some-config", handler); try { lc.login(); Subject subject = lc.getSubject(); } catch(LoginException e) { System.out.println("authentication failed"); e.printStackTrace(); } // Perform work as authenticated Subject // ... // Scope of work complete, logout to remove authentication info try { lc.logout(); } catch(LoginException e) { System.out.println("logout failed"); e.printStackTrace(); } // A sample MyHandler class class MyHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback)callbacks[i]; nc.setName(username); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback)callbacks[i]; pc.setPassword(password); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } } Developers integrate with an authentication technology by creating an implementation of the LoginModule interface. This allows different authentication technologies to be plugged into an application by administrator. Multiple LoginModules can be chained together to allow for more
  • 108. 352 | P a g e than one authentication technology as part of the authentication process. For example, one LoginModule may perform username/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators. The life cycle of a LoginModule is driven by the LoginContext object against which the client creates and issues the login method. The process consists of a two phases. The steps of the process are as follows:  The LoginContext creates each configured LoginModule using its public no- arg constructor.  Each LoginModule is initialized with a call to its initialize method. The Subject argument is guaranteed to be non-null. The signature of the initialize method is: public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options).  The login method is then called to start the authentication process. An example method implementation might prompt the user for a username and password, and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices, or simply extract user information from the underlying operating system. The validation of user identity by each LoginModule is considered phase 1 of JAAS authentication. The signature of the login method is: boolean login() throws LoginException. Failure is indicated by throwing a LoginException. A return of true indicates that the method succeeded, while a return of false indicates that the login module should be ignored.  If the LoginContext's overall authentication succeeds, commit is invoked on each LoginModule. If phase 1 succeeded for a LoginModule, then the commit method continues with phase 2: associating relevant principals, public credentials, and/or private credentials with the subject. If phase 1 fails for a LoginModule, then commit removes any previously stored authentication state, such as usernames or passwords. The signature of the commit method is: boolean commit() throws LoginException. Failure to complete the commit phase is indicated by throwing a LoginException. A return of true indicates that the method succeeded, while a return of false indicates that the login module should be ignored.
  • 109. 353 | P a g e  If the LoginContext's overall authentication failed, then the abort method is invoked on each LoginModule. The abort method removes/destroys any authentication state created by the login or initialize methods. The signature of the abort method is:boolean abort() throws LoginException. Failure to complete the abort phase is indicated by throwing a LoginException. A return of true indicates that the method succeeded, while a return of false indicates that the login module should be ignored.  Removal of the authentication state after a successful login is accomplished when the application invokes logout on the LoginContext. This in turn results in a logout method invocation on each LoginModule. The logout method removes the principals and credentials originally associated with the subject during the commit operation. Credentials should be destroyed upon removal. The signature of the logout method is: boolean logout() throws LoginException. Failure to complete the logout process is indicated by throwing a LoginException. A return of true indicates that the method succeeded, while a return of false indicates that the login module should be ignored. When a LoginModule must communicate with the user to obtain authentication information, it uses a CallbackHandler object. Applications implement the CallbackHandler interface and pass it to the LoginContext, which forwards it directly to the underlying login modules. Login modules use the CallbackHandler both to gather input from users, such as a password or smart- card PIN number, and to supply information to users, such as status information. By allowing the application to specify theCallbackHandler, underlying LoginModules remain independent from the different ways applications interact with users. For example, a CallbackHandler's implementation for a GUI application might display a window to solicit user input. On the other hand, a callbackhandler's implementation for a non-GUI environment, such as an application server, might simply obtain credential information using an application server API. The callbackhandler interface has one method to implement: void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException; The last authentication class to cover is the Callback interface. This is a tagging interface for which several default implementations are provided,
  • 110. 354 | P a g e including NameCallback and PasswordCallback that were used in Example 8.8, “An illustration of the steps of the authentication process from the application perspective.” LoginModule s use a Callback to request information required by the authentication mechanism the LoginModule encapsulates. LoginModule s pass an array of Callback s directly to theCallbackHandler.handle method during the authentication's login phase. If a callbackhandler does not understand how to use a Callback object passed into the handle method, it throws an UnsupportedCallbackException to abort the login call. The JBoss Security Model Similar to the rest of the JBoss architecture, security at the lowest level is defined as a set of interfaces for which alternate implementations may be provided. There are three basic interfaces that define the JBoss server security layer:org.jboss.security.AuthenticationManager, org.jboss.security.RealmMapping, and org.jboss.security.SecurityProxy. Figure 8.3, “The key security model interfaces and their relationship to the JBoss server EJB container elements.”shows a class diagram of the security interfaces and their relationship to the EJB container architecture.
  • 111. 355 | P a g e Figure 8.3. The key security model interfaces and their relationship to the JBoss server EJB container elements. The light blue classes represent the security interfaces while the yellow classes represent the EJB container layer. The two interfaces required for the implementation of the J2EE security model are the org.jboss.security.AuthenticationManager andorg.jboss.security.RealmMapping. The roles of the security interfaces presented in Figure 8.3, “The key security model interfaces and their relationship to the JBoss server EJB container elements.” are summarized in the following list.  AuthenticationManager is an interface responsible for validating credentials associated with principals. Principals are identities and examples
  • 112. 356 | P a g e include usernames, employee numbers, social security numbers, and so on. Credentials are proof of the identity and examples include passwords, session keys, digital signatures, and so on. The isValid method is invoked to see if a user identity and associated credentials as known in the operational environment are valid proof of the user identity.  RealmMapping is an interface responsible for principal mapping and role mapping. The getPrincipal method takes a user identity as known in the operational environment and returns the application domain identity. The doesUserHaveRole method validates that the user identity in the operation environment has been assigned the indicated role from the application domain.  SecurityProxy is an interface describing the requirements for a custom SecurityProxyInterceptor plugin. A SecurityProxy allows for the externalization of custom security checks on a per-method basis for both the EJB home and remote interface methods.  SubjectSecurityManager is a subinterface of AuthenticationManager that simply adds accessor methods for obtaining the security domain name of the security manager and the current thread's authenticated Subject.  SecurityDomain is an extension of the AuthenticationManager, RealmMapping, and SubjectSecurityManager interfaces. It is a move to a comprehensive security interface based on the JAAS Subject, a java.security.KeyStore, and the JSSE com.sun.net.ssl.KeyManagerFactory and com.sun.net.ssl.TrustManagerFactory interfa ces. This interface is still a work in progress that will be the basis of a multi-domain security architecture that will better support ASP style deployments of applications and resources. Note that the AuthenticationManager, RealmMapping and SecurityProxy interfaces have no association to JAAS related classes. Although the JBossSX framework is heavily dependent on JAAS, the basic security interfaces required for implementation of the J2EE security model are not. The JBossSX framework is simply an implementation of the basic security plug-in interfaces that are based on JAAS. The component diagram presented in Figure 8.4, “The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.” illustrates this fact. The implication of this plug-in architecture is that you are free to replace the JAAS-based JBossSX implementation classes with your own custom security manager
  • 113. 357 | P a g e implementation that does not make use of JAAS, if you so desire. You'll see how to do this when you look at the JBossSX MBeans available for the configuration of JBossSX in Figure 8.4, “The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.”. Figure 8.4. The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.
  • 114. 358 | P a g e 8.3.1. Enabling Declarative Security in JBoss Revisited Recall that our discussion of the J2EE standard security model ended with a requirement for the use of JBoss server specific deployment descriptor to enable security. The details of this configuration is presented here, as this is part of the generic JBoss security model. Figure 8.5, “The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.” shows the JBoss-specific EJB and web application deployment descriptor's security-related elements. Figure 8.5. The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.
  • 115. 359 | P a g e The value of a security-domain element specifies the JNDI name of the security manager interface implementation that JBoss uses for the EJB and web containers. This is an object that implements both of the AuthenticationManager and RealmMappinginterfaces. When specified as a top-level element it defines what security domain in effect for all EJBs in the deployment unit. This is the typical usage because mixing security managers within a deployment unit complicates inter-component operation and administration. To specify the security domain for an individual EJB, you specify the security- domain at the container configuration level. This will override any top-level security-domain element. The unauthenticated-principal element specifies the name to use for the Principal object returned by the EJBContext.getUserPrincpal method when an unauthenticated user invokes an EJB. Note that this conveys no special permissions to an unauthenticated caller. Its primary purpose is to allow unsecured servlets and JSP pages to invoke unsecured EJBs and allow the target EJB to obtain a non-null Principal for the caller using the getUserPrincipal method. This is a J2EE specification requirement. The security-proxy element identifies a custom security proxy implementation that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. This may be an implementation of the org.jboss.security.SecurityProxy interface, or just an object that implements methods in the home, remote, local home or local interfaces of the EJB to secure without implementing any common interface. If the given class does not implement the SecurityProxy interface, the instance must be wrapped in a SecurityProxy implementation that delegates the method invocations to the object. The org.jboss.security.SubjectSecurityProxy is an example SecurityProxyimplementation used by the default JBossSX installation. Take a look at a simple example of a custom SecurityProxy in the context of a trivial stateless session bean. The custom SecurityProxy validates that no one invokes the bean's echo method with a four-letter word as its argument. This is a check that is not possible with role-based security; you cannot define a FourLetterEchoInvoker role because the security context is the method argument,
  • 116. 360 | P a g e not a property of the caller. The code for the custom SecurityProxy is given in Example 8.9, “The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint.”, and the full source code is available in the src/main/org/jboss/chap8/ex1 directory of the book examples. The associated jboss.xml descriptor that installs the EchoSecurityProxy as the custom proxy for the EchoBean is given in Example 8.10, “The jboss.xml descriptor which configures the EchoSecurityProxy as the custom security proxy for the EchoBean.”. Example 8.9. The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint. package org.jboss.chap8.ex1; import java.lang.reflect.Method; import javax.ejb.EJBContext; import org.apache.log4j.Category; import org.jboss.security.SecurityProxy; /** A simple example of a custom SecurityProxy implementation * that demonstrates method argument based security checks. * @author Scott.Stark@jboss.org * @version $Revision: 1.15 $ */ public class EchoSecurityProxy implements SecurityProxy { Category log = Category.getInstance(EchoSecurityProxy.class); Method echo; public void init(Class beanHome, Class beanRemote, Object securityMgr) throws InstantiationException { log.debug("init, beanHome="+beanHome + ", beanRemote="+beanRemote + ", securityMgr="+securityMgr); // Get the echo method for equality testing in invoke try { Class[] params = {String.class}; echo = beanRemote.getDeclaredMethod("echo", params); } catch(Exception e) { String msg = "Failed to finde an echo(String) method"; log.error(msg, e); throw new InstantiationException(msg);
  • 117. 361 | P a g e } } public void setEJBContext(EJBContext ctx) { log.debug("setEJBContext, ctx="+ctx); } public void invokeHome(Method m, Object[] args) throws SecurityException { // We don't validate access to home methods } public void invoke(Method m, Object[] args, Object bean) throws SecurityException { log.debug("invoke, m="+m); // Check for the echo method if (m.equals(echo)) { // Validate that the msg arg is not 4 letter word String arg = (String) args[0]; if (arg == null || arg.length() == 4) throw new SecurityException("No 4 letter words"); } // We are not responsible for doing the invoke } } Example 8.10. The jboss.xml descriptor which configures the EchoSecurityProxy as the custom security proxy for the EchoBean. <jboss> <security-domain>java:/jaas/other</security-domain> <enterprise-beans> <session> <ejb-name>EchoBean</ejb-name> <security-proxy>org.jboss.chap8.ex1.EchoSecurityProxy</security-proxy> </session> </enterprise-beans> </jboss> The EchoSecurityProxy checks that the method to be invoked on the bean instance corresponds to the echo(String) method loaded the init method. If there is a match, the method argument is obtained and its length compared against 4 or
  • 118. 362 | P a g e null. Either case results in a SecurityException being thrown. Certainly this is a contrived example, but only in its application. It is a common requirement that applications must perform security checks based on the value of method arguments. The point of the example is to demonstrate how custom security beyond the scope of the standard declarative security model can be introduced independent of the bean implementation. This allows the specification and coding of the security requirements to be delegated to security experts. Since the security proxy layer can be done independent of the bean implementation, security can be changed to match the deployment environment requirements. Now test the custom proxy by running a client that attempts to invoke the EchoBean.echo method with the arguments Hello and Four as illustrated in this fragment: public class ExClient { public static void main(String args[]) throws Exception { Logger log = Logger.getLogger("ExClient"); log.info("Looking up EchoBean"); InitialContext iniCtx = new InitialContext(); Object ref = iniCtx.lookup("EchoBean"); EchoHome home = (EchoHome) ref; Echo echo = home.create(); log.info("Created Echo"); log.info("Echo.echo('Hello') = "+echo.echo("Hello")); log.info("Echo.echo('Four') = "+echo.echo("Four")); } } The first call should succeed, while the second should fail due to the fact that Four is a four-letter word. Run the client as follows using Ant from the examples directory: [nr@toki examples]$ ant -Dchap=chap8 -Dex=1 run-example run-example1: [copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy [echo] Waiting for 5 seconds for deploy... [java] [INFO,ExClient] Looking up EchoBean [java] [INFO,ExClient] Created Echo
  • 119. 363 | P a g e [java] [INFO,ExClient] Echo.echo('Hello') = Hello [java] Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: [java] java.rmi.AccessException: SecurityException; nested exception is: [java] java.lang.SecurityException: No 4 letter words ... [java] at org.jboss.chap8.ex1.ExClient.main(ExClient.java:28) [java] Caused by: java.rmi.AccessException: SecurityException; nested exception is: [java] java.lang.SecurityException: No 4 letter words ... The result is that the echo('Hello') method call succeeds as expected and the echo('Four') method call results in a rather messy looking exception, which is also expected. The above output has been truncated to fit in the book. The key part to the exception is that the SecurityException("No 4 letter words") generated by the EchoSecurityProxy was thrown to abort the attempted method invocation as desired. 8.4. The JBoss Security Extension Architecture The preceding discussion of the general JBoss security layer has stated that the JBossSX security extension framework is an implementation of the security layer interfaces. This is the primary purpose of the JBossSX framework. The details of the implementation are interesting in that it offers a great deal of customization for integration into existing security infrastructures. A security infrastructure can be anything from a database or LDAP server to a sophisticated security software suite. The integration flexibility is achieved using the pluggable authentication model available in the JAAS framework. The heart of the JBossSX framework is org.jboss.security.plugins.JaasSecurityManager. This is the default implementation of the AuthenticationManager and RealmMapping interfaces. Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” shows how the JaasSecurityManager integrates into the EJB and web container layers based on the security-domain element of the corresponding component deployment descriptor.
  • 120. 364 | P a g e Figure 8.6. The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager. Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” depicts an enterprise application that contains both EJBs and web content secured under the security domain jwdomain. The EJB and web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At
  • 121. 365 | P a g e deployment time, the security-domain element value in the jboss.xml and jboss- web.xml descriptors is used to obtain the security manager instance associated with the container. The security interceptor then uses the security manager to perform its role. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container. The JBossSX JaasSecurityManager implementation, shown in Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” as the JaasSecurityMgr component, performs security checks based on the information associated with the Subject instance that results from executing the JAAS login modules configured under the name matching the security-domain element value. We will drill into the JaasSecurityManagerimplementation and its use of JAAS in the following section. 8.4.1. How the JaasSecurityManager Uses JAAS The JaasSecurityManager uses the JAAS packages to implement the AuthenticationManager and RealmMapping interface behavior. In particular, its behavior derives from the execution of the login module instances that are configured under the name that matches the security domain to which the JaasSecurityManager has been assigned. The login modules implement the security domain's principal authentication and role-mapping behavior. Thus, you can use the JaasSecurityManager across different security domains simply by plugging in different login module configurations for the domains. To illustrate the details of the JaasSecurityManager's usage of the JAAS authentication process, you will walk through a client invocation of an EJB home method invocation. The prerequisite setting is that the EJB has been deployed in the JBoss server and its home interface methods have been secured using method-permission elements in the ejb-jar.xml descriptor, and it has been assigned a security domain named jwdomain using the jboss.xml descriptor security-domain element.
  • 122. 366 | P a g e Figure 8.7. An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation. Figure 8.7, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.” provides a view of
  • 123. 367 | P a g e the client to server communication we will discuss. The numbered steps shown are: 1. The client first has to perform a JAAS login to establish the principal and credentials for authentication, and this is labeled Client Side Login in the figure. This is how clients establish their login identities in JBoss. Support for presenting the login information via JNDI InitialContext properties is provided via an alternate configuration. A JAAS login entails creating a LoginContext instance and passing the name of the configuration to use. The configuration name is other. This one-time login associates the login principal and credentials with all subsequent EJB method invocations. Note that the process might not authenticate the user. The nature of the client-side login depends on the login module configuration that the client uses. In this example, theother client-side login configuration entry is set up to use the ClientLoginModule module (an org.jboss.security.ClientLoginModule). This is the default client side module that simply binds the username and password to the JBoss EJB invocation layer for later authentication on the server. The identity of the client is not authenticated on the client. 2. Later, the client obtains the EJB home interface and attempts to create a bean. This event is labeled as Home Method Invocation. This results in a home interface method invocation being sent to the JBoss server. The invocation includes the method arguments passed by the client along with the user identity and credentials from the client-side JAAS login performed in step 1. 3. On the server side, the security interceptor first requires authentication of the user invoking the call, which, as on the client side, involves a JAAS login. 4. The security domain under which the EJB is secured determines the choice of login modules. The security domain name is used as the login configuration entry name passed to the LoginContext constructor. The EJB security domain is jwdomain. If the JAAS login authenticates the user, a JAAS Subject is created that contains the following in its PrincipalsSet:  A java.security.Principal that corresponds to the client identity as known in the deployment security environment.  A java.security.acl.Group named Roles that contains the role names from the application domain to which the user has been
  • 124. 368 | P a g e assigned. org.jboss.security.SimplePrincipal objects are used to represent the role names;SimplePrincipal is a simple string-based implementation of Principal. These roles are used to validate the roles assigned to methods in ejb-jar.xml and the EJBContext.isCallerInRole(String) method implementation.  An optional java.security.acl.Group named CallerPrincipal, which contains a single org.jboss.security.SimplePrincipal that corresponds to the identity of the application domain's caller. The CallerPrincipal sole group member will be the value returned by the EJBContext.getCallerPrincipal() method. The purpose of this mapping is to allow a Principal as known in the operational security environment to map to a Principal with a name known to the application. In the absence of a CallerPrincipal mapping the deployment security environment principal is used as the getCallerPrincipal method value. That is, the operational principal is the same as the application domain principal. 5. The final step of the security interceptor check is to verify that the authenticated user has permission to invoke the requested method This is labeled as Server Side Authorization in Figure 8.7, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.”. Performing the authorization this entails the following steps:  Obtain the names of the roles allowed to access the EJB method from the EJB container. The role names are determined by ejb- jar.xml descriptor role-name elements of all method- permission elements containing the invoked method.  If no roles have been assigned, or the method is specified in an exclude-list element, then access to the method is denied. Otherwise, the doesUserHaveRole method is invoked on the security manager by the security interceptor to see if the caller has one of the assigned role names. This method iterates through the role names and checks if the authenticated user's Subject Roles group contains a SimplePrincipal with the assigned role name. Access is allowed if any role name is a member of the Roles group. Access is denied if none of the role names are members.  If the EJB was configured with a custom security proxy, the method invocation is delegated to it. If the security proxy wants
  • 125. 369 | P a g e to deny access to the caller, it will throw a java.lang.SecurityException. If no SecurityException is thrown, access to the EJB method is allowed and the method invocation passes to the next container interceptor. Note that the SecurityProxyInterceptor handles this check and this interceptor is not shown. Every secured EJB method invocation, or secured web content access, requires the authentication and authorization of the caller because security information is handled as a stateless attribute of the request that must be presented and validated on each request. This can be an expensive operation if the JAAS login involves client-to-server communication. Because of this, the JaasSecurityManager supports the notion of an authentication cache that is used to store principal and credential information from previous successful logins. You can specify the authentication cache instance to use as part of the JaasSecurityManager configuration as you will see when the associated MBean service is discussed in following section. In the absence of any user-defined cache, a default cache that maintains credential information for a configurable period of time is used. 8.4.2. The JaasSecurityManagerService MBean The JaasSecurityManagerService MBean service manages security managers. Although its name begins with Jaas, the security managers it handles need not use JAAS in their implementation. The name arose from the fact that the default security manager implementation is the JaasSecurityManager. The primary role of the JaasSecurityManagerService is to externalize the security manager implementation. You can change the security manager implementation by providing an alternate implementation of theAuthenticationManager and RealmMapping interfaces. Of course this is optional because, by default, the JaasSecurityManager implementation is used. The second fundamental role of the JaasSecurityManagerService is to provide a JNDI javax.naming.spi.ObjectFactory implementation to allow for simple code-free management of the JNDI name to security manager implementation mapping. It has been mentioned that security is enabled by specifying the JNDI name of the security manager implementation via the security-domain deployment descriptor element. When you specify a JNDI name, there has to be an object- binding there to use. To simplify the setup of the JNDI name to security
  • 126. 370 | P a g e manager bindings, the JaasSecurityManagerService manages the association of security manager instances to names by binding a next naming system reference with itself as the JNDI ObjectFactory under the name java:/jaas. This allows one to use a naming convention of the form java:/jaas/XYZ as the value for the security-domain element, and the security manager instance for the XYZ security domain will be created as needed for you. The security manager for the domain XYZ is created on the first lookup against the java:/jaas/XYZ binding by creating an instance of the class specified by the SecurityManagerClassName attribute using a constructor that takes the name of the security domain. For example, consider the following container security configuration snippet: <jboss> <!-- Configure all containers to be secured under the "hades" security domain --> <security-domain>java:/jaas/hades</security-domain> <!-- ... --> </jboss> Any lookup of the name java:/jaas/hades will return a security manager instance that has been associated with the security domain named hades. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the JaasSecurityManagerService SecurityManagerClassName attribute. The JaasSecurityManagerService MBean is configured by default for use in the standard JBoss distribution, and you can often use the default configuration as is. The configurable attributes of the JaasSecurityManagerService include:  SecurityManagerClassName: The name of the class that provides the security manager implementation. The implementation must support both the org.jboss.security.AuthenticationManager and org.jboss.security.RealmMappinginterfa ces. If not specified this defaults to the JAAS- based org.jboss.security.plugins.JaasSecurityManager.  CallbackHandlerClassName: The name of the class that provides the javax.security.auth.callback.CallbackHandler implementation used by the JaasSecurityManager. You can override the handler used by the JaasSecurityManagerif the default implementation (org.jboss.security.auth.callback.SecurityAssociationHandler) does not meet your
  • 127. 371 | P a g e needs. This is a rather deep configuration that generally should not be set unless you know what you are doing.  SecurityProxyFactoryClassName: The name of the class that provides the org.jboss.security.SecurityProxyFactory implementation. If not specified this defaults to org.jboss.security.SubjectSecurityProxyFactory.  AuthenticationCacheJndiName: Specifies the location of the security credential cache policy. This is first treated as an ObjectFactory location capable of returning CachePolicy instances on a per-security-domain basis. This is done by appending the name of the security domain to this name when looking up the CachePolicy for a domain. If this fails, the location is treated as a single CachePolicy for all security domains. As a default, a timed cache policy is used.  DefaultCacheTimeout: Specifies the default timed cache policy timeout in seconds. The default value is 1800 seconds (30 minutes). The value you use for the timeout is a tradeoff between frequent authentication operations and how long credential information may be out of synch with respect to the security information store. If you want to disable caching of security credentials, set this to 0 to force authentication to occur every time. This has no affect if the AuthenticationCacheJndiName has been changed from the default value.  DefaultCacheResolution: Specifies the default timed cache policy resolution in seconds. This controls the interval at which the cache current timestamp is updated and should be less than the DefaultCacheTimeout in order for the timeout to be meaningful. The default resolution is 60 seconds(1 minute). This has no affect if the AuthenticationCacheJndiName has been changed from the default value. The JaasSecurityManagerService also supports a number of useful operations. These include flushing any security domain authentication cache at runtime, getting the list of active users in a security domain authentication cache, and any of the security manager interface methods. Flushing a security domain authentication cache can be used to drop all cached credentials when the underlying store has been updated and you want the store state to be used immediately. The MBean operation signature is: public void flushAuthenticationCache(String securityDomain).
  • 128. 372 | P a g e This can be invoked programmatically using the following code snippet: MBeanServer server = ...; String jaasMgrName = "jboss.security:service=JaasSecurityManager"; ObjectName jaasMgr = new ObjectName(jaasMgrName); Object[] params = {domainName}; String[] signature = {"java.lang.String"}; server.invoke(jaasMgr, "flushAuthenticationCache", params, signature); Getting the list of active users provides a snapshot of the Principals keys in a security domain authentication cache that are not expired. The MBean operation signature is: public List getAuthenticationCachePrincipals(String securityDomain). This can be invoked programmatically using the following code snippet: MBeanServer server = ...; String jaasMgrName = "jboss.security:service=JaasSecurityManager"; ObjectName jaasMgr = new ObjectName(jaasMgrName); Object[] params = {domainName}; String[] signature = {"java.lang.String"}; List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals", params, signature); The security manager has a few additional access methods. public boolean isValid(String securityDomain, Principal principal, Object credential); public Principal getPrincipal(String securityDomain, Principal principal); public boolean doesUserHaveRole(String securityDomain, Principal principal, Object credential, Set roles); public Set getUserRoles(String securityDomain, Principal principal, Object credential); They provide access to the corresponding AuthenticationManager and RealmMapping interface method of the associated security domain named by the securityDomain argument. 8.4.3. The JaasSecurityDomain MBean The org.jboss.security.plugins.JaasSecurityDomain is an extension of JaasSecurityManager that adds the notion of a KeyStore, aJSSE KeyManagerFactory and a TrustManagerFactory for supporting SSL and other cryptographic use cases. The additional configurable attributes of the JaasSecurityDomain include: JKS
  • 129. 373 | P a g e  KeyStoreType: The type of the KeyStore implementation. This is the type argument passed to the java.security.KeyStore.getInstance(String type) factory method.  KeyStoreURL: A URL to the location of the KeyStore database. This is used to obtain an InputStream to initialize the KeyStore. If the string is not a value URL, it iss treated as a file.  KeyStorePass: The password associated with the KeyStore database contents. The KeyStorePass is also used in combination with the Salt and IterationCount attributes to create a PBE secret key used with the encode/decode operations. TheKeyStorePass attribute value format is one of the following: o The plaintext password for the KeyStore The toCharArray() value of the string is used without any manipulation. o A command to execute to obtain the plaintext password. The format is {EXT}... where the ... is the exact command line that will be passed to the Runtime.exec(String) method to execute a platform- specific command. The first line of the command output is used as the password. o A class to create to obtain the plaintext password. The format is {CLASS}classname[:ctorarg] where the [:ctorarg] is an optional string that will be passed to the constructor when instantiating the the classname. The password is obtained from classname by invoking a toCharArray() method if found, otherwise, the toString() method is used.  Salt: The PBEParameterSpec salt value.  IterationCount: The PBEParameterSpec iteration count value.  ManagerServiceName: Sets the JMX object name string of the security manager service MBean. This is used to register the defaults to register the JaasSecurityDomain as a the security manager under java:/jaas/<domain> where <domain> is the name passed to the MBean constructor. The name defaults to jboss.security:service=JaasSecurityManager.  LoadSunJSSEProvider: A flag indicating if the Sun com.sun.net.ssl.internal.ssl.Provider security provider should be loaded on startup. This is needed when using the Sun JSSE jars without them installed as an extension with JDK 1.3. This should be set to false with JDK 1.4 or when using an alternate JSSE provider. This flag currently defaults to true.
  • 130. 374 | P a g e 8.4.4. An XML JAAS Login Configuration MBean JBoss uses a custom implementation of the javax.security.auth.login.Configuration class that is provided by the org.jboss.security.auth.login.XMLLoginConfig MBean. This configuration implementation uses an XML format that conforms to the DTD given by Figure 8.8, “The XMLLoginConfig DTD”. Figure 8.8. The XMLLoginConfig DTD The name attribute of the application-policy is the login configuration name. This corresponds to the portion of the jboss.xml and jboss-web.xml security- domain element value after the java:/jaas/ prefix. The code attribute of the login- moduleelement specifies the class name of the login module implementation. The flag attribute controls the overall behavior of the authentication stack. The allowed values and measnings are:  required: the LoginModule is required to succeed. If it succeeds or fails, authentication still continues to proceed down the LoginModule list.  requisite: the LoginModule is required to succeed. If it succeeds, authentication continues down the LoginModule list. If it fails, control immediately returns to the application (authentication does not proceed down the LoginModule list).  sufficient: the LoginModule is not required to succeed. If it does succeed, control immediately returns to the application (authentication does not proceed down the LoginModule list). If it fails, authentication continues down the LoginModule list.
  • 131. 375 | P a g e  optional: the LoginModule is not required to succeed. If it succeeds or fails, authentication still continues to proceed down the LoginModule list. Zero or more module-option elements may be specified as child elements of a login-module. These define name/value string pairs that are made available to the login module during initialization. The name attribute specifies the option name while themodule-option body provides the value. An example login configuration is given in Example 8.11, “A sample login module configuration suitable for use with XMLLoginConfig”. Example 8.11. A sample login module configuration suitable for use with XMLLoginConfig <policy> <application-policy name="srp-test"> <authentication> <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule" flag="required"> <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> </login-module> </authentication> </application-policy> </policy> The XMLLoginConfig MBean supports the following attributes:  ConfigURL: specifies the URL of the XML login configuration file that should be loaded by this MBean on startup. This must be a valid URL string representation.  ConfigResource: specifies the resource name of the XML login configuration file that should be loaded by this MBean on startup. The name is treated as a classpath resource for which a URL is located using the thread context class loader.  ValidateDTD: a flag indicating if the XML configuration should be validated against its DTD. This defaults to true.
  • 132. 376 | P a g e The MBean also supports the following operations that allow one to dynamically extend the login configurations at runtime. Note that any operation that attempts to alter login configuration requires ajavax.security.auth.AuthPermission("refreshLoginConfiguration") when running with a security manager. The org.jboss.chap8.service.SecurityConfig service demonstrates how this can be used to add/remove a deployment specific scurity configuration dynamically.  void addAppConfig(String appName, AppConfigurationEntry[] entries): this adds the given login module configuration stack to the current configuration under the given appName. This replaces any existing entry under that name.  void removeAppConfig(String appName): this removes the login module configuration registered under the given appName.  String[] loadConfig(URL configURL) throws Exception: this loads one or more login configurations from a URL representing either an XML or legacy Sun login configuration file. Note that all login configurations must be added or none will be added. It returns the names of the login configurations that were added.  void removeConfigs(String[] appNames): this removes the login configurations specified appNames array.  String displayAppConfig(String appName): this operation displays a simple string format of the named configuration if it exists. 8.4.5. The JAAS Login Configuration Management MBean The installation of the custom javax.security.auth.login.Configuration is managed by the org.jboss.security.plugins.SecurityConfig MBean. There is one configurable attribute:  LoginConfig: Specifies the JMX ObjectName string of the that provides the default JAAS login configuration. When the SecurityConfig is started, this mean is queried for its javax.security.auth.login.Configuration by calling itsgetConfiguration(Configuration currentConfig) operation. If the LoginConfig attribute is not specified then the default Sun Configuration implementation described in the Configuration class JavaDocs is used. In addition to allowing for a custom JAAS login configuration implementation, this service allows configurations to be chained together in a stack at runtime.
  • 133. 377 | P a g e This allows one to push a login configuration onto the stack and latter pop it. This is a feature used by the security unit tests to install custom login configurations into a default JBoss installation. Pusing a new configuration is done using: public void pushLoginConfig(String objectName) throws JMException, MalformedObjectNameException; The objectName parameters specifies an MBean similar to the LoginConfig attribute. The current login configuration may be removed using: public void popLoginConfig() throws JMException; 8.4.6. Using and Writing JBossSX Login Modules The JaasSecurityManager implementation allows complete customization of the authentication mechanism using JAAS login module configurations. By defining the login module configuration entry that corresponds to the security domain name you have used to secure access to your J2EE components, you define the authentication mechanism and integration implementation. The JBossSX framework includes a number of bundled login modules suitable for integration with standard security infrastructure store protocols such as LDAP and JDBC. It also includes standard base class implementations that help enforce the expectedLoginModule to Subject usage pattern that was described in theSection 8.4.7, “Writing Custom Login Modules”. These implementations allow for easy integration of your own authentication protocol, if none of the bundled login modules prove suitable. In this section we will first describe the useful bundled login modules and their configuration, and then end with a discussion of how to create your own custom LoginModule implementations for use with JBoss. 8.4.6.1. org.jboss.security.auth.spi.IdentityLoginModule The IdentityLoginModule is a simple login module that associates the principal specified in the module options with any subject authenticated against the module. It creates a SimplePrincipal instance using the name specified by the principal option. Although this is certainly not an appropriate login module for production strength authentication, it can be of use in development
  • 134. 378 | P a g e environments when you want to test the security associated with a given principal and associated roles. The supported login module configuration options include:  principal=string: The name to use for the SimplePrincipal all users are authenticated as. The principal name defaults to guest if no principal option is specified.  roles=string-list: The names of the roles that will be assigned to the user principal. The value is a comma-delimited list of role names.  password-stacking=useFirstPass: When password-stacking option is set, this module first looks for a shared username under the property name javax.security.auth.login.name in the login module shared state map. If found this is used as the principal name. If not found the principal name set by this login module is stored under the property name javax.security.auth.login.name. A sample legacy Sun format login configuration entry that would authenticate all users as the principal named jduke and assign role names of TheDuke, and AnimatedCharacter is: testIdentity { org.jboss.security.auth.spi.IdentityLoginModule required principal=jduke roles=TheDuke,AnimatedCharater; }; The corresponding XMLLoginConfig format is: <policy> <application-policy name="testIdentity"> <authentication> <login-module code="org.jboss.security.auth.spi.IdentityLoginModule" flag="required"> <module-option name="principal">jduke</module-option> <module-option name="roles">TheDuke,AnimatedCharater</module-option> </login-module> </authentication> </application-policy> </policy>
  • 135. 379 | P a g e To add this entry to a JBoss server login cofiguration found in the default configuration file set you would modify the conf/default/auth.conf file of the JBoss distribution. 8.4.6.2. org.jboss.security.auth.spi.UsersRolesLoginModule The UsersRolesLoginModule is another simple login module that supports multiple users and user roles, and is based on two Java Properties formatted text files. The username-to-password mapping file is called users.properties and the username-to-roles mapping file is called roles.properties. The properties files are loaded during initialization using the initialize method thread context class loader. This means that these files can be placed into the J2EE deployment JAR, the JBoss configuration directory, or any directory on the JBoss server or system classpath. The primary purpose of this login module is to easily test the security settings of multiple users and roles using properties files deployed with the application. The users.properties file uses a username=password format with each user entry on a separate line as show here: username1=password1 username2=password2 ... The roles.properties file uses as username=role1,role2,... format with an optional group name value. For example: username1=role1,role2,... username1.RoleGroup1=role3,role4,... username2=role1,role3,... The username.XXX form of property name is used to assign the username roles to a particular named group of roles where the XXX portion of the property name is the group name. The username=... form is an abbreviation for username.Roles=..., where the Roles group name is the standard name the JaasSecurityManager expects to contain the roles which define the users permissions. The following would be equivalent definitions for the jduke username: jduke=TheDuke,AnimatedCharacter
  • 136. 380 | P a g e jduke.Roles=TheDuke,AnimatedCharacter The supported login module configuration options include the following:  unauthenticatedIdentity=name: Defines the principal name that should be assigned to requests that contain no authentication information. This can be used to allow unprotected servlets to invoke methods on EJBs that do not require a specific role. Such a principal has no associated roles and so can only access either unsecured EJBs or EJB methods that are associated with the unchecked permission constraint.  password-stacking=useFirstPass: When password-stacking option is set, this module first looks for a shared username and password under the property names javax.security.auth.login.name and javax.security.auth.login.passwordrespectivel y in the login module shared state map. If found these are used as the principal name and password. If not found the principal name and password are set by this login module and stored under the property namesjavax.security.auth.login.name and javax.security.auth.login.password respectivel y.  hashAlgorithm=string: The name of the java.security.MessageDigest algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. When hashAlgorithm is specified, the clear text password obtained from the callbackhandler is hashed before it is passed to UsernamePasswordLoginModule.validatePassword as the inputPassword argument. The expectedPassword as stored in the users.properties file must be comparably hashed.  hashEncoding=base64|hex: The string format for the hashed pass and must be either base64 or hex. Base64 is the default.  hashCharset=string: The encoding used to convert the clear text password to a byte array. The platform default encoding is the default.  usersProperties=string: The name of the properties resource containing the username to password mappings. This defaults to users.properties.  rolesProperties=string: The name of the properties resource containing the username to roles mappings. This defaults to roles.properties. A sample legacy Sun format login configuration entry that assigned unauthenticated users the principal name nobody and contains based64 encoded, MD5 hashes of the passwords in a usersb64.properties file is:
  • 137. 381 | P a g e testUsersRoles { org.jboss.security.auth.spi.UsersRolesLoginModule required usersProperties=usersb64.properties hashAlgorithm=MD5 hashEncoding=base64 unauthenticatedIdentity=nobody ; }; The corresponding XMLLoginConfig format is: <policy> <application-policy name="testUsersRoles"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">usersb64.properties</module-option> <module-option name="hashAlgorithm">MD5</module-option> <module-option name="hashEncoding">base64</module-option> <module-option name="unauthenticatedIdentity">nobody</module-option> </login-module> </authentication> </application-policy> </policy> 8.4.6.3. org.jboss.security.auth.spi.LdapLoginModule The LdapLoginModule is a LoginModule implementation that authenticates against an LDAP server using JNDI login using the login module configuration options. You would use the LdapLoginModule if your username and credential information are store in an LDAP server that is accessible using a JNDI LDAP provider. The LDAP connectivity information is provided as configuration options that are passed through to the environment object used to create JNDI initial context. The standard LDAP JNDI properties used include the following:  java.naming.factory.initial: The classname of the InitialContextFactory implementation. This defaults to the Sun LDAP provider implementation com.sun.jndi.ldap.LdapCtxFactory.  java.naming.provider.url: The LDAP URL for the LDAP server  java.naming.security.authentication: The security level to use. This defaults to simple.  java.naming.security.protocol: The transport protocol to use for secure access, such as, ssl.
  • 138. 382 | P a g e  java.naming.security.principal: The principal for authenticating the caller to the service. This is built from other properties as described below.  java.naming.security.credentials: The value of the property depends on the authentication scheme. For example, it could be a hashed password, clear-text password, key, certificate, and so on. The supported login module configuration options include the following:  principalDNPrefix=string: A prefix to add to the username to form the user distinguished name. See principalDNSuffix for more info.  principalDNSuffix=string: A suffix to add to the username when forming the user distiguished name. This is useful if you prompt a user for a username and you don't want the user to have to enter the fully distinguished name. Using this property andprincipalDNSuffix the userDN will be formed as: String userDN = principalDNPrefix + username + principalDNSuffix;  useObjectCredential=true|false: Indicates that the credential should be obtained as an opaque Object using the org.jboss.security.auth.callback.ObjectCallback type of Callback rather than as a char[] password using a JAASPasswordCallback. This allows for passing non- char[] credential information to the LDAP server.  rolesCtxDN=string: The fixed distinguished name to the context to search for user roles.  userRolesCtxDNAttributeName=string: The name of an attribute in the user object that contains the distinguished name to the context to search for user roles. This differs from rolesCtxDN in that the context to search for a user's roles can be unique for each user.  roleAttributeID=string: The name of the attribute that contains the user roles. If not specified this defaults to roles.  roleAttributeIsDN=string: A flag indicating whether the roleAttributeID contains the fully distinguished name of a role object, or the role name. If false, the role name is taken from the value of roleAttributeID. If true, the role attribute represents the distinguished name of a role object. The role name is taken from the value of the roleNameAttributeId attribute of the context name by the distinguished
  • 139. 383 | P a g e name. In certain directory schemas (e.g., MS ActiveDirectory), role attributes in the user object are stored as DNs to role objects instead of as simple names, in which case, this property should be set to true. The default is false.  roleNameAttributeID=string: The name of the attribute of the in the context pointed to by the roleCtxDN distiguished name value which contains the role name. If the roleAttributeIsDN property is set to true, this property is used to find the role object's name attribute. The default is group.  uidAttributeID=string: The name of the attribute in the object containing the user roles that corresponds to the userid. This is used to locate the user roles. If not specified this defaults to uid.  matchOnUserDN=true|false: A flag indicating if the search for user roles should match on the user's fully distinguished name. If false, just the username is used as the match value against the uidAttributeName attribute. If true, the full userDN is used as the match value.  unauthenticatedIdentity=string: The principal name that should be assigned to requests that contain no authentication information. This behavior is inherited from the UsernamePasswordLoginModule superclass.  password-stacking=useFirstPass: When the password-stacking option is set, this module first looks for a shared username and password under the property names javax.security.auth.login.name andjavax.security.auth.login.password respectivel y in the login module shared state map. If found these are used as the principal name and password. If not found the principal name and password are set by this login module and stored under the property names javax.security.auth.login.name and javax.security.auth.login.password respectivel y.  hashAlgorithm=string: The name of the java.security.MessageDigest algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. When hashAlgorithm is specified, the clear text password obtained from the callbackhandler is hashed before it is passed to UsernamePasswordLoginModule.validatePassword as the inputPassword argument. The expectedPassword as stored in the LDAP server must be comparably hashed.
  • 140. 384 | P a g e  hashEncoding=base64|hex: The string format for the hashed pass and must be either base64 or hex. Base64 is the default.  hashCharset=string: The encoding used to convert the clear text password to a byte array. The platform default encoding is the default.  allowEmptyPasswords: A flag indicating if empty (length 0) passwords should be passed to the LDAP server. An empty password is treated as an anonymous login by some LDAP servers and this may not be a desirable feature. Set this to false to reject empty passwords, true to have the LDAP server validate the empty password. The default is true. The authentication of a user is performed by connecting to the LDAP server based on the login module configuration options. Connecting to the LDAP server is done by creating an InitialLdapContext with an environment composed of the LDAP JNDI properties described previously in this section. The Context.SECURITY_PRINCIPAL is set to the distinguished name of the user as obtained by the callback handler in combination with the principalDNPrefix and principalDNSuffix option values, and the Context.SECURITY_CREDENTIALS property is either set to the String password or the Object credential depending on the useObjectCredential option. Once authentication has succeeded by virtue of being able to create an InitialLdapContext instance, the user's roles are queried by performing a search on the rolesCtxDN location with search attributes set to the roleAttributeName anduidAttributeName option values. The roles names are obtaining by invoking the toString method on the role attributes in the search result set. A sample Sun legacy format login configuration entry is: testLdap { org.jboss.security.auth.spi.LdapLoginModule required java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url="ldap://ldaphost.jboss.org:1389/" java.naming.security.authentication=simple principalDNPrefix=uid= uidAttributeID=userid roleAttributeID=roleName principalDNSuffix=,ou=People,o=jboss.org rolesCtxDN=cn=JBossSX Tests,ou=Roles,o=jboss.org };
  • 141. 385 | P a g e The corresponding XMLLoginConfig format is: <policy> <application-policy name="testLdap"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required"> <module-option name="java.naming.factory.initial"> com.sun.jndi.ldap.LdapCtxFactory </module-option> <module-option name="java.naming.provider.url"> ldap://ldaphost.jboss.org:1389/ </module-option> <module-option name="java.naming.security.authentication"> simple </module-option> <module-option name="principalDNPrefix">uid=</module-option> <module-option name="uidAttributeID">userid</module-option> <module-option name="roleAttributeID">roleName</module-option> <module-option name="principalDNSuffix">,ou=People,o=jboss.org </module-option> <module-option name="rolesCtxDN">cn=JBossSX Tests,ou=Roles,o=jboss.org </module-option> </login-module> </authentication> </application-policy> </policy> To help you understand all of the options of the LdapLoginModule, consider the sample LDAP server data shown in Figure 8.9, “An LDAP server configuration compatible with the testLdap sample configuration.”. This figure corresponds to the testLdaplogin configuration just shown.
  • 142. 386 | P a g e Figure 8.9. An LDAP server configuration compatible with the testLdap sample configuration. Take a look at the testLdap login module configuration in comparision to the Figure 8.9, “An LDAP server configuration compatible with the testLdap sample configuration.” schema. The java.naming.factory.initial, java.naming.factory.url andjava.naming.security options indicate the Sun LDAP JNDI provider implementation will be used, the LDAP server is located on host ldaphost.jboss.org on port 1389, and that simple username and password will be used to authenticate clients connecting to the LDAP server. When the LdapLoginModule performs authentication of a user, it does so by connecting to the LDAP server specified by the java.naming.factory.url. The java.naming.security.principal property is built from the principalDNPrefix, passed in username and principalDNSuffix as described above. For the testLdap configuration example and a username of jduke, the java.naming.security.principal string would be uid=jduke,ou=People,o=jboss.org. This corresponds to the LDAP context on the lower right of Figure 8.9, “An LDAP server configuration compatible with the testLdap sample configuration.” labeled as Principal Context. The java.naming.security.credentials property would be set to the passed in password and it would have to match the userPassword attribute of the principal context. How a secured LDAP context stores the authentication credential information
  • 143. 387 | P a g e depends on the LDAP server, so your LDAP server may handle the validation of thejava.naming.security.credentials property differently. Once authentication succeeds, the roles on which authorization will be based are retrieved by performing a JNDI search of the LDAP context whose distinguished name is given by the rolesCtxDN option value. For the testLdap configuration this iscn=JBossSX Tests,ou=Roles,o=jboss.org and corresponds to the LDAP context on the lower left of Figure 8.9, “An LDAP server configuration compatible with the testLdap sample configuration.” labeled Roles Context. The search attempts to locate any subcontexts that contain an attribute whose name is given by the uidAttributeID option, and whose value matches the username passed to the login module. For any matching context, all values of the attribute whose name is given by theroleAttributeID option are obtained. For the testLdap configuration the attribute name that contains the roles is called roleName. The resulting roleName values are stored in the JAAS Subject associated with the LdapLoginModule as the Roles group principals that will be used for role-based authorization. For the LDAP schema shown in Figure 8.9, “An LDAP server configuration compatible with the testLdap sample configuration.”, the roles that will be assigned to the user jduke are TheDuke andAnimatedCharacter. 8.4.6.4. org.jboss.security.auth.spi.DatabaseServerLoginModule The DatabaseServerLoginModule is a JDBC based login module that supports authentication and role mapping. You would use this login module if you have your username, password and role information in a JDBC accessible database. TheDatabaseServerLoginModule is based on two logical tables: Table Principals(PrincipalID text, Password text) Table Roles(PrincipalID text, Role text, RoleGroup text) The Principals table associates the user PrincipalID with the valid password and the Roles table associates the user PrincipalID with its role sets. The roles used for user permissions must be contained in rows with a RoleGroup column value ofRoles. The tables are logical in that you can specify the SQL query that the login module uses. All that is required is that the java.sql.ResultSet has the same logical structure as the Principals and Roles tables described previously. The actual
  • 144. 388 | P a g e names of the tables and columns are not relevant as the results are accessed based on the column index. To clarify this notion, consider a database with two tables, Principals and Roles, as already declared. The following statements build the tables to contain aPrincipalID java with a Password of echoman in the Principals table, a PrincipalID java with a role named Echo in the Roles RoleGroup in the Roles table, and a PrincipalID java with a role named caller_java in the CallerPrincipalRoleGroup in the Roles table: INSERT INTO Principals VALUES('java', 'echoman') INSERT INTO Roles VALUES('java', 'Echo', 'Roles') INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal') The supported login module configuration options include the following:  dsJndiName: The JNDI name for the DataSource of the database containing the logical Principals and Roles tables. If not specified this defaults to java:/DefaultDS.  principalsQuery: The prepared statement query equivalent to: select Password from Principals where PrincipalID=?. If not specified this is the exact prepared statement that will be used.  rolesQuery: The prepared statement query equivalent to: select Role, RoleGroup from Roles where PrincipalID=?. If not specified this is the exact prepared statement that will be used.  unauthenticatedIdentity=string: The principal name that should be assigned to requests that contain no authentication information.  password-stacking=useFirstPass: When password-stacking option is set, this module first looks for a shared username and password under the property names javax.security.auth.login.name andjavax.security.auth.login.password respectivel y in the login module shared state map. If found these are used as the principal name and password. If not found the principal name and password are set by this login module and stored under the property names javax.security.auth.login.name and javax.security.auth.login.password respectivel y.  hashAlgorithm=string: The name of the java.security.MessageDigest algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. When hashAlgorithm is specified, the clear text password obtained from the callbackhandler is hashed before it is passed
  • 145. 389 | P a g e to UsernamePasswordLoginModule.validatePassword as the inputPassword argument. The expectedPassword as obtained from the database must be comparably hashed.  hashEncoding=base64|hex: The string format for the hashed pass and must be either base64 or hex. Base64 is the default.  hashCharset=string: The encoding used to convert the clear text password to a byte array. The platform default encoding is the default  ignorePasswordCase=true|false: A boolean flag indicating if the password comparison should ignore case. This can be useful for hashed password encoding where the case of the hashed password is not significant.  principalClass: An option that specifies a Principal implementation class. This must support a constructor taking a string argument for the princpal name. As an example DatabaseServerLoginModule configuration, consider a custom table schema like the following: CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64)) CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32)) A sample Sun legacy format corresponding DatabaseServerLoginModule configuration would be: testDB { org.jboss.security.auth.spi.DatabaseServerLoginModule required dsJndiName="java:/MyDatabaseDS" principalsQuery="select passwd from Users username where username=?" rolesQuery="select userRoles, 'Roles' from UserRoles where username=?" ; }; The corresponding XMLLoginConfig format is: <policy> <application-policy name="testDB"> <authentication> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="dsJndiName">java:/MyDatabaseDS</module-option> <module-option name="principalsQuery"> select passwd from Users username where username=?</module-option> <module-option name="rolesQuery">
  • 146. 390 | P a g e select userRoles, 'Roles' from UserRoles where username=?</module-option> </login-module> </authentication> </application-policy> </policy> 8.4.6.5. BaseCertLoginModule This is a login module which authenticates users based on X509 certificates. A typical usecase for this login module is CLIENT-CERT authentication in the web tier. This login module only performs authentication. You need to combine it with another login module capable of acquiring the authorization roles to completely define access to a secured web or EJB component. Two subclasses of this login module, CertRolesLoginModule and DatabaseCertLoginModule extend the behavior to obtain the authorization roles from either a properties file or database. The BaseCertLoginModule needs a KeyStore to perform user validation. This is obtained through a org.jboss.security.SecurityDomain implementation. Typically, the SecurityDomain implementation is configured using theorg.jboss.security.plugins.JaasSecurityDomain MBean as shown in this jboss-service.xml configuration fragment: <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.web:service=SecurityDomain"> <constructor> <arg type="java.lang.String" value="jmx-console"/> </constructor> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">unit-tests-server</attribute> </mbean> This creates a security domain with the name jmx- console whose SecurityDomain implementation is available via JNDI under the name java:/jaas/jmx-console following the JBossSX security domain naming pattern. To secure a web application such as thejmx-console.war using client certs and role based authorization, one would first modify the web.xml to declare the resources to be secured, along with the allowed roles and security domain to be used for authentication and authorization. <?xml version="1.0"?>
  • 147. 391 | P a g e <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> ... <security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description>An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>JBoss JMX Console</realm-name> </login-config> <security-role> <role-name>JBossAdmin</role-name> </security-role> </web-app> Next we, need to specify the JBoss security domain in jboss-web.xml: <jboss-web> <security-domain>java:/jaas/jmx-console</security-domain> </jboss-web> Finally, you need to define the login module configuration for the jmx-console security domain you just specified. This is done in the conf/login-config.xml file. <application-policy name="jmx-console"> <authentication> <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="securityDomain">java:/jaas/jmx-console</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="usersProperties">jmx-console-users.properties</module-option>
  • 148. 392 | P a g e <module-option name="rolesProperties">jmx-console-roles.properties</module-option> </login-module> </authentication> </application-policy> Here the BaseCertLoginModule is used for authentication of the client cert, and the UsersRolesLoginModule is only used for authorization due to the password- stacking=useFirstPass option. Both the localhost.keystore and the jmx-console- roles.properties need an entry that maps to the principal associated with the client cert. By default, the principal is created using the client certificate distinguished name. Consider the following certificate: [starksm@banshee9100 conf]$ keytool -printcert -file unit-tests-client.export Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin @jboss.com, OU=QA, O=JBoss Inc. Serial number: 100103 Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005 Certificate fingerprints: MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58 The localhost.keystore would need this cert stored with an alias of CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US and the jmx-console-roles.properties would also need an entry for the same entry. Since the DN contains many characters that are normally treated as delimiters, you will need to escape the problem characters using a backslash ('') as shown here: # A sample roles.properties file for use with the UsersRolesLoginModule CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US=JBossAdmin admin=JBossAdmin 8.4.6.6. org.jboss.security.auth.spi.ProxyLoginModule The ProxyLoginModule is a login module that loads a delegate LoginModule using the current thread context class loader. The purpose of this module is to work around the current JAAS 1.0 class loader limitation that requires LoginModules to be on the system classpath[2] . Some custom LoginModules use classes that are loaded from the JBoss server lib/ext directory and these are not available if the LoginModule is placed on the system classpath. To work around this limitation you use theProxyLoginModule to bootstrap the custom LoginModule. The ProxyLoginModule has one required configuration option called moduleName. It
  • 149. 393 | P a g e specifies the fully qualified class name of the LoginModule implementation that is to be bootstrapped. Any number of additional configuration options may be specified, and they will be passed to the bootstrapped login module. As an example, consider a custom login module that makes use of some service that is loaded from the JBoss lib/ext directory. The class name of the custom login module is com.biz.CustomServiceLoginModule. A suitable Sun legacy formatProxyLoginModule configuration entry for bootstrapping this custom login module would be: testProxy { org.jboss.security.auth.spi.ProxyLoginModule required moduleName=com.biz.CustomServiceLoginModule customOption1=value1 customOption2=value2 customOption3=value3; }; The corresponding XMLLoginConfig format is: <policy> <application-policy name="testProxy"> <authentication> <login-module code="org.jboss.security.auth.spi.ProxyLoginModule" flag="required"> <module-option name="moduleName"> com.biz.CustomServiceLoginModule </module-option> <module-option name="customOption1">value1</module-option> <module-option name="customOption2">value2</module-option> <module-option name="customOption3">value3</module-option> </login-module> </authentication> </application-policy> </policy> 8.4.6.7. org.jboss.security.auth.spi.RunAsLoginModule JBoss has a helper login module called RunAsLoginModule that pushes a run as role for the duration of the login phase of authentication, and pops the run as role in either the commit or abort phase. The purpose of this login module is to provide a role for other login modules that need to access secured resources in order to perform their authentication. An example would be a login module
  • 150. 394 | P a g e that accesses an secured EJB. This login module must be configured ahead of the login module(s) that need a run as role established. The only login module configuration option is:  roleName: the name of the role to use as the run as role during login phase. If not specified a default of nobody is used. 8.4.6.8. org.jboss.security.ClientLoginModule The ClientLoginModule is an implementation of LoginModule for use by JBoss clients for the establishment of the caller identity and credentials. This simply sets the org.jboss.security.SecurityAssociation.principal to the value of theNameCallback filled in by the callbackhandler, and the org.jboss.security.SecurityAssociation.credential to the value of the PasswordCallback filled in by the callbackhandler. This is the only supported mechanism for a client to establish the current thread's caller. Both stand- alone client applications and server environments, acting as JBoss EJB clients where the security environment has not been configured to use JBossSX transparently, need to use the ClientLoginModule. Of course, you could always set the org.jboss.security.SecurityAssociation information directly, but this is considered an internal API that is subject to change without notice. Note that this login module does not perform any authentication. It merely copies the login information provided to it into the JBoss server EJB invocation layer for subsequent authentication on the server. If you need to perform client-side authentication of users you would need to configure another login module in addition to the ClientLoginModule. The supported login module configuration options include the following:  multi-threaded=true|false: When the multi-threaded option is set to true, each login thread has its own principal and credential storage. This is useful in client environments where multiple user identities are active in separate threads. When true, each separate thread must perform its own login. When set to false the login identity and credentials are global variables that apply to all threads in the VM. The default for this option is false.
  • 151. 395 | P a g e  password-stacking=useFirstPass: When password-stacking option is set, this module first looks for a shared username and password using javax.security.auth.login.name and javax.security.auth.login.password respectively in the login module shared state map. This allows a module configured prior to this one to establish a valid username and password that should be passed to JBoss. You would use this option if you want to perform client-side authentication of clients using some other login module such as the LdapLoginModule.  restore-login-identity=[true|false]: When restore-login-identity is true, the SecurityAssociation principal and credential seen on entry to the login() method are saved and restored on either abort or logout. When false (the default), the abort and logout simply clear the SecurityAssociation. A restore-login-identity of true is needed if one need to change identities and then restore the original caller identity. A sample login configuration for ClientLoginModule is the default configuration entry found in the JBoss distribution client/auth.conf file. The configuration is: other { // Put your login modules that work without jBoss here // jBoss LoginModule org.jboss.security.ClientLoginModule required; // Put your login modules that need jBoss here }; 8.4.7. Writing Custom Login Modules If the login modules bundled with the JBossSX framework do not work with your security environment, you can write your own custom login module implementation that does. Recall from the section on the JaasSecurityManager architecture that the JaasSecurityManager expected a particular usage pattern of the Subject principals set. You need to understand the JAAS Subject class's information storage features and the expected usage of these features to be able to write a login module that works with the JaasSecurityManager. This section examines this requirement and introduces two abstract base LoginModule implementations that can help you implement your own custom login modules.
  • 152. 396 | P a g e You can obtain security information associated with a Subject in six ways using the following methods: java.util.Set getPrincipals() java.util.Set getPrincipals(java.lang.Class c) java.util.Set getPrivateCredentials() java.util.Set getPrivateCredentials(java.lang.Class c) java.util.Set getPublicCredentials() java.util.Set getPublicCredentials(java.lang.Class c) For Subject identities and roles, JBossSX has selected the most natural choice: the principals sets obtained via getPrincipals() and getPrincipals(java.lang.Class). The usage pattern is as follows:  User identities (username, social security number, employee ID, and so on) are stored as java.security.Principal objects in the SubjectPrincipals set. The Principal implementation that represents the user identity must base comparisons and equality on the name of the principal. A suitable implementation is available as the org.jboss.security.SimplePrincipal class. Other Principal instances may be added to the SubjectPrincipals set as needed.  The assigned user roles are also stored in the Principals set, but they are grouped in named role sets using java.security.acl.Group instances. The Group interface defines a collection of Principals and/or Groups, and is a subinterface ofjava.security.Principal. Any number of role sets can be assigned to a Subject. Currently, the JBossSX framework uses two well- known role sets with the names Roles and CallerPrincipal. The Roles Group is the collection of Principals for the named roles as known in the application domain under which the Subject has been authenticated. This role set is used by methods like the EJBContext.isCallerInRole(String), which EJBs can use to see if the current caller belongs to the named application domain role. The security interceptor logic that performs method permission checks also uses this role set. The CallerPrincipalGroup consists of the single Principal identity assigned to the user in the application domain. TheEJBContext.getCallerPrincipal() method uses the CallerPrincipal to allow the application domain to map from the operation environment identity to a user identity suitable for the application. If a Subject does not have aCallerPrincipalGroup, the application identity is the same as operational environment identity.
  • 153. 397 | P a g e 8.4.7.1. Support for the Subject Usage Pattern To simplify correct implementation of the Subject usage patterns described in the preceding section, JBossSX includes two abstract login modules that handle the population of the authenticated Subject with a template pattern that enforces correct Subjectusage. The most generic of the two is the org.jboss.security.auth.spi.AbstractServerLoginModule class. It provides a concrete implementation of the javax.security.auth.spi.LoginModule interface and offers abstract methods for the key tasks specific to an operation environment security infrastructure. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses. package org.jboss.security.auth.spi; /** * This class implements the common functionality required for a JAAS * server-side LoginModule and implements the JBossSX standard * Subject usage pattern of storing identities and roles. Subclass * this module to create your own custom LoginModule and override the * login(), getRoleSets(), and getIdentity() methods. */ public abstract class AbstractServerLoginModule implements javax.security.auth.spi.LoginModule { protected Subject subject; protected CallbackHandler callbackHandler; protected Map sharedState; protected Map options; protected Logger log; /** Flag indicating if the shared credential should be used */ protected boolean useFirstPass; /** * Flag indicating if the login phase succeeded. Subclasses that * override the login method must set this to true on successful * completion of login */ protected boolean loginOk; // ... /** * Initialize the login module. This stores the subject, * callbackHandler and sharedState and options for the login * session. Subclasses should override if they need to process * their own options. A call to super.initialize(...) must be * made in the case of an override.
  • 154. 398 | P a g e * * <p> * The options are checked for the <em>password-stacking</em> parameter. * If this is set to "useFirstPass", the login identity will be taken from the * <code>javax.security.auth.login.name</code> value of the sharedState map, * and the proof of identity from the * <code>javax.security.auth.login.password</code> value of the sharedState map. * * @param subject the Subject to update after a successful login. * @param callbackHandler the CallbackHandler that will be used to obtain the * the user identity and credentials. * @param sharedState a Map shared between all configured login module instances * @param options the parameters passed to the login module. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { // ... } /** * Looks for javax.security.auth.login.name and * javax.security.auth.login.password values in the sharedState * map if the useFirstPass option was true and returns true if * they exist. If they do not or are null this method returns * false. * Note that subclasses that override the login method * must set the loginOk ivar to true if the login succeeds in * order for the commit phase to populate the Subject. This * implementation sets loginOk to true if the login() method * returns true, otherwise, it sets loginOk to false. */ public boolean login() throws LoginException { // ... } /** * Overridden by subclasses to return the Principal that * corresponds to the user primary identity. */ abstract protected Principal getIdentity(); /** * Overridden by subclasses to return the Groups that correspond * to the role sets assigned to the user. Subclasses should
  • 155. 399 | P a g e * create at least a Group named "Roles" that contains the roles * assigned to the user. A second common group is * "CallerPrincipal," which provides the application identity of * the user rather than the security domain identity. * * @return Group[] containing the sets of roles */ abstract protected Group[] getRoleSets() throws LoginException; } You'll need to to pay attention to the loginOk instance variable. This must be set to true if the login succeeds, false otherwise by any subclasses that override the login method. Failure to set this variable correctly will result in the commit method either not updating the Subject when it should, or updating the Subject when it should not. Tracking the outcome of the login phase was added to allow login module to be chained together with control flags that do not require that the login module succeed in order for the overall login to succeed. The second abstract base login module suitable for custom login modules is the org.jboss.security.auth.spi.UsernamePasswordLoginModule. The login module further simplifies custom login module implementation by enforcing a string-based username as the user identity and a char[] password as the authentication credential. It also supports the mapping of anonymous users (indicated by a null username and password) to a Principal with no roles. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses. package org.jboss.security.auth.spi; /** * An abstract subclass of AbstractServerLoginModule that imposes a * an identity == String username, credentials == String password * view on the login process. Subclasses override the * getUsersPassword() and getUsersRoles() methods to return the * expected password and roles for the user. */ public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule { /** The login identity */ private Principal identity; /** The proof of login identity */ private char[] credential;
  • 156. 400 | P a g e /** The principal to use when a null username and password are seen */ private Principal unauthenticatedIdentity; /** * The message digest algorithm used to hash passwords. If null then * plain passwords will be used. */ private String hashAlgorithm = null; /** * The name of the charset/encoding to use when converting the * password String to a byte array. Default is the platform's * default encoding. */ private String hashCharset = null; /** The string encoding format to use. Defaults to base64. */ private String hashEncoding = null; // ... /** * Override the superclass method to look for an * unauthenticatedIdentity property. This method first invokes * the super version. * * @param options, * @option unauthenticatedIdentity: the name of the principal to * assign and authenticate when a null username and password are * seen. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); // Check for unauthenticatedIdentity option. Object option = options.get("unauthenticatedIdentity"); String name = (String) option; if (name != null) { unauthenticatedIdentity = new SimplePrincipal(name); } } // ... /** * A hook that allows subclasses to change the validation of the * input password against the expected password. This version
  • 157. 401 | P a g e * checks that neither inputPassword or expectedPassword are null * and that inputPassword.equals(expectedPassword) is true; * * @return true if the inputPassword is valid, false otherwise. */ protected boolean validatePassword(String inputPassword, String expectedPassword) { if (inputPassword == null || expectedPassword == null) { return false; } return inputPassword.equals(expectedPassword); } /** * Get the expected password for the current username available * via the getUsername() method. This is called from within the * login() method after the CallbackHandler has returned the * username and candidate password. * * @return the valid password String */ abstract protected String getUsersPassword() throws LoginException; } The choice of subclassing the AbstractServerLoginModule versus UsernamePasswordLoginModule is simply based on whether a String based username and String credential are usable for the authentication technology you are writing the login module for. If the string based semantic is valid, then subclass UsernamePasswordLoginModule, else subclass AbstractServerLoginModule. The steps you are required to perform when writing a custom login module are summerized in the following depending on which base login module class you choose. When writing a custom login module that integrates with your security infrastructure, you should start by subclassing AbstractServerLoginModule or UsernamePasswordLoginModule to ensure that your login module provides the authenticated Principal information in the form expected by the JBossSX security manager. When subclassing the AbstractServerLoginModule, you need to override the following:
  • 158. 402 | P a g e  void initialize(Subject, CallbackHandler, Map, Map): if you have custom options to parse.  boolean login(): to perform the authentication activity. Be sure to set the loginOk instance variable to true if login succeeds, false if it fails.  Principal getIdentity(): to return the Principal object for the user authenticated by the log() step.  Group[] getRoleSets(): to return at least one Group named Roles that contains the roles assigned to the Principal authenticated during login(). A second common Group is named CallerPrincipal and provides the user's application identity rather than the security domain identity. When subclassing the UsernamePasswordLoginModule, you need to override the following:  void initialize(Subject, CallbackHandler, Map, Map): if you have custom options to parse.  Group[] getRoleSets(): to return at least one Group named Roles that contains the roles assigned to the Principal authenticated during login(). A second common Group is named CallerPrincipal and provides the user's application identity rather than the security domain identity.  String getUsersPassword(): to return the expected password for the current username available via the getUsername() method. The getUsersPassword() method is called from within login() after the callbackhandler returns the username and candidate password. 8.4.7.2. A Custom LoginModule Example In this section we will develop a custom login module example. It will extend the UsernamePasswordLoginModule and obtains a user's password and role names from a JNDI lookup. The idea is that there is a JNDI context that will return a user's password if you perform a lookup on the context using a name of the form password/<username> where <username> is the current user being authenticated. Similary, a lookup of the form roles/<username> returns the requested user's roles. The source code for the example is located in the src/main/org/jboss/chap8/ex2 directory of the book examples. Example 8.12, “ A JndiUserAndPass custom login module” shows the source code for
  • 159. 403 | P a g e the JndiUserAndPass custom login module. Note that because this extends the JBoss UsernamePasswordLoginModule, all the JndiUserAndPass does is obtain the user's password and roles from the JNDI store. The JndiUserAndPass does not concern itself with the JAAS LoginModule operations. Example 8.12. A JndiUserAndPass custom login module package org.jboss.chap8.ex2; import java.security.acl.Group; import java.util.Map; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.jboss.security.auth.spi.UsernamePasswordLoginModule; /** * An example custom login module that obtains passwords and roles * for a user from a JNDI lookup. * * @author Scott.Stark@jboss.org * @version $Revision: 1.15 $ */ public class JndiUserAndPass extends UsernamePasswordLoginModule { /** The JNDI name to the context that handles the password/username lookup */ private String userPathPrefix; /** The JNDI name to the context that handles the roles/ username lookup */ private String rolesPathPrefix; /** * Override to obtain the userPathPrefix and rolesPathPrefix options. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); userPathPrefix = (String) options.get("userPathPrefix"); rolesPathPrefix = (String) options.get("rolesPathPrefix"); } /**
  • 160. 404 | P a g e * Get the roles the current user belongs to by querying the * rolesPathPrefix + '/' + super.getUsername() JNDI location. */ protected Group[] getRoleSets() throws LoginException { try { InitialContext ctx = new InitialContext(); String rolesPath = rolesPathPrefix + '/' + super.getUsername(); String[] roles = (String[]) ctx.lookup(rolesPath); Group[] groups = {new SimpleGroup("Roles")}; log.info("Getting roles for user="+super.getUsername()); for(int r = 0; r < roles.length; r ++) { SimplePrincipal role = new SimplePrincipal(roles[r]); log.info("Found role="+roles[r]); groups[0].addMember(role); } return groups; } catch(NamingException e) { log.error("Failed to obtain groups for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } /** * Get the password of the current user by querying the * userPathPrefix + '/' + super.getUsername() JNDI location. */ protected String getUsersPassword() throws LoginException { try { InitialContext ctx = new InitialContext(); String userPath = userPathPrefix + '/' + super.getUsername(); log.info("Getting password for user="+super.getUsername()); String passwd = (String) ctx.lookup(userPath); log.info("Found password="+passwd); return passwd; } catch(NamingException e) { log.error("Failed to obtain password for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } } The details of the JNDI store are found in the org.jboss.chap8.ex2.service.JndiStore MBean. This service binds an ObjectFactory that
  • 161. 405 | P a g e returns a javax.naming.Context proxy into JNDI. The proxy handles lookup operations done against it by checking the prefix of the lookup name against password and roles. When the name begins with password, a user's password is being requested. When the name begins with roles the user's roles are being requested. The example implementation always returns a password of theduke and an array of roles names equal to {"TheDuke", "Echo"} regardless of what the username is. You can experiment with other implementations as you wish. The example code includes a simple session bean for testing the custom login module. To build, deploy and run the example, execute the following command from the examples directory. Make sure you have the JBoss server running. The key lines from the client are given in Example 8.13, “The chap8- ex2 secured client access output” while the server side operation of the is shown in Example 8.14, “The chap8-ex2 server side behavior of the JndiUserAndPass”. Example 8.13. The chap8-ex2 secured client access output [nr@toki examples]$ ant -Dchap=chap8 -Dex=2 run-example Buildfile: build.xml ... run-example2: [copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy [echo] Waiting for 5 seconds for deploy... [java] [INFO,ExClient] Login with username=jduke, password=theduke [java] [INFO,ExClient] Looking up EchoBean2 [java] [INFO,ExClient] Created Echo [java] [INFO,ExClient] Echo.echo('Hello') = Hello Example 8.14. The chap8-ex2 server side behavior of the JndiUserAndPass 17:48:11,458 INFO [EjbModule] Deploying EchoBean2 17:48:11,890 INFO [JndiStore] Start, bound security/store 17:48:11,896 INFO [SecurityConfig] Using JAAS AuthConfig: jar:file:/private/tmp/jboss-3.2.6/s erver/default/tmp/deploy/tmp22821chap8-ex2.jar-contents/chap8-ex2.sar!/META-INF/login-config.x ml 17:48:12,355 INFO [EJBDeployer] Deployed: file:/private/tmp/jboss-3.2.6/server/default/deploy /chap8-ex2.jar The choice of using the JndiUserAndPass custom login module for the server side authentication of the user is determined by the login configuration for the
  • 162. 406 | P a g e example security domain. The EJB JAR META-INF/jboss.xml descriptor sets the security domain and the sar META-INF/login-config.xml descriptor defines the login module configuration. The contents of these descriptors are shown in Example 8.15, “The chap8-ex2 security domain and login module configuration”. Example 8.15. The chap8-ex2 security domain and login module configuration <?xml version="1.0"?> <jboss> <security-domain>java:/jaas/chap8-ex2</security-domain> </jboss> Example 8.16. The login-config.xml configuration fragment for the chap8-ex2 application <application-policy name = "chap8-ex2"> <authentication> <login-module code="org.jboss.chap8.ex2.JndiUserAndPass" flag="required"> <module-option name = "userPathPrefix">/security/store/password</module-option> <module-option name = "rolesPathPrefix">/security/store/roles</module-option> </login-module> </authentication> </application-policy> 8.4.8. The DynamicLoginConfig service Security domains defined in the login-config.xml file are essentially static. They are read when JBoss starts up, but there is no easy way to add a new security domain or change the definition for an existing one. The DynamicLoginConfig service allows you to dynamically deploy security domains. This allows you to specify JAAS login configuration as part of a deployment (or just as a standalone service) rather than having to edit the static login- config.xml file. The service supports the following attributes:  AuthConfig: The resource path to the JAAS login configuration file to use. This defaults to login-config.xml
  • 163. 407 | P a g e  LoginConfigService: the XMLLoginConfig service name to use for loading. This service must support a String loadConfig(URL) operation to load the configurations.  SecurityManagerService: The SecurityManagerService name used to flush the registered security domains. This service must support a flushAuthenticationCache(String) operation to flush the case for the argument security domain. Setting this triggers the flush of the authentication caches when the service is stopped. Here is an examble MBean definition using the DynamicLoginConfig service. <server> <mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="..."> <attribute name="AuthConfig">login-config.xml</attribute> <!-- The service which supports dynamic processing of login-config.xml configurations. --> <depends optional-attribute-name="LoginConfigService"> jboss.security:service=XMLLoginConfig </depends> <!-- Optionally specify the security mgr service to use when this service is stopped to flush the auth caches of the domains registered by this service. --> <depends optional-attribute-name="SecurityManagerService"> jboss.security:service=JaasSecurityManager </depends> </mbean> </server> This will load the specified AuthConfig resource using the specified LoginConfigService MBean by invoking loadConfig with the apropriate resource URL. When the service is stopped the configurations are removed. The resource specified may be either an XML file, or a Sun JAAS login configuration. 8.5. The Secure Remote Password (SRP) Protocol The SRP protocol is an implementation of a public key exchange handshake described in the Internet standards working group request for comments 2945(RFC2945). The RFC2945 abstract states: This document describes a cryptographically strong network authentication mechanism known as the Secure Remote Password (SRP) protocol. This
  • 164. 408 | P a g e mechanism is suitable for negotiating secure connections using a user- supplied password, while eliminating the security problems traditionally associated with reusable passwords. This system also performs a secure key exchange in the process of authentication, allowing security layers (privacy and/or integrity protection) to be enabled during the session. Trusted key servers and certificate infrastructures are not required, and clients are not required to store or manage any long-term keys. SRP offers both security and deployment advantages over existing challenge-response techniques, making it an ideal drop-in replacement where secure password authentication is needed. Note: The complete RFC2945 specification can be obtained from http://www.rfc-editor.org/rfc.html. Additional information on the SRP algorithm and its history can be found at http://www-cs- students.stanford.edu/~tjw/srp/. SRP is similar in concept and security to other public key exchange algorithms, such as Diffie-Hellman and RSA. SRP is based on simple string passwords in a way that does not require a clear text password to exist on the server. This is in contrast to other public key-based algorithms that require client certificates and the corresponding certificate management infrastructure. Algorithms like Diffie-Hellman and RSA are known as public key exchange algorithms. The concept of public key algorithms is that you have two keys, one public that is available to everyone, and one that is private and known only to you. When someone wants to send encrypted information to you, then encrpyt the information using your public key. Only you are able to decrypt the information using your private key. Contrast this with the more traditional shared password based encryption schemes that require the sender and receiver to know the shared password. Public key algorithms eliminate the need to share passwords. For more information on public key algorithms as well as numerous other cryptographic algorithms, see Applied Cryptography, Second Edition by Bruce Schneier, ISBN 0-471-11709-9. The JBossSX framework includes an implementation of SRP that consists of the following elements:
  • 165. 409 | P a g e  An implementation of the SRP handshake protocol that is independent of any particular client/server protocol  An RMI implementation of the handshake protocol as the default client/server SRP implementation  A client side JAAS LoginModule implementation that uses the RMI implementation for use in authenticating clients in a secure fashion  A JMX MBean for managing the RMI server implementation. The MBean allows the RMI server implementation to be plugged into a JMX framework and externalizes the configuration of the verification information store. It also establishes an authentication cache that is bound into the JBoss server JNDI namespace.  A server side JAAS LoginModule implementation that uses the authentication cache managed by the SRP JMX MBean. Figure 8.10, “The JBossSX components of the SRP client-server framework.” gives a diagram of the key components involved in the JBossSX implementation of the SRP client/server framework.
  • 166. 410 | P a g e Figure 8.10. The JBossSX components of the SRP client-server framework. On the client side, SRP shows up as a custom JAAS LoginModule implementation that communicates to the authentication server through an org.jboss.security.srp.SRPServerInterface proxy. A client enables authentication using SRP by creating a login configuration entry that includes the org.jboss.security.srp.jaas.SRPLoginModule. This module supports the following configuration options:  principalClassName: This option is no longer supported. The principal class is now always org.jboss.security.srp.jaas.SRPPrincipal.  srpServerJndiName: The JNDI name of the SRPServerInterface object to use for communicating with the SRP authentication server. If
  • 167. 411 | P a g e both srpServerJndiName and srpServerRmiUrl options are specified, the srpServerJndiName is tried before srpServerRmiUrl.  srpServerRmiUrl: The RMI protocol URL string for the location of the SRPServerInterface proxy to use for communicating with the SRP authentication server.  externalRandomA: A true/false flag indicating if the random component of the client public key A should come from the user callback. This can be used to input a strong cryptographic random number coming from a hardware token for example.  hasAuxChallenge: A true/false flag indicating an that a string will be sent to the server as an additional challenge for the server to validate. If the client session supports an encryption cipher then a temporary cipher will be created using the session private key and the challenge object sent as a javax.crypto.SealedObject.  multipleSessions: a true/false flag indicating if a given client may have multiple SRP login sessions active simultaneously. Any other options passed in that do not match one of the previous named options is treated as a JNDI property to use for the environment passed to the IntialContext constructor. This is useful if the SRP server interface is not available from the defaultIntialContext. The SRPLoginModule needs to be configured along with the standard ClientLoginModule to allow the SRP authentication credentials to be used for validation of access to security J2EE components. An example login configuration entry that demonstrates such a setup is: srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; }; On the JBoss server side, there are two MBeans that manage the objects that collectively make up the SRP server. The primary service is the org.jboss.security.srp.SRPService MBean, and it is responsible for exposing an RMI
  • 168. 412 | P a g e accessible version of the SRPServerInterface as well as updating the SRP authentication session cache. The configurable SRPService MBean attributes include the following:  JndiName: The JNDI name from which the SRPServerInterface proxy should be available. This is the location where the SRPService binds the serializable dynamic proxy to the SRPServerInterface. If not specified it defaults tosrp/SRPServerInterface.  VerifierSourceJndiName: The JNDI name of the SRPVerifierSource implementation that should be used by the SRPService. If not set it defaults to srp/DefaultVerifierSource.  AuthenticationCacheJndiName: The JNDI name under which the authentication org.jboss.util.CachePolicy implementation to be used for caching authentication information is bound. The SRP session cache is made available for use through this binding. If not specified it defaults to srp/AuthenticationCache.  ServerPort: RMI port for the SRPRemoteServerInterface. If not specified it defaults to 10099.  ClientSocketFactory: An optional custom java.rmi.server.RMIClientSocketFactory implementation class name used during the export of the SRPServerInterface. If not specified the default RMIClientSocketFactory is used.  ServerSocketFactory: An optional custom java.rmi.server.RMIServerSocketFactory implementation class name used during the export of the SRPServerInterface. If not specified the default RMIServerSocketFactory is used.  AuthenticationCacheTimeout: Specifies the timed cache policy timeout in seconds. If not specified this defaults to 1800 seconds(30 minutes).  AuthenticationCacheResolution: Specifies the timed cache policy resolution in seconds. This controls the interval between checks for timeouts. If not specified this defaults to 60 seconds(1 minute).  RequireAuxChallenge: Set if the client must supply an auxillary challenge as part of the verify phase. This gives control over whether the SRPLoginModule configuration used by the client must have the useAuxChallenge option enabled.  OverwriteSessions: A flag indicating if a successful user auth for an existing session should overwrite the current session. This controls the
  • 169. 413 | P a g e behavior of the server SRP session cache when clients have not enabled the multiple session per user mode. The default is false meaning that the second attempt by a user to authentication will succeeed, but the resulting SRP session will not overwrite the previous SRP session state. The one input setting is the VerifierSourceJndiName attribute. This is the location of the SRP password information store implementation that must be provided and made available through JNDI. The org.jboss.security.srp SRPVerifierStoreService is an example MBean service that binds an implementation of the SRPVerifierStore interface that uses a file of serialized objects as the persistent store. Although not realistic for a production environment, it does allow for testing of the SRP protocol and provides an example of the requirements for an SRPVerifierStore service. The configurable SRPVerifierStoreService MBean attributes include the following:  JndiName: The JNDI name from which the SRPVerifierStore implementation should be available. If not specified it defaults to srp/DefaultVerifierSource.  StoreFile: The location of the user password verifier serialized object store file. This can be either a URL or a resource name to be found in the classpath. If not specified it defaults to SRPVerifierStore.ser. The SRPVerifierStoreService MBean also supports addUser and delUser operations for addition and deletion of users. The signatures are: public void addUser(String username, String password) throws IOException; public void delUser(String username) throws IOException; An example configuration of these services is presented in Section 8.5, “The Secure Remote Password (SRP) Protocol”. 8.5.1. Providing Password Information for SRP The default implementation of the SRPVerifierStore interface is not likely to be suitable for you production security environment as it requires all password hash information to be available as a file of serialized objects. You need to provide an MBean service that provides an implementation of the SRPVerifierStore interface that integrates with your existing security information stores. The SRPVerifierStore interface is shown in.
  • 170. 414 | P a g e Example 8.17. The SRPVerifierStore interface package org.jboss.security.srp; import java.io.IOException; import java.io.Serializable; import java.security.KeyException; public interface SRPVerifierStore { public static class VerifierInfo implements Serializable { /** * The username the information applies to. Perhaps redundant * but it makes the object self contained. */ public String username; /** The SRP password verifier hash */ public byte[] verifier; /** The random password salt originally used to verify the password */ public byte[] salt; /** The SRP algorithm primitive generator */ public byte[] g; /** The algorithm safe-prime modulus */ public byte[] N; } /** * Get the indicated user's password verifier information. */ public VerifierInfo getUserVerifier(String username) throws KeyException, IOException; /** * Set the indicated users' password verifier information. This * is equivalent to changing a user's password and should * generally invalidate any existing SRP sessions and caches. */ public void setUserVerifier(String username, VerifierInfo info) throws IOException; /** * Verify an optional auxillary challenge sent from the client to * the server. The auxChallenge object will have been decrypted * if it was sent encrypted from the client. An example of a * auxillary challenge would be the validation of a hardware token * (SafeWord, SecureID, iButton) that the server validates to * further strengthen the SRP password exchange. */ public void verifyUserChallenge(String username, Object auxChallenge)
  • 171. 415 | P a g e throws SecurityException; } The primary function of a SRPVerifierStore implementation is to provide access to the SRPVerifierStore.VerifierInfo object for a given username. The getUserVerifier(String) method is called by the SRPService at that start of a user SRP session to obtain the parameters needed by the SRP algorithm. The elements of the VerifierInfo objects are:  username: The user's name or id used to login.  verifier: This is the one-way hash of the password or PIN the user enters as proof of their identity. The org.jboss.security.Util class has a calculateVerifier method that performs that password hashing algorithm. The output passwordH(salt | H(username | ':' | password)) as defined by RFC2945. Here H is the SHA secure hash function. The username is converted from a string to a byte[] using the UTF-8 encoding.  salt: This is a random number used to increase the difficulty of a brute force dictionary attack on the verifier password database in the event that the database is compromised. It is a value that should be generated from a cryptographically strong random number algorithm when the user's existing clear-text password is hashed.  g: The SRP algorithm primitive generator. In general this can be a well known fixed parameter rather than a per-user setting. The org.jboss.security.srp.SRPConf utility class provides several settings for g including a good default which can obtained via SRPConf.getDefaultParams().g().  N: The SRP algorithm safe-prime modulus. In general this can be a well known fixed parameter rather than a per-user setting. The org.jboss.security.srp.SRPConf utility class provides several settings for N including a good default which can obtained via SRPConf.getDefaultParams().N(). So, step 1 of integrating your existing password store is the creation of a hashed version of the password information. If your passwords are already store in an irreversible hashed form, then this can only be done on a per-user basis as part of an upgrade proceedure for example. Note that the setUserVerifier(String, VerifierInfo) method is not used by the current SRPSerivce
  • 172. 416 | P a g e and may be implemented as noop method, or even one that throws an exception stating that the store is read-only. Step 2 is the creation of the custom SRPVerifierStore interface implementation that knows how to obtain the VerifierInfo from the store you created in step 1. The verifyUserChallenge(String, Object) method of the interface is only called if the client SRPLoginModule configuration specifies the hasAuxChallenge option. This can be used to integrate existing hardware token based schemes like SafeWord or Radius into the SRP algorithm. Step 3 is the creation of an MBean that makes the step 2 implementation of the SRPVerifierStore interface available via JNDI, and exposes any configurable parameters you need. In addition to the defaultorg.jboss.security.srp.SRPVerifierStoreService example, the SRP example presented later in this chapter provides a Java properties file based SRPVerifierStore implementation. Between the two examples you should have enough to integrate your security store. 8.5.2. Inside of the SRP algorithm The appeal of the SRP algorithm is that is allows for mutual authentication of client and server using simple text passwords without a secure communication channel. You might be wondering how this is done. If you want the complete details and theory behind the algorithm, refer to the SRP references mentioned in a note earlier. There are six steps that are performed to complete authentication: 1. The client side SRPLoginModule retrieves the SRPServerInterface instance for the remote authentication server from the naming service. 2. The client side SRPLoginModule next requests the SRP parameters associated with the username attempting the login. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. ThegetSRPParameters(username) call retrieves the SRP parameters for the given username.
  • 173. 417 | P a g e 3. The client side SRPLoginModule begins an SRP session by creating an SRPClientSession object using the login username, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking the SRPServerInterface.init method and passes in the username and client generated random number A. The server returns its own random number B. This step corresponds to the exchange of public keys. 4. The client side SRPLoginModule obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the login Subject. The server challenge response M2 from step 4 is verified by invoking the SRPClientSession.verify method. If this succeeds, mutual authentication of the client to server, and server to client have been completed.The client side SRPLoginModule next creates a challenge M1 to the server by invokingSRPClientSession.response method passing the server random number B as an argument. This challenge is sent to the server via the SRPServerInterface.verify method and server's response is saved as M2. This step corresponds to an exchange of challenges. At this point the server has verified that the user is who they say they are. 5. The client side SRPLoginModule saves the login username and M1 challenge into the LoginModule sharedState map. This is used as the Principal name and credentials by the standard JBoss ClientLoginModule. The M1 challenge is used in place of the password as proof of identity on any method invocations on J2EE components. The M1 challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password. 6. At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the SRPCacheLoginModule. Although SRP has many interesting properties, it is still an evolving component in the JBossSX framework and has some limitations of which you should be aware. Issues of note include the following:
  • 174. 418 | P a g e  Because of how JBoss detaches the method transport protocol from the component container where authentication is performed, an unauthorized user could snoop the SRP M1 challenge and effectively use the challenge to make requests as the associated username. Custom interceptors that encrypt the challenge using the SRP session key can be used to prevent this issue.  The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent J2EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout very long (up to 2,147,483,647 seconds, or approximately 68 years), or handle re- authentication in your code on failure.  By default there can only be one SRP session for a given username. Because the negotiated SRP session produces a private session key that can be used for encryption/decryption between the client and server, the session is effectively a stateful one. JBoss supports for multiple SRP sessions per user, but you cannot encrypt data with one session key and then decrypt it with another. To use end-to-end SRP authentication for J2EE component calls, you need to configure the security domain under which the components are secured to use the org.jboss.security.srp.jaas.SRPCacheLoginModule. The SRPCacheLoginModule has a single configuration option named cacheJndiName that sets the JNDI location of the SRP authentication CachePolicy instance. This must correspond to the AuthenticationCacheJndiName attribute value of the SRPService MBean. TheSRPCacheLoginModule authenticates user credentials by obtaining the client challenge from the SRPServerSession object in the authentication cache and comparing this to the challenge passed as the user credentials. Figure 8.11, “A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.” illustrates the operation of the SRPCacheLoginModule.login method implementation.
  • 175. 419 | P a g e Figure 8.11. A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache. 8.5.2.1. An SRP example We have covered quite a bit of material on SRP and now its time to demonstrate SRP in practice with an example. The example demonstrates client side authentication of the user via SRP as well as subsequent secured access to a simple EJB using the SRP session challenge as the user credential. The test code deploys an EJB JAR that includes a sar for the configuration of the server side login module configuration and SRP services. As in the previous examples we will dynamically install the server side login module configuration using the SecurityConfig MBean. In this example we also use a custom implementation of the SRPVerifierStore interface that uses an in memory store that is seeded from a Java properties file rather than a serialized object store as used by the SRPVerifierStoreService. This custom service is org.jboss.chap8.ex3.service.PropertiesVerifierStore. The following shows the contents of the JAR that contains the example EJB and SRP services.
  • 176. 420 | P a g e [orb@toki examples]$ java -cp output/classes ListJar output/chap8/chap8-ex3.jar output/chap8/chap8-ex3.jar +- META-INF/MANIFEST.MF +- META-INF/ejb-jar.xml +- META-INF/jboss.xml +- org/jboss/chap8/ex3/Echo.class +- org/jboss/chap8/ex3/EchoBean.class +- org/jboss/chap8/ex3/EchoHome.class +- roles.properties +- users.properties +- chap8-ex3.sar (archive) | +- META-INF/MANIFEST.MF | +- META-INF/jboss-service.xml | +- META-INF/login-config.xml | +- org/jboss/chap8/ex3/service/PropertiesVerifierStore$1.class | +- org/jboss/chap8/ex3/service/PropertiesVerifierStore.class | +- org/jboss/chap8/ex3/service/PropertiesVerifierStoreMBean.class | +- org/jboss/chap8/service/SecurityConfig.class | +- org/jboss/chap8/service/SecurityConfigMBean.class The key SRP related items in this example are the SRP MBean services configuration, and the SRP login module configurations. The jboss- service.xml descriptor of the chap8-ex3.sar is given in Example 8.18, “The chap8- ex3.sar jboss-service.xml descriptor for the SRP services”, while Example 8.19, “The client side standard JAAS configuration” and Example 8.20, “The server side XMLLoginConfig configuration” give the example client side and server side login module configurations. Example 8.18. The chap8-ex3.sar jboss-service.xml descriptor for the SRP services <server> <!-- The custom JAAS login configuration that installs a Configuration capable of dynamically updating the config settings --> <mbean code="org.jboss.chap8.service.SecurityConfig" name="jboss.docs.chap8:service=LoginConfig-EX3"> <attribute name="AuthConfig">META-INF/login-config.xml</attribute> <attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute> </mbean> <!-- The SRP service that provides the SRP RMI server and server side authentication cache --> <mbean code="org.jboss.security.srp.SRPService" name="jboss.docs.chap8:service=SRPService">
  • 177. 421 | P a g e <attribute name="VerifierSourceJndiName">srp-test/chap8-ex3</attribute> <attribute name="JndiName">srp-test/SRPServerInterface</attribute> <attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute> <attribute name="ServerPort">0</attribute> <depends>jboss.docs.chap8:service=PropertiesVerifierStore</depends> </mbean> <!-- The SRP store handler service that provides the user password verifier information --> <mbean code="org.jboss.chap8.ex3.service.PropertiesVerifierStore" name="jboss.docs.chap8:service=PropertiesVerifierStore"> <attribute name="JndiName">srp-test/chap8-ex3</attribute> </mbean> </server> Example 8.19. The client side standard JAAS configuration srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="srp-test/SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; }; Example 8.20. The server side XMLLoginConfig configuration <application-policy name="chap8-ex3"> <authentication> <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule" flag = "required"> <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> <module-option name="password-stacking">useFirstPass</module-option> </login-module> </authentication> </application-policy> The example services are the ServiceConfig and the PropertiesVerifierStore and SRPService MBeans. Note that the JndiName attribute of the PropertiesVerifierStore is equal to the VerifierSourceJndiName attribute of the SRPService, and that the SRPService depends on the PropertiesVerifierStore. This is required because the SRPService needs an implementation of
  • 178. 422 | P a g e the SRPVerifierStore interface for accessing user password verification information. The client side login module configuration makes use of the SRPLoginModule with a srpServerJndiName option value that corresponds to the JBoss server component SRPService JndiName attribute value(srp-test/SRPServerInterface). Also needed is the ClientLoginModule configured with the password- stacking="useFirstPass" value to propagate the user authentication credentials generated by the SRPLoginModule to the EJB invocation layer. There are two issues to note about the server side login module configuration. First, note the cacheJndiName=srp-test/AuthenticationCache configuration option tells the SRPCacheLoginModule the location of the CachePolicy that contains theSRPServerSession for users who have authenticated against the SRPService. This value corresponds to the SRPService AuthenticationCacheJndiName attribute value. Second, the configuration includes a UsersRolesLoginModule with thepassword- stacking=useFirstPass configuration option. It is required to use a second login module with the SRPCacheLoginModule because SRP is only an authentication technology. A second login module needs to be configured that accepts the authentication credentials validated by the SRPCacheLoginModule to set the principal's roles that determines the principal's permissions. The UsersRolesLoginModule is augmenting the SRP authentication with properties file based authorization. The user's roles are coming the roles.properties file included in the EJB JAR. Now, run the example 3 client by executing the following command from the book examples directory: [starksm@banshee examples]$ ant -Dchap=chap8 -Dex=3 run-example Buildfile: build.xml ... run-example3: [copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy [echo] Waiting for 5 seconds for deploy... [java] Logging in using the 'srp' configuration [java] Created Echo [java] Echo.echo()#1 = This is call 1 [java] Echo.echo()#2 = This is call 2
  • 179. 423 | P a g e In the examples/logs directory you will find a file called ex3-trace.log. This is a detailed trace of the client side of the SRP algorithm. The traces show step-by- step the construction of the public keys, challenges, session key and verification. Note that the client has taken a long time to run relative to the other simple examples. The reason for this is the construction of the client's public key. This involves the creation of a cryptographically strong random number, and this process takes quite a bit of time the first time it occurs. If you were to log out and log in again within the same VM, the process would be much faster. Also note that Echo.echo()#2 fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the SRPService cache expiration. The SRPService cache policy timeout has been set to a mere 10 seconds to force this issue. As stated earlier, you need to make the cache timeout very long, or handle re-authentication on failure. 8.6. Running JBoss with a Java 2 security manager By default the JBoss server does not start with a Java 2 security manager. If you want to restrict privileges of code using Java 2 permissions you need to configure the JBoss server to run under a security manager. This is done by configuring the Java VM options in the run.bat or run.sh scripts in the JBoss server distribution bin directory. The two required VM options are as follows:  java.security.manager: This is used without any value to specify that the default security manager should be used. This is the preferred security manager. You can also pass a value to the java.security.manager option to specify a custom security manager implementation. The value must be the fully qualified class name of a subclass of java.lang.SecurityManager. This form specifies that the policy file should augment the default security policy as configured by the VM installation.  java.security.policy: This is used to specify the policy file that will augment the default security policy information for the VM. This option takes two forms: java.security.policy=policyFileURL and java.security.policy==policyFileURL. The first form specifies that the policy file should augment the default security policy as configured by the VM installation. The second form specifies
  • 180. 424 | P a g e that only the indicated policy file should be used. The policyFileURL value can be any URL for which a protocol handler exists, or a file path specification. Example 8.21, “The modifications to the Win32 run.bat start script to run JBoss with a Java 2 security manager.” illustrates a fragment of the standard run.bat start script for Win32 that shows the addition of these two options to the command line used to start JBoss. Example 8.21. The modifications to the Win32 run.bat start script to run JBoss with a Java 2 security manager. ... set CONFIG=%1 @if "%CONFIG%" == "" set CONFIG=default set PF=../conf/%CONFIG%/server.policy set OPTS=-Djava.security.manager set OPTS=%OPTS% -Djava.security.policy=%PF% echo JBOSS_CLASSPATH=%JBOSS_CLASSPATH% java %JAXP% %OPTS% -classpath "%JBOSS_CLASSPATH%" org.jboss.Main %* Example 8.22, “The modifications to the UNIX/Linux run.sh start script to run JBoss with a Java 2 security manager.” shows a fragment of the standard run.sh start script for UNIX/Linux systems that shows the addition of these two options to the command line used to start JBoss. Example 8.22. The modifications to the UNIX/Linux run.sh start script to run JBoss with a Java 2 security manager. # ... CONFIG=$1 if [ "$CONFIG" == "" ]; then CONFIG=default; fi PF=../conf/$CONFIG/server.policy OPTS=-Djava.security.manager OPTS="$OPTS -Djava.security.policy=$PF" echo JBOSS_CLASSPATH=$JBOSS_CLASSPATH java $HOTSPOT $JAXP $OPTS -classpath $JBOSS_CLASSPATH org.jboss.Main $@ Both start scripts are setting the security policy file to the server.policy file located in the JBoss configuration file set directory that corresponds to the configuration name passed as the first argument to the script. This allows one
  • 181. 425 | P a g e maintain a security policy per configuration file set without having to modify the start script. Enabling Java 2 security is the easy part. The difficult part of Java 2 security is establishing the allowed permissions. If you look at the server.policy file that is contained in the default configuration file set, you'll see that it contains the following permission grant statement: grant { // Allow everything for now permission java.security.AllPermission; }; This effectively disables security permission checking for all code as it says any code can do anything, which is not a reasonable default. What is a reasonable set of permissions is entirely up to you. The current set of JBoss specific java.lang.RuntimePermissions that are required include: TargetName What the permission allows Risks org.jboss.security.SecurityAsso ciation.getPrincipalInfo Access to the org.jboss.security.SecurityAssociatio n getPrincipal() and getCredentials() methods. The ability to see the current thread caller and credentials. org.jboss.security.SecurityAsso ciation.setPrincipalInfo Access to the org.jboss.security.SecurityAssociatio n setPrincipal() and setCredentials() methods. The ability to set the current thread caller and credentials. org.jboss.security.SecurityAsso ciation.setServer Access to the org.jboss.security.SecurityAssociatio n setServer method. The ability to enable or disable multithread storage of the caller principal and credential. org.jboss.security.SecurityAsso ciation.setRunAsRole Access to the org.jboss.security.SecurityAssociatio n pushRunAsRole and popRunAsRole The ability to change the current caller run-as role
  • 182. 426 | P a g e TargetName What the permission allows Risks methods. principal. To conclude this discussion, here is a little-known tidbit on debugging security policy settings. There are various debugging flag that you can set to determine how the security manager is using your security policy file as well as what policy files are contributing permissions. Running the VM as follows shows the possible debugging flag settings: [nr@toki bin]$ java -Djava.security.debug=help all turn on all debugging access print all checkPermission results combiner SubjectDomainCombiner debugging jar jar verification logincontext login context results policy loading and granting provider security provider debugging scl permissions SecureClassLoader assigns The following can be used with access: stack include stack trace domain dumps all domains in context failure before throwing exception, dump stack and domain that didn't have permission Note: Separate multiple options with a comma Running with -Djava.security.debug=all provides the most output, but the output volume is torrential. This might be a good place to start if you don't understand a given security failure at all. A less verbose setting that helps debug permission failures is to use -Djava.security.debug=access,failure. This is still relatively verbose, but not nearly as bad as the all mode as the security domain information is only displayed on access failures. 8.7. Using SSL with JBoss using JSSE JBoss uses JSSE the Java Secure Socket Extension (JSSE). JSSE is bundled with JBoss and it comes with JDK 1.4. For more information on JSSE see: http://java.sun.com/products/jsse/index.html. A simple test that you can
  • 183. 427 | P a g e use the JSSE as bundled with JBoss works is to run a program like the following: import java.net.*; import javax.net.ServerSocketFactory; import javax.net.ssl.*; public class JSSE_install_check { public static void main(String[] args) throws Exception { Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); ServerSocketFactory factory = SSLServerSocketFactory.getDefault(); SSLServerSocket sslSocket = (SSLServerSocket) factory.createServerSocket(12345); String [] cipherSuites = sslSocket.getEnabledCipherSuites(); for(int i = 0; i < cipherSuites.length; i++) { System.out.println("Cipher Suite " + i + " = " + cipherSuites[i]); } } } The book examples includes a testcase for this which can be run using the following command. This will produce a lot of output as the - Djavax.net.debug=all option is passed to the VM. [nr@toki examples]$ ant -Dchap=chap8 -Dex=4a run-example ... run-example4a: run-example4a: [echo] Testing JSSE availablility [java] keyStore is : [java] keyStore type is : jks [java] init keystore [java] init keymanager of type SunX509 [java] trustStore is: /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home /lib/security/cacerts [java] trustStore type is : jks [java] init truststore ... [java] init context [java] trigger seeding of SecureRandom [java] done seeding SecureRandom [java] Cipher Suite 0 = SSL_RSA_WITH_RC4_128_MD5 [java] Cipher Suite 1 = SSL_RSA_WITH_RC4_128_SHA [java] Cipher Suite 2 = TLS_RSA_WITH_AES_128_CBC_SHA
  • 184. 428 | P a g e [java] Cipher Suite 3 = TLS_DHE_RSA_WITH_AES_128_CBC_SHA [java] Cipher Suite 4 = TLS_DHE_DSS_WITH_AES_128_CBC_SHA [java] Cipher Suite 5 = SSL_RSA_WITH_3DES_EDE_CBC_SHA [java] Cipher Suite 6 = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA [java] Cipher Suite 7 = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA [java] Cipher Suite 8 = SSL_RSA_WITH_DES_CBC_SHA [java] Cipher Suite 9 = SSL_DHE_RSA_WITH_DES_CBC_SHA [java] Cipher Suite 10 = SSL_DHE_DSS_WITH_DES_CBC_SHA [java] Cipher Suite 11 = SSL_RSA_EXPORT_WITH_RC4_40_MD5 [java] Cipher Suite 12 = SSL_RSA_EXPORT_WITH_DES40_CBC_SHA [java] Cipher Suite 13 = SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA [java] Cipher Suite 14 = SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA The JSSE jars include the jcert.jar, jnet.jar and jsse.jar in the JBOSS_DIST/client directory. Once you have tested that JSSE runs, you need a public key/private key pair in the form of an X509 certificate for use by the SSL server sockets. For the purpose of this example we have created a self-signed certificate using the JDK keytool and included the resulting keystore file in the chap8 source directory as chap8.keystore. It was created using the following command and input: [nr@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore -v alidity 3650 [orb@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore - validity 3650 Enter keystore password: rmi+ssl What is your first and last name? [Unknown]: Chapter 8 SSL Example What is the name of your organizational unit? [Unknown]: JBoss Book What is the name of your organization? [Unknown]: JBoss, Inc. What is the name of your City or Locality? [Unknown]: Issaquah What is the name of your State or Province? [Unknown]: WA What is the two-letter country code for this unit? [Unknown]: US Is CN=Chapter 8 SSL Example, OU=JBoss Book, O="JBoss, Inc.", L=Issaquah, ST=WA, C=US corre ct? [no]: yes Enter key password for <rmi+ssl> (RETURN if same as keystore password):
  • 185. 429 | P a g e This produces a keystore file called chap8.keystore. A keystore is a database of security keys. There are two different types of entries in a keystore:  key entries: each entry holds very sensitive cryptographic key information, which is stored in a protected format to prevent unauthorized access. Typically, a key stored in this type of entry is a secret key, or a private key accompanied by the certificate chain for the corresponding public key. The keytool and jarsigner tools only handle the later type of entry, that is private keys and their associated certificate chains.  trusted certificate entries: each entry contains a single public key certificate belonging to another party. It is called a trusted certificate because the keystore owner trusts that the public key in the certificate indeed belongs to the identity identified by the subject (owner) of the certificate. The issuer of the certificate vouches for this, by signing the certificate. Listing the src/main/org/jboss/chap8/chap8.keystore examples file contents using the keytool shows one self-signed certificate: [nr@toki examples]$ keytool -list -v -keystore src/main/org/jboss/chap8/chap8.keystore Enter keystore password: rmi+ssl Keystore type: jks Keystore provider: SUN Your keystore contains 1 entry Alias name: rmi+ssl Creation date: Nov 8, 2001 Entry type: keyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C= US Issuer: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C =US Serial number: 3beb5271 Valid from: Thu Nov 08 21:50:09 CST 2001 until: Sun Nov 06 21:50:09 CST 2011 Certificate fingerprints: MD5: F6:1B:2B:E9:A5:23:E7:22:B2:18:6F:3F:9F:E7:38:AE SHA1: F2:20:50:36:97:86:52:89:71:48:A2:C3:06:C8:F9:2D:F7:79:00:36
  • 186. 430 | P a g e ******************************************* ******************************************* With JSSE working and a keystore with the certificate you will use for the JBoss server, your are ready to configure JBoss to use SSL for EJB access. This is done by configuring the EJB invoker RMI socket factories. The JBossSX framework includes implementations of the java.rmi.server.RMIServerSocketFactory and java.rmi.server.RMIClientSocketFactory interfaces that enable the use of RMI over SSL encrypted sockets. The implementation classes areorg.jboss.security.ssl.RMISSLServerSocketFactory and org.jboss.security.ssl.RMISSLClientSocketFact ory respectively. There are two steps to enable the use of SSL for RMI access to EJBs. The first is to enable the use of a keystore as the database for the SSL server certificate, which is done by configuring an org.jboss.security.plugins.JaasSecurityDomain MBean. The jboss-service.xml descriptor in the chap8/ex4 directory includes the JaasSecurityDomain definition shown in Example 8.23, “A sample JaasSecurityDomain config for RMI/SSL”. Example 8.23. A sample JaasSecurityDomain config for RMI/SSL <!-- The SSL domain setup --> <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=JaasSecurityDomain,domain=RMI+SSL"> <constructor> <arg type="java.lang.String" value="RMI+SSL"/> </constructor> <attribute name="KeyStoreURL">chap8.keystore</attribute> <attribute name="KeyStorePass">rmi+ssl</attribute> </mbean> The JaasSecurityDomain is a subclass of the standard JaasSecurityManager class that adds the notions of a keystore as well JSSE KeyManagerFactory and TrustManagerFactory access. It extends the basic security manager to allow support for SSL and other cryptographic operations that require security keys. This configuration simply loads the chap8.keystore from the example 4 MBean sar using the indicated password. The second step is to define an EJB invoker configuration that uses the JBossSX RMI socket factories that support SSL. To do this you need to define a custom configuration for the JRMPInvoker we saw in Chapter 5, EJBs on JBoss as well as an EJB setup that makes use of this invoker. The configuration required to
  • 187. 431 | P a g e enable RMI over SSL access to stateless session bean is provided for you in Example 8.24, “The jboss-service.xml configurations to enable SSL with the example 4 stateless session bean.” andExample 8.25, “The jboss.xml configuration to enable SSL with the example 4 stateless session bean.” The top of the listing shows the jboss-service.xml descriptor that defines the custom JRMPInovker, and the bottom shows the example 4 EchoBean4configuration needed to use the SSL invoker. You will use this configuration in a stateless session bean example. Example 8.24. The jboss-service.xml configurations to enable SSL with the example 4 stateless session bean. <mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker name="jboss:service=invoker,type=jrmp,socketType=SSL"> <attribute name="RMIObjectPort">14445</attribute> <attribute name="RMIClientSocketFactory"> org.jboss.security.ssl.RMISSLClientSocketFactory </attribute> <attribute name="RMIServerSocketFactory"> org.jboss.security.ssl.RMISSLServerSocketFactory </attribute> <attribute name="SecurityDomain">java:/jaas/RMI+SSL</attribute> <depends>jboss.security:service=JaasSecurityDomain,domain=RMI+SSL</depends> </mbean> Example 8.25. The jboss.xml configuration to enable SSL with the example 4 stateless session bean. <?xml version="1.0"?> <jboss> <enterprise-beans> <session> <ejb-name>EchoBean4</ejb-name> <configuration-name>Standard Stateless SessionBean</configuration-name> <home-invoker>jboss:service=invoker,type=jrmp,socketType=SSL</home-invoker> <bean-invoker>jboss:service=invoker,type=jrmp,socketType=SSL</bean-invoker> </session> </enterprise-beans> </jboss> The example 4 code is located under the src/main/org/jboss/chap8/ex4 directory of the book examples. This is another simple stateless session bean with an echo method that returns its input argument. It is hard to tell when SSL is in use unless it fails, so we'll run the example 4 client in two different ways to
  • 188. 432 | P a g e demonstrate that the EJB deployment is in fact using SSL. Start the JBoss server using the default configuration and then run example 4b as follows: [nr@toki examples]$ ant -Dchap=chap8 -Dex=4b run-example ... run-example4b: [copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy [echo] Waiting for 15 seconds for deploy... [java] Exception in thread "main" java.rmi.ConnectIOException: error during JRMP conn ection establishment; nested exception is: [java] javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExcep tion: No trusted certificate found [java] at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:274) ... [java] Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.Validat orException: No trusted certificate found [java] at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA12275) ... [java] Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.Validat orException: No trusted certificate found [java] at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA12275) ... The resulting exception is expected, and is the purpose of the 4b version of the example. Note that the exception stack trace has been edited to fit into the book format, so expect some difference. The key item to notice about the exception is it clearly shows you are using the Sun JSSE classes to communicate with the JBoss EJB container. The exception is saying that the self-signed certificate you are using as the JBoss server certificate cannot be validated as signed by any of the default certificate authorities. This is expected because the default certificate authority keystore that ships with the JSSE package only includes well known certificate authorities such as VeriSign, Thawte, and RSA Data Security. To get the EJB client to accept your self-signed certificate as valid, you need to tell the JSSE classes to use your chap8.keystore as its truststore. A truststore is just a keystore that contains public key certificates used to sign other certificates. To do this, run example 4 using - Dex=4 rather than -Dex=4b to pass the location of the correct truststore using the javax.net.ssl.trustStore system property: [nr@toki examples]$ ant -Dchap=chap8 -Dex=4 run-example ... run-example4: [copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy [echo] Waiting for 5 seconds for deploy...
  • 189. 433 | P a g e [java] 0 [HandshakeCompletedNotify-Thread] DEBUG org.jboss.security.ssl.RMISSLClientS ocketFactory - SSL handshakeCompleted, cipher=SSL_RSA_WITH_RC4_128_MD5, peerHost=127.0.0. 1 [java] Created Echo [java] Echo.echo()#1 = This is call 1 This time the only indication that an SSL socket is involved is because of the SSL handshakeCompleted message. This is coming from the RMISSLClientSocketFactory class as a debug level log message. If you did not have the client configured to print out log4j debug level messages, there would be no direct indication that SSL was involved. If you note the run times and the load on your system CPU, there definitely is a difference. SSL, like SRP, involves the use of cryptographically strong random numbers that take time to seed the first time they are used. This shows up as high CPU utilization and start up times. One consequence of this is that if you are running on a system that is slower than the one used to run the examples for the book, such as when running example 4b, you may seen an exception similar to the following: javax.naming.NameNotFoundException: EchoBean4 not bound at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer at sun.rmi.transport.StreamRemoteCall.executeCall at sun.rmi.server.UnicastRef.invoke at org.jnp.server.NamingServer_Stub.lookup at org.jnp.interfaces.NamingContext.lookup at org.jnp.interfaces.NamingContext.lookup at javax.naming.InitialContext.lookup at org.jboss.chap8.ex4.ExClient.main(ExClient.java:29) The problem is that the JBoss server has not finished deploying the example EJB in the time the client allowed. This is due to the initial setup time of the secure random number generator used by the SSL server socket. If you see this issue, simply rerun the example again or increase the deployment wait time in the chap8 build.xml Ant script. 8.8. Configuring JBoss for use Behind a Firewall JBoss comes with many socket based services that open listening ports. In this section we list the services that open ports that might need to be configured to work when accessing JBoss behind a firewall. The following table shows the ports, socket type, associated service for the services in the default configuration file set. Table 8.2, “Additional ports in the all
  • 190. 434 | P a g e configuration” shows the same information for the additional ports that exist in the all configuration file set. Table 8.1. The ports found in the default configuration Port Type Service 1099 TCP org.jboss.naming.NamingService 1098 TCP org.jboss.naming.NamingService 1162 UDP org.jboss.jmx.adaptor.snmp.trapd.TrapdService 4444 TCP org.jboss.invocation.jrmp.server.JRMPInvoker 4445 TCP org.jboss.invocation.pooled.server.PooledInvoker 8009 TCP org.jboss.web.tomcat.tc4.EmbeddedTomcatService 8080 TCP org.jboss.web.tomcat.tc4.EmbeddedTomcatService 8083 TCP org.jboss.web.WebService 8090 TCP org.jboss.mq.il.oil.OILServerILService 8092 TCP org.jboss.mq.il.oil2.OIL2ServerILService 8093 TCP org.jboss.mq.il.uil2.UILServerILService 0[a] TCP org.jboss.mq.il.rmi.RMIServerILService 0[b] UDP org.jboss.jmx.adaptor.snmp.agent.SnmpAgentService [a] This service binds to an anonymous TCP port and does not support configuration of the port or bind interface. [b] This service binds to an anonymous UDP port and does not support configuration of the port or bind interface. Table 8.2. Additional ports in the all configuration
  • 191. 435 | P a g e Port Type Service 1100 TCP org.jboss.ha.jndi.HANamingService 0[a] TCP org.jboss.ha.jndi.HANamingService 1102 UDP org.jboss.ha.jndi.HANamingService 3528 TCP org.jboss.invocation.iiop.IIOPInvoker 45566[b] UDP org.jboss.ha.framework.server.ClusterPartition [a] Currently anonymous but can be set via the RmiPort attribute. [b] Plus two additional anonymous UDP ports, one can be set using the rcv_port, and the other cannot be set. 8.9. How to Secure the JBoss Server JBoss comes with several admin access points that need to be secured or removed to prevent unauthorized access to admin functions in a deployment. This section describes the various admin services and how to secure them. 8.9.1. The jmx-console.war The jmx-console.war found in the deploy directory provides an html view into the JMX microkernel. As such, it provides access to arbitrary admin type access like shutting down the server, stopping services, deploying new services, etc. It should either be secured like any other web application, or removed. 8.9.2. The web-console.war The web-console.war found in the deploy/management directory is another web application view into the JMX microkernel. This uses a combination of an applet and a HTML view and provides the same level of access to admin functionality as the jmx-console.war. As such, it should either be secured or removed. The web-console.war contains commented out templates for basic security in its WEB-INF/web.xml as well as commented out setup for a security domain in WEB-INF/jboss-web.xml.
  • 192. 436 | P a g e 8.9.3. The http-invoker.sar The http-invoker.sar found in the deploy directory is a service that provides RMI/HTTP access for EJBs and the JNDI Naming service. This includes a servlet that processes posts of marshalled org.jboss.invocation.Invocation objects that represent invocations that should be dispatched onto the MBeanServer. Effectively this allows access to MBeans that support the detached invoker operation via HTTP since one could figure out how to format an approriate HTTP post. To security this access point you would need to secure the JMXInvokerServlet servlet found in the http-invoker.sar/invoker.war/WEB- INF/web.xml descriptor. There is a secure mapping defined for the /restricted/JMXInvokerServlet path by default, one would simply have to remove the other paths and configure the http-invoker security domain setup in the http- invoker.sar/invoker.war/WEB-INF/jboss-web.xml descriptor. 8.9.4. The jmx-invoker-adaptor-server.sar The jmx-invoker-adaptor-server.sar is a service that exposes the JMX MBeanServer interface via an RMI compatible interface using the RMI/JRMP detached invoker service. The only way for this service to be secured currently would be to switch the protocol to RMI/HTTP and secure the http-invoker.sar as described in the previous section. In the future this service will be deployed as an XMBean with a security interceptor that supports role based access checks. If your so inclined this is a configuration that can setup today following the proceedure demonstrated in XMBean example: Section 2.4.3.2.3, “Version 3, Adding Security and Remote Access to the JNDIMap XMBean”. Secure JMX Console (Authentication Only) 1.1. About the JMX Console The jmx-console is the default console that is available with the JBoss Application Server. It displays the various MBean Services that are running in a JBoss Application Server instance. A user is able to get and set attributes and invoke operations on the various services. For more information, please refer to the 'JBoss Application Server User or Administrator's Guide'. The following wiki page has a good description of the JMX Console. http:// wiki.jboss.org/wiki/Wiki.jsp?page=JMXConsole
  • 193. 437 | P a g e 1.2. Simple Security for the JMX Console If you want to have simple secured jmx console where the user/password and user/roles come from properties files, then you can follow the following steps: 1. Locate the jmx-console.war directory in the deploy directory of your server configuration. If you are just using the default configuration, then it will be under JBOSS_DIR/server/default/deploy directory and you are using the clustered configuration, then it will be under JBOSS_DIR/server/all/deploy directory. 2. Now edit the web.xml file under jmx-console.war/WEB-INF directory and uncomment the security constraint block as shown below: <!-- A security constraint that restricts access to the HTML JMX console to users with the role JBossAdmin. Edit the roles to what you want and uncomment the WEB-INF/jboss-web.xml/security-domain element to enable secured access to the HTML JMX console. --> <security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description>An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint> 3. Edit the jboss-web.xml file also and uncomment the security-domain element as shown below: <jboss-web> JBoss 1.0 1 <!-- Uncomment the security-domain to enable security. You will need to edit the htmladaptor login configuration to setup the login modules used to authentication users. --> <security-domain>java:/jaas/jmx-console</security-domain> </jboss-web> 2. Now locate the two properties files called as jmx-console-users.properties and jmx- console-roles.properties that will be in the conf directory of your server configuration under the props sub-directory('default', 'all' or 'custom'). An example of the location will be /server/default/conf/props. 3. In the jmx-console-users.properties, you can add/change the user/password combination. 4. In the jmx-console-roles.properties, you will need to assign roles to the users you added or changed in step.4. 4. Just remember to add JBossAdmin role to the users who will be using the jmx-console.
  • 194. 438 | P a g e 5. Now when you start JBoss and try to access the jmx-console, you should see a pop up appear that will ask you to enter the username and password. You can use one of the users/password combination that you configured in steps 4 and 5. 6. Secure JMX Console (Authentication Only) Secure JMX Console (Access Control) 2.1. Need for Access Control on the JMX Console The previous chapter talked about securing the jmx console. The security provided there applied to the entire console with no controls on what an user can do with reference to the various JMX operations possible on the console. 2.2. Details You will need to follow the following steps to enable access control on the jmx console. 1. Perform all the steps outlined in the earlier chapter to secure the jmx-console. Edit the web.xml file of deploy/jmx-console.war/WEB-INF in the server configuration you are using (default, all, custom etc). You will need to uncomment the filter settings as shown here: <!-- --> <filter> <filter-name>JmxOpsAccessControlFilter</filter-name> <filter-class>org.jboss.jmx.adaptor.html.JMXOpsAccessControlFilter</filter-class> <init-param> <param-name>updateAttributes</param-name> <param-value>UpdateAttributeRole</param-value> <description>Comma-delimited Roles that define the JMX Operation denoting updation of Attributes</</init-param> <init-param> <param-name>invokeOp</param-name> <param-value>InvokeOpRole</param-value> <description>Comma-delimited Roles that define the JMX Operation denoting Invocation of Operations</</init- param> </filter> <filter-mapping> <filter-name>JmxOpsAccessControlFilter</filter-name> <servlet-name>HtmlAdaptor</servlet-name> </filter-mapping> 2. Now if an user is allowed to click the 'invoke' buttons on the various MBean services in the jmx console (action will invoke operations), then the user needs to have 'InvokeOpRole'. If the user is allowed to click the 'Apply Changes' button(action will update the jmx attributes of the service), then the user needs to have 'updateAttributeRole'. For this to apply, you will need to update the jmx-console-roles.properties file. An example is shown below: # A sample roles.properties file for use with the UsersRolesLoginModule admin=JBossAdmin,HttpInvoker,UpdateAttributeRole
  • 195. 439 | P a g e JBoss 1.0 3 admin2=JBossAdmin,HttpInvoker,InvokeOpRole 2.3. Reference http://wiki.jboss.org/wiki/Wiki.jsp?page=AccessControlForJMXConsole Secure JMX Console (Access Control) JBoss 1.0 4 Secure the JMX Invokers (Authentication Only) 3.1. Introduction The JMX invokers are the entry points to the MBean Server. If there is a need to restrict external access to the MBean Server, then there is a need to secure the invokers. 3.2. Enable Authentication for the JMX Invoker The JMX invoker can be made to authenticate against the JBoss Security JAAS framework like the web or ejb layers. 3.2.1. Modifications Required You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server configuration (eg: default configuration). Please uncomment the following section. <operation> <description>The detached invoker entry point</description> <name>invoke</name> <parameter> <description>The method invocation context</description> <name>invocation</name> <type>org.jboss.invocation.Invocation</type> </parameter> <return-type>java.lang.Object</return-type> <!-- Uncomment to require authenticated users --> <descriptors> <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securityDomain="java:/jaas/jmx-console"/> </interceptors> </descriptors> </operation> The value of the security domain needs to be defined in the conf/login-config.xml. You can resuse the security domain used to restrict access to the jmx-console. 3.2.2. Troubleshooting When you use JDK5+, you may see the following error:
  • 196. 440 | P a g e org.jboss.deployment.DeploymentException?: No PropertyDescriptor? for attribute:securityDomain; - nested throwable: (java.beans.IntrospectionException?: No PropertyDescriptor? for attribute:securityDomain) JBoss 1.0 5 This is due to a change in how the jmx descriptor names are stored with case preserved. To work around this isssue simply use all lower case attribute names. <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securitydomain="java:/jaas/jmx-console"/> </interceptors> Secure the JMX Invokers (Authentication Only) JBoss 1.0 6 Secure the JMX Invokers (Authorization/Access Control) 4.1. Introduction In the last chapter, you enabled authentication on the JMX invoker. This would basically restrict access to just the actors that have identified themselves. There may need for fine-grained access control on the JMX invoker. You may want to restrict access to users who have certain roles. 4.2. Enable Access Control or Authorization for the JMX Invoker The JMX invoker can be made to authorize all requests. 4.2.1. Modifications Required (Use Case 1) You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server configuration (eg: default configuration). Please add an additional interceptor to look as follows: <operation> <description>The detached invoker entry point</description> <name>invoke</name> <parameter> <description>The method invocation context</description> <name>invocation</name> <type>org.jboss.invocation.Invocation</type> </parameter> <return-type>java.lang.Object</return-type> <!-- Uncomment to require authenticated users --> <descriptors> <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securityDomain="java:/jaas/jmx-console"/> <interceptor code="org.jboss.jmx.connector.invoker.AuthorizationInterceptor" authorizingClass="org.jboss.jmx.connector.invoker.RolesAuthorization"/> </interceptors> </descriptors> </operation>
  • 197. 441 | P a g e The AuthorizationInterceptor will use the JAAS authenticated subject that has been created by the Authentication- Interceptor and will allow access to users who have a role called as "JBossAdmin". 4.2.2. Modifications Required (Use Case 2) JBoss 1.0 7 You will need to edit the jmx-invoker-service.xml file under the deploy directory of your server configuration (eg: default configuration). Please add an additional interceptor to look as follows: <operation> <description>The detached invoker entry point</description> <name>invoke</name> <parameter> <description>The method invocation context</description> <name>invocation</name> <type>org.jboss.invocation.Invocation</type> </parameter> <return-type>java.lang.Object</return-type> <!-- Uncomment to require authenticated users --> <descriptors> <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securityDomain="java:/jaas/jmx-console"/> <interceptor code="org.jboss.jmx.connector.invoker.AuthorizationInterceptor" authorizingClass="org.jboss.jmx.connector.invoker.ExternalizableRolesAuthorization"/> </interceptors> </descriptors> </operation> This use case handles cases where you can configure the various roles that an user can have to gain access. The previous use case just handled the case when the users had a role called as "JBossAdmin". In this case, you will need to provide a properties file called as "jmx-invoker-roles.properties" in a jar file or place
  • 198. 442 | P a g e Integrate security infrastructures with JBossSX JBossSX uses JAAS to integrate application servers and security infrastructures Summary The current Enterprise JavaBean and Servlet specifications omit integration between the application server and existing security infrastructures. This article describes how version 3.2.x of the open source JBoss application server security extension project (JBossSX) uses Java Authentication and Authorization Service (JAAS) login modules as its integration API. JAAS allows for integration without programming, using security infrastructures that use Java Database Connectivity, the lightweight directory access protocol (LDAP), or properties-based login modules bundled with JBoss. For security infrastructures that do not support those access mechanisms, integration entails writing a simple custom login module. key aspect of the Java 2 Platform, Enterprise Edition (J2EE) component models is a simple declarative security model. The Enterprise JavaBean (EJB) 2.0 and Servlet 2.3 specifications support a role-based declarative security model that externalizes security from application logic and decouples the application security roles from the deployment environment's security implementation. At the application level, the ejb-jar.xml and web.xml deployment descriptors define security. Although this model allows for an independent, simple specification of the application server's security requirements, mapping the application-defined security onto the deployment environment security's infrastructure is an application- server-specific activity. Thus, configuring a J2EE application's security requires proprietary application server APIs or tools. One such tool is the Java Authentication and Authorization Service (JAAS). In this article, I describe how the JBoss security extension, JBossSX, uses the standard JAAS to integrate with the deployment environment's security infrastructure. By configuring the JAAS login modules bundled with JBoss, you can complete the integration without custom programming. If the bundled login modules don't work with your security infrastructure, you can simply write a custom login module that does; I'll show you how in this article. The key topics that I cover here include:  The J2EE declarative security model  The key JAAS classes  Details of how the JBossSX security manager uses JAAS in its implementation of the J2EE declarative security model  Details of how you can write a custom JAAS login module for JBoss I also include a secure enterprise application example that demonstrates the declarative security model and the configuration of JAAS login modules to integrate the deployment environment's security.
  • 199. 443 | P a g e J2EE declarative security overview The first step to securing a J2EE application is to specify the application security requirements via the standard J2EE deployment descriptors. You secure access to EJBs and Web components in an enterprise application by using the ejb-jar.xml and web.xml deployment descriptors. Figures 1 and 2 illustrate the security-related elements in the EJB 2.0 and Servlet 2.2 deployment descriptors, respectively.
  • 200. 444 | P a g e Figure 1. The EJB 2.0 deployment descriptor security elements Together, these security elements define the bean author and application assembler's view of an enterprise application's security requirements.
  • 201. 445 | P a g e Figure 2. The Servlet 2.2 deployment descriptor security elements So that you'll have sufficient background for the example presented later in this article, I'll first review the security elements pictured in Figures 1 and 2. Enterprise beans security references As you can see in Figure 1, enterprise beans may declare one or more security-role-ref elements. An EJB can access the caller principal and ask if the caller belongs to a role by name. The caller principal is obtained from theEJBContext.getCallerPrincipal() method as a java.security.Principal instance. Using the EJBContext.isCallerInRole(String) method, an EJB checks if a caller is in a role that has been declared with a security-role-ref element. The role-name element value must link to a security role in the assembly-descriptor section of ejb-jar.xml through the role-link element. You typically use isCallerInRole() to perform a security check that cannot be defined using method permissions. See section 21.2.5 of the EJB 2.0 Specification for more details on accessing the caller's security context.
  • 202. 446 | P a g e Enterprise beans security identity Figure 1 also shows that enterprise beans can optionally declare a security-identity element. New to EJB 2.0 is the ability to specify what identity an EJB should use when it invokes methods on other EJBs. The application assembler uses the security-identity element to indicate that the current caller's identity should be propagated by using a use-caller-identity element as security-identity's value. Alternatively, the application assembler can use the run-as element with thesecurity-identity's value as role-name to specify that EJB calls are performed with the security role given by the role-name value. Note that this does not change the caller's identity as seen by EJBContext.getCallerPrincipal(). Rather, the caller's security roles are set to the single role specified by the run-as/role-name element value. You can use a run-as identity to keep external clients from accessing internal EJBs. To do that, assign the internal EJB method permissions that restrict access to a role never assigned to an external client, and use the restricted role as the run- as/role-name element value for EJBs that use the internal EJB. Assembly descriptor security roles The security role referenced by either security-role-ref or security-identity elements needs to map to one of the application's declared roles. An application assembler defines logical security roles by adding security-role elements to theassembly-descriptor element. In JBoss, a security-role is only used to map an EJB security-role-ref/role-name to the logical role to which the EJB role name refers. The user's assigned roles are a dynamic function of the application's security manager, as you will see when I discuss the JBossSX implementation. JBoss does not require defined security-roles to identify method permissions. Therefore, you should specify a security-role element for every role used in the method- permission element for portability across application servers and for deployment descriptor maintenance. Assembly descriptor method permissions An application assembler can set the roles that are allowed to invoke an EJB's home and component interface methods through method-permission elements. Each method-permission element contains one or more role-name elements that define the logical roles allowed access to one or more EJB methods as identified by method elements. With EJB 2.0, you can now specify the unchecked element instead of the role-name element to declare that an authenticated user can access one or more methods. In addition, you can declare that no one should have access to a method with the exclude-list element. For method syntax, see section 21.3.2 of the EJB 2.0 Specification. An example EJB deployment descriptor The following ejb-jar.xml descriptor illustrates the use of EJB security elements and is the descriptor used in the article example: <ejb-jar> <display-name>SecurityTests</display-name> <enterprise-beans> <session> <description>A trivial stateless session echo bean</description> <ejb-name>PublicSession</ejb-name> <home>org.jboss.docs.jaas.howto.SessionHome</home>
  • 203. 447 | P a g e <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-class>org.jboss.docs.jaas.howto.StatelessSessionBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <ejb-ref> <ejb-ref-name>ejb/PrivateSession</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-link>PrivateSession</ejb-link> </ejb-ref> <security-identity> <run-as> <role-name>InternalUser</role-name> </run-as> </security-identity> </session> <session> <description>A trivial stateful session echo bean</description> <ejb-name>PrivateSession</ejb-name> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-class>org.jboss.docs.jaas.howto.StatefulSessionBean</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> <assembly-descriptor> <security-role> <role-name>Coder</role-name> </security-role> <security-role> <role-name>Echo</role-name> </security-role> <security-role> <role-name>InternalUser</role-name> </security-role> <method-permission> <role-name>Echo</role-name> <method> <ejb-name>PublicSession</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>InternalUser</role-name> <method>
  • 204. 448 | P a g e <ejb-name>PrivateSession</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>Coder</role-name> <method> <ejb-name>PublicSession</ejb-name> <method-name>create</method-name> </method> <method> <ejb-name>PublicSession</ejb-name> <method-name>remove</method-name> </method> </method-permission> <method-permission> <unchecked/> <method> <ejb-name>PublicSession</ejb-name> <method-name>noop</method-name> </method> </method-permission> <exclude-list> <description>Methods that cannot be used in this deployment</description> <method> <ejb-name>PublicSession</ejb-name> <method-name>restricted</method-name> </method> </exclude-list> </assembly-descriptor> </ejb-jar> Web application security constraints In a Web application, security is defined by the roles allowed access to content; a URL pattern identifies the protected content. For example, the web.xml descriptor fragment below indicates that any URL lying under the Web application's/restricted path requires an AuthorizedUser role: <web-app> ... <security-constraint> <web-resource-collection> <web-resource-name>Secure Content</web-resource-name> <url-pattern>/restricted/*</ url-pattern></ <web-resource-collection> <auth-constraint>
  • 205. 449 | P a g e <role-name>AuthorizedUser</role-name> </auth-constraint> </security-constraint> ... <security-role> <description>The role required to access restricted content</description> <role-name>AuthorizedUser</role-name> </security-role> </web-app> The security-role-ref and security-role elements are equivalent to their EJB counterparts. Specify the security domain in JBoss The J2EE security elements I have covered describe only the security requirements from the application's perspective. Since J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The EJB specification omits these application-server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model. Figure 3 shows the JBoss-specific EJB and Web application deployment descriptor's security-related elements.
  • 206. 450 | P a g e Figure 3. The JBoss-specific EJB and Web deployment descriptor security elements Use the security-domain element to identify the Java Naming and Directory Interface (JNDI) name of the security manager interface implementation that JBoss uses for the EJB and Web containers. You may specify security-domain as an EJB-level element to only set security for one or more EJBs when security- domain is not a top-level element, or when security-domain is a top-level element and you want to
  • 207. 451 | P a g e override it. The security-proxy element identifies a custom security interceptor that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. I won't go into detail about that JBoss-specific feature, as this article focuses on using JAAS to implement the standard declarative security model. A JBoss security manager implementation requires the org.jboss.security.EJBSecurityManager and org.jboss.security.RealmMapping interfaces presented in Figure 4. Figure 4. JBoss security manager interfaces For the remainder of this article, I focus on the JBossSX org.jboss.security.plugins.JaasSecurityManager, a JAAS-based implementation of the security manager interfaces. But first, I'll present a brief introduction to JAAS.
  • 208. 452 | P a g e What is JAAS? The JAAS 1.0 API consists of a set of Java packages for the user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with the current JDK 1.4 beta. As the JBossSX framework only uses the authentication aspect of JAAS to implement the declarative-role- based J2EE security model, this introduction focuses only on that topic. For a more comprehensive overview, see the JAAS material in Resources. I took much of this section's material from the JAAS 1.0 Developers Guide. JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can succeed without changing the JBossSX security manager. Authentication consists of instantiating a LoginContext object, which passes the name of a Configuration entry to determine which LoginModule will be created. The LoginModules define the authentication technology. LoginModules often use a username and password to verify identity, but any form of identity and identity verification will work. The JAAS Core Classes The JAAS core classes break down into three categories: common, authentication, and authorization. The list below presents the common and authentication classes, since the JBossSX functionality covered in this article uses only these classes.  Common classes: o Subject (javax.security.auth.Subject) o Principal (java.security.Principal)  Authentication classes: o Callback (javax.security.auth.callback.Callback) o CallbackHandler (javax.security.auth.callback.CallbackHandler) o Configuration (javax.security.auth.login.Configuration) o LoginContext (javax.security.auth.login.LoginContext) o LoginModule (javax.security.auth.spi.LoginModule) Subject and Principal To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term Subject to represent the request's source. Subject is the key JAAS class; it represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 java.security.Principal interface to represent a principal.
  • 209. 453 | P a g e Once authenticated, a Subject is populated with associated identities, or Principals. A Subject may have many Principals. For example, a person may have a name Principal (John Doe) and a social security number Principal (123-45-6789), both of which help distinguish it from other Subjects. To retrieve the Principals associated with a Subject, two methods are available: public Set getPrincipals(); public Set getPrincipals(Class c); The first method returns all Principals contained in the Subject. The second method only returns those Principals that are instances of Class c or Class c's subclasses. An empty set will return if the Subject has no associated Principals. Note that the java.security.acl.Group interface is a subinterface of java.security.Principal, and so an instance in the Principals set may represent a logical grouping of other principals or groups of principals. Authentication classes The following steps will authenticate a Subject: 1. An application instantiates a LoginContext. 2. The LoginContext consults a Configuration to load all the LoginModules configured for that application. 3. The application invokes the LoginContext's login method. 4. The login method invokes all the loaded LoginModules. Each LoginModule attempts to authenticate the Subject. Upon success, LoginModules associate relevant Principals and credentials with the Subject. 5. The LoginContext returns the authentication status to the application. 6. If authentication succeeds, the application retrieves the authenticated Subject from the LoginContext. The LoginContext class provides the basic methods for authenticating Subjects and offers a way to develop an application independent of the underlying authentication technology. The LoginContext consults a Configuration to determine the authentication services -- or LoginModules -- configured for a particular application. Therefore, you can plug in different LoginModules under an application without changing the application itself. All LoginContext constructors share a common parameter: name. The LoginContext uses name to index the login Configuration. Actual authentication occurs with a call to the following method: public void login() throws LoginException; When login() invokes, all the configured LoginModules' respective login methods invoke to perform authentication. If authentication succeeds, the following method can retrieve the authenticated Subject (which may now hold Principals, public credentials, and private credentials):
  • 210. 454 | P a g e public Subject getSubject(); To log out a Subject and remove its authenticated Principals and credentials, use the method below: public void logout() throws LoginException; The following code sample demonstrates the calls necessary to authenticate a Subject using the LoginModules configured under the name jwdomain: // let the LoginContext instantiate a new Subject LoginContext lc = new LoginContext("jwdomain"); try { // authenticate the Subject lc.login(); System.out.println("authentication successful"); // get the authenticated Subject Subject subject = lc.getSubject(); ... // all finished -- logout lc.logout(); } catch (LoginException le) { System.out.println("authentication unsuccessful"); le.printStackTrace(); } With the LoginModule interface, developers can implement different authentication technologies that can be plugged under an application. For example, one LoginModule may perform username/password- based authentication, while others may interface to hardware devices such as smart card readers or biometric authenticators. To instantiate a LoginModule, a LoginContext expects each LoginModule to provide a public constructor that takes no arguments. Then, to initialize aLoginModule with the relevant information, a LoginContext calls the LoginModule's initialize() method. The subject argument is guaranteed to be nonnull. The signature of the initialize() method is: void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options); The login() method starts authentication; its signature is:
  • 211. 455 | P a g e boolean login() throws LoginException; An example method implementation might prompt the user for a username and password, and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices or simply extract user information from the underlying operating system. The validation of user identity by each LoginModule is considered Phase 1 of JAAS authentication. Authentication completes when theLoginContext calls: boolean commit() throws LoginException; If Phase 1 succeeds, then the commit() method continues with Phase 2: associating relevant Principals, public credentials, or private credentials with the Subject. If Phase 1 fails, then boolean commit() throws LoginException; removes any previously stored authentication state, such as usernames or passwords. The following method halts authentication: boolean abort() throws LoginException; Typical implementations of that method also clean up previously stored authentication state. The following method logs out a Subject: boolean logout() throws LoginException; That method removes the Principals and credentials originally associated with the Subject during the commit operation. Credentials should be destroyed upon removal. When a LoginModule must communicate with the user to obtain authentication information, it uses a CallbackHandler. Applications implement the CallbackHandler interface and pass it to the LoginContext, which forwards it directly to the underlying LoginModules. LoginModules use the CallbackHandler both to gather input from users (such as a password or smart-card PIN number) and to supply information to users (such as status information). By allowing the application to specify the CallbackHandler, underlying LoginModules remain independent from the different ways applications interact with users. For example, a CallbackHandler's implementation for a GUI application might display a window to solicit user input. On the other hand, a CallbackHandler's implementation for a non-GUI environment, such as an application server, might simply obtain credential information using an application server API. The CallbackHandler interface has one method to implement: void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
  • 212. 456 | P a g e The last authentication class I will cover is the Callback interface. It is a tagging interface that features several implementations, including NameCallback and PasswordCallback. LoginModules use a Callback to request information required by the authentication mechanism the LoginModule encapsulates. LoginModules pass an array of Callbacks directly to the CallbackHandler's handle method during the authentication's login phase. Inside the JBossSX JaasSecurityManager Now let's return to the JBossSX security manager implementation. I'll start with an overview of how the JBoss security components interact. Figure 5 shows the main components and how the security domain assigned in the JBoss EJB and Web deployment descriptors ties them together.
  • 213. 457 | P a g e Figure 5. Security component interaction overview Figure 5 depicts an enterprise application that contains both EJBs and Web content secured under the security domain jwdomain. The EJB and Web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the security domain in the jboss.xml and jboss-web.xml descriptors is used to obtain the security manager instance associated with the container and used by the security interceptor. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container.
  • 214. 458 | P a g e For the JBossSX default security manager implementation, shown in Figure 5 as the JaasSecurityMgr component, security checks are based on the information associated with the javax.security.auth.Subject instance. That instance results from executing the JAAS login modules configured under the name matching the security-domain element value. We will drill into the JaasSecurityManager implementation and its use of JAAS in the following sections. The JAAS in JaasSecurityManager The default JBossSX security manager implementation org.jboss.security.plugins.JaasSecurityManager uses the JAAS packages to implement its behavior. In particular, its behavior derives from the login module (javax.security.auth.spi.LoginModule) whose configuration entry name matches the security domain to which the JaasSecurityManager has been assigned. The login module implements the security domain's principal authentication and role- mapping behavior. Hence, you can use the JaasSecurityManager across different security domains simply by plugging in different login module configurations for the domains. The security check Consider a client that invokes a method on an EJB configured to use a JaasSecurityManager instance for security. Figure 6 illustrates some components involved in the security check; the security check's key steps are outlined below the figure.
  • 215. 459 | P a g e Figure 6. EJB access authentication procedure 1. The client first has to perform a JAAS login to establish the principal and credentials for authentication, which is how clients establish their login identities in JBoss. Support for presenting the login information via the JNDIInitialContext properties is not provided. A JAAS login entails creating a javax.security.auth.login.LoginContext instance and passing the configuration's name to use. In Figure 6, the configuration name is other. This one-time login associates the login principal and credentials with all subsequent EJB method invocations. Note that the process might not authenticate the user. The nature of the client-side login depends on the login module configuration that the client uses. In Figure 6, the other client-side login configuration entry is set up to use the ClientLoginModule (org.jboss.security.ClientLoginModule); that module does not perform client-side authentication, but simply binds the username and password to the JBoss EJB invocation layer for later authentication on the server. 2. Later, the client obtains an EJB's home interface and attempts to create a bean, resulting in a home interface method invocation sent to the JBoss server. The invocation includes the method arguments passed by the client along with the user identity and credentials from the client-side JAAS login. 3. On the server side, the security check first requires authentication of the user invoking the call, which, as on the client side, involves a JAAS login. The security domain under which the EJB is secured determines the choice of login modules. The security domain's name is used as the login configuration entry name passed to the LoginContext constructor. In Figure 6, the EJB security
  • 216. 460 | P a g e domain is jwdomain. If the JAAS login authenticates the user, a JAAS Subject is created that contains the following in its PrincipalsSet: o A java.security.Principal that corresponds to the client identity. o A java.security.acl.Group named Roles that contains the role names from the application domain to which the user has been assigned. org.jboss.security.SimplePrincipal objects are used to represent the role names; SimplePrincipalis a simple string-based implementation of Principal. These roles are used to validate the roles assigned to methods in ejb-jar.xml and the EJBContext.isCallerInRole(String) method. o An optional java.security.acl.Group named CallerPrincipal, which contains a single org.jboss.security.SimplePrincipal that corresponds to the identity of the application domain's caller. The CallerPrincipal sole group member is the value returned by the EJBContext.getCallerPrincipal() method. The purpose of this mapping is to allow a Principal known in the deployment security environment to map to a Principal with a name known to the application. In the absence of a CallerPrincipal mapping the deployment security environment, Principal returns. 4. The final step of the security check is to verify the authenticated user has permission to invoke the requested method. Doing this requires the following steps: 1. Obtain the names of the roles allowed to access the EJB method from the EJB container. The names are ejb-jar.xml descriptor role-name elements of all method- permission elements containing the invoked method. 2. If no roles have been assigned, then access to the method is denied. Otherwise, the JaasSecurityManager.doesUserHaveRole(Principal, Set) method invokes to see if the caller principal has one of the assigned role names. The method iterates through the role names and checks if the user javax.security.auth.Subject's Roles group contains a SimplePrincipal with the assigned role name. Access is allowed if any role name is a member of the Roles group; access is denied if none of the role names are members. 3. If the EJB was configured with a custom security proxy, the method invocation is delegated to it. If the security proxy wants to deny access to the caller, it will throw a SecurityException. If no SecurityException is thrown, access to the EJB method is allowed; the SecurityInterceptor passes the method invocation to the next container interceptor. Note that you can configure the JaasSecurityManager to use a cache of authentication information so that a JAAS login is not performed on every method invocation. If no cache is specified in the JaasSecurityManager's configuration, a timed cache is used by default. JBossSX custom login modules As shown above, the JBossSX security manager relies on the JAAS login modules for a security domain for authentication and authorization. The security manager authorizes users with the information stored in the Subject. If theLoginModules that ship with the JBoss server do not integrate into your existing security infrastructure, you can write a custom LoginModule that does. Writing a custom login module entails mapping your security infrastructure information onto a javax.security.auth.Subject using the usage pattern expected by JBossSX.
  • 217. 461 | P a g e JBossSX Subject usage patterns The JBossSX security manager inside the JBoss application server executes the login modules used by a security domain. Since these modules run inside the JBoss server, they are called server-side login modules. When you write a custom LoginModule, you write a server-side login module. To understand how server-side login modules are used in JBoss, you need to understand the JAAS Subject class's information storage features. You can obtain security information associated with a Subject in six ways:  java.util.Set getPrincipals()  java.util.Set getPrincipals(java.lang.Class c)  java.util.Set getPrivateCredentials()  java.util.Set getPrivateCredentials(java.lang.Class c)  java.util.Set getPublicCredentials()  java.util.Set getPublicCredentials(java.lang.Class c) For Subject identities and roles, JBossSX has selected the most natural choice: the PrincipalsSet obtained via getPrincipals() and getPrincipals(java.lang.Class). The usage pattern follows: User identities (username, social security number, employee ID, and so on) are stored as java.security.Principal objects in the Subject Principals set. The assigned user roles are also stored in the Principals set, but in named role sets usingjava.security.acl.Group instances. The Group interface -- a collection of Principals and/or Groups -- is a subinterface of java.security.Principal. Any number of role sets can be assigned to a Subject. Currently, the JBossSX framework uses two well-known role sets: Roles and CallerPrincipal. The Roles set is the Principal set for the named roles as known in the application domain under which the Subject has been authenticated. This role set is used by methods like theEJBContext.isCallerInRole(String), which EJBs use to see if the current caller belongs to the named application domain role. The security interceptor logic that performs method permission checks also uses the role set. The CallerPrincipal role set consists of the single Principal identity assigned to the user in the application domain. The EJBContext.getCallerPrincipal() method uses CallerPrincipal to allow the application domain to map from the operation environment identity to a user identity suitable for the application. If a Subject does not have a CallerPrincipal role set, the application identity is the operational environment identity. Support for the Subject usage pattern To simplify correct implementation of the Subject usage patterns described in the preceding section, JBossSX includes an abstract login module that handles the population of the authenticated Subject with a template pattern. Theorg.jboss.security.auth.spi.AbstractLoginModule class provides concrete implementations of the javax.security.auth.spi.LoginModule interface and offers abstract methods for the key tasks specific to an operation environment security infrastructure. The key details of the class are: package org.jboss.security.auth.spi; /** This class implements the common functionality required for a JAAS server-side LoginModule and implements the JBossSX standard Subject usage pattern of storing identities and roles. Subclass this module to create your own custom LoginModule and override the login(), getRoleSets(), and getIdentity()
  • 218. 462 | P a g e methods. */ public abstract class AbstractServerLoginModule implements javax.security.auth.spi.LoginModule { protected Subject subject; protected CallbackHandler callbackHandler; protected Map sharedState; protected Map options; ... /** Initialize the login module. This stores the subject, callbackHandler and sharedState, and options for the login session. Subclasses should override if they need to process their own options. A call to super.initialize(...) must be made in the case of an override. @param subject, the Subject to update after a successful login. @param callbackHandler, the CallbackHandler that will be used to obtain the the user identity and credentials. @param sharedState, a Map shared between all configured login module instances @param options, @option password-stacking: if true, the login identity will be taken from the javax.security.auth.login.name value of the sharedState map, and the proof of identity from the javax.security.auth.login.password value of the sharedState map. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { ... } /** Looks for javax.security.auth.login.name and javax.security.auth.login.password values in the sharedState map if the useFirstPass option was true and returns true if they exist. If they do not or are null, this method returns false. Subclasses should override to perform the required credential validation steps. */ public boolean login() throws LoginException { ... } /** Overridden by subclasses to return the Principal that corresponds to the user primary identity. */ abstract protected Principal getIdentity(); /** Overridden by subclasses to return the Groups that correspond to the role sets assigned to the user. Subclasses should create at least a Group named "Roles" that contains the roles assigned to the user. A second common group is "CallerPrincipal," which provides the application identity of the user rather than the security domain identity.
  • 219. 463 | P a g e @return Group[] containing the sets of roles */ abstract protected Group[] getRoleSets() throws LoginException; } As an alternate base login module, the UsernamePasswordLoginModule further simplifies custom login module implementation by using the string-based username as the user identity and the char[] password as the authentication credential. It also maps anonymous users (indicated by a null username and password) to a Principal. You would typically support anonymous users by setting the Principal that EJBContext.getCallerPrincipal() returns when an unsecure servlet or JavaServer Page (JSP) calls an EJB. The key methods of UsernamePasswordLoginModule are: package org.jboss.security.auth.spi; /** An abstract subclass of AbstractServerLoginModule that imposes a an identity == String username, credentials == String password view on the login process. Subclasses override the getUsersPassword() and getUsersRoles() methods to return the expected password and roles for the user. */ public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule { /** The login identity */ private Principal identity; /** The proof of login identity */ private char[] credential; /** The principal to use when a null username and password are seen */ private Principal unauthenticatedIdentity; ... /** Override the superclass method to look for an unauthenticatedIdentity property. This method first invokes the super version. @param options, @option unauthenticatedIdentity: the name of the principal to assign and authenticate when a null username and password are seen. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); // Check for unauthenticatedIdentity option. String name = (String) options.get("unauthenticatedIdentity"); if( name != null ) unauthenticatedIdentity = new SimplePrincipal(name); }
  • 220. 464 | P a g e ... /** A hook that allows subclasses to change the validation of the input password against the expected password. This version checks that neither inputPassword or expectedPassword are null and that inputPassword.equals(expectedPassword) is true; @return true if the inputPassword is valid, false otherwise. */ protected boolean validatePassword(String inputPassword, String expectedPassword) { if( inputPassword == null || expectedPassword == null ) return false; return inputPassword.equals(expectedPassword); } /** Get the expected password for the current username available via the getUsername() method. This is called from within the login() method after the CallbackHandler has returned the username and candidate password. @return the valid password String */ abstract protected String getUsersPassword() throws LoginException; } Write a custom login module When writing a custom login module that integrates with your security infrastructure, you should start by subclassing org.jboss.security.auth.spi.AbstractLoginModule or one of its subclasses to ensure that your login module provides the authenticated Principal information in the form expected by the JBossSX security manager. When subclassing the AbstractLoginModule, you need to override:  void initialize(Subject, CallbackHandler, Map, Map) if you have custom options to parse.  boolean login() to perform the authentication activity.  Principal getIdentity() to return the Principal object for the user authenticated by the log() step.  Group[] getRoleSets() to return at least a Group named Roles that contains the roles assigned to the Principal authenticated during login(). A second common group is CallerPrincipal; it provides, if necessary, the user's application identity rather than the security domain identity. When subclassing the UsernamePasswordLoginModule, a subclass of AbstractLoginModule, write:  void initialize(Subject, CallbackHandler, Map, Map) if you have custom options to parse.  String getUsersPassword() to return the expected password for the current username available via the getUsername() method. The getUsersPassword() method is called from within login() after the CallbackHandler returns the username and candidate password.  Group[] getRoleSets() to return at least a Group named Roles that contains the roles assigned to the Principal authenticated during login(). A second group CallerPrincipal provides, if necessary, the user's application identity instead of the security domain identity.
  • 221. 465 | P a g e An example Want to see the security features in action? The source code for the example is included in the article archive in the jw-0831-jaas/example directory and I'll walk you through it. You will set up and deploy the example to a JBoss/Tomcat 3.2.1 bundle. You'll also look at the application from the secure and unsecured servlet accessing a secured EJB to demonstrate many of the security features presented in this article. To deploy the example application:  You need the Ant build tool. If you don't already have it, see the Ant homepage. I am using 1.5.4.  Next, download the JBoss/Tomcat 3.2.3 bundle from SourceForge and unarchive it. At the time of this writing, the current JBoss/Tomcat bundle is jboss-3.2.3.zip and it unarchives to create a jboss-3.2.3 directory.  The examples are located in the jw-0831-jaas/example subdirectory of this archive.  Edit the jboss.dist property that specifies the JBoss/Tomcat bundle location in the build.xml file, or override the property on the command line to Ant by creating an ant.properties file in the examples root directory. The default location is /tmp/jboss-3.2.3, so if you unarchive the JBoss/Tomcat bundle in your /tmp directory, you're ready to go.  Build and deploy the example ears by running Ant within the example directory. Your output should look something like this: [starksm@dedicated74 example]$ ant Buildfile: build.xml validate: fail_if_not_valid: init: [echo] Using jboss.dist=/tmp/jboss-3.2.3 [echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss- 3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes compile: [mkdir] Created dir: /tmp/jaashowto/example/output/classes [javac] Compiling 7 source files to /tmp/jaashowto/example/output/classes jar1: [mkdir] Created dir: /tmp/jaashowto/example/output/META-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [jar] Building jar: /tmp/jaashowto/example/output/ssbean1.jar war1: [mkdir] Created dir: /tmp/jaashowto/example/output/web/WEB- INF/classes/org/jboss/docs/jaas/howto [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-
  • 222. 466 | P a g e INF/classes/org/jboss/docs/jaas/howto [jar] Building jar: /tmp/jaashowto/example/output/tutorial1.war ear1: [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [jar] Building jar: /tmp/jaashowto/example/output/tutorial1.ear jar2: [delete] Deleting directory /tmp/jaashowto/example/output/META-INF [mkdir] Created dir: /tmp/jaashowto/example/output/META-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [jar] Building jar: /tmp/jaashowto/example/output/ssbean2.jar war2: [delete] Deleting directory /tmp/jaashowto/example/output/web [mkdir] Created dir: /tmp/jaashowto/example/output/web/WEB- INF/classes/org/jboss/docs/jaas/howto [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB-INF [copy] Copying 1 file to /tmp/jaashowto/example/output/web/WEB- INF/classes/org/jboss/docs/jaas/howto [jar] Building jar: /tmp/jaashowto/example/output/tutorial2.war ear2: [copy] Copying 1 file to /tmp/jaashowto/example/output/META-INF [jar] Building jar: /tmp/jaashowto/example/output/tutorial2.ear ears: [mkdir] Created dir: /tmp/jboss-3.2.3/server/jaas_howto [copy] Copying 130 files to /tmp/jboss-3.2.3/server/jaas_howto [copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/conf [copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/deploy [copy] Copying 1 file to /tmp/jboss-3.2.3/server/jaas_howto/deploy BUILD SUCCESSFUL Total time: 4 secondsTotal time: 2 seconds  If you see something similar to this: [starksm@banshee example]$ ant Buildfile: build.xml validate: fail_if_not_valid: BUILD FAILED
  • 223. 467 | P a g e file:/tmp/jaashowto/example/build.xml:28: jboss.dist=/tmp/jboss-3.2.3 is not a valid JBoss dist directory you need to correct the jboss.dist property's value in the Ant build.xml file in the example directory as indicated in the previous step. <>Now start the JBoss server with the jaas_howto configuration, which contains the JAAS login configuration file and was created by the Ant build process. To start JBoss, go to the jboss- 3.2.3/bin directory and execute the run.sh orrun.bat script as appropriate for your operating system, passing in the jaas_howto config name. Here's an example from a Linux system with key output emphasized: <> [starksm@dedicated74 bin]$ ./run.sh -c jaas_howto =============================================================================== = JBoss Bootstrap Environment JBOSS_HOME: /tmp/jboss-3.2.3 JAVA: /usr/java/j2sdk1.4.2_04/bin/java JAVA_OPTS: -server -Dprogram.name=run.sh CLASSPATH: /tmp/jboss-3.2.3/bin/run.jar:/usr/java/j2sdk1.4.2_04/lib/tools.jar =============================================================================== = 23:19:41,847 INFO [Server] Starting JBoss (MX MicroKernel)... 23:19:41,849 INFO [Server] Release ID: JBoss [WonderLand] 3.2.3 (build: CVSTag=JBoss_3_2_3 date=200311301445) 23:19:41,850 INFO [Server] Home Dir: /tmp/jboss-3.2.3 23:19:41,850 INFO [Server] Home URL: file:/tmp/jboss-3.2.3/ 23:19:41,850 INFO [Server] Library URL: file:/tmp/jboss-3.2.3/lib/ 23:19:41,851 INFO [Server] Patch URL: null 23:19:41,852 INFO [Server] Server Name: jaas_howto 23:19:41,852 INFO [Server] Server Home Dir: /tmp/jboss-3.2.3/server/jaas_howto 23:19:41,852 INFO [Server] Server Home URL: file:/tmp/jboss-3.2.3/server/jaas_howto/ 23:19:41,853 INFO [Server] Server Data Dir: /tmp/jboss-3.2.3/server/jaas_howto/data 23:19:41,853 INFO [Server] Server Temp Dir: /tmp/jboss-3.2.3/server/jaas_howto/tmp 23:19:41,854 INFO [Server] Server Config URL: file:/tmp/jboss-3.2.3/server/jaas_howto/conf/ 23:19:41,854 INFO [Server] Server Library URL: file:/tmp/jboss-3.2.3/server/jaas_howto/lib/ 23:19:41,854 INFO [Server] Root Deployment Filename: jboss-service.xml
  • 224. 468 | P a g e 23:19:41,860 INFO [Server] Starting General Purpose Architecture (GPA)... 23:19:42,276 INFO [ServerInfo] Java version: 1.4.2_04,Sun Microsystems Inc. 23:19:42,276 INFO [ServerInfo] Java VM: Java HotSpot(TM) Server VM 1.4.2_04-b05,Sun Microsystems Inc. 23:19:42,276 INFO [ServerInfo] OS-System: Linux 2.4.20-9smp,i386 23:19:42,323 INFO [ServiceController] Controller MBean online 23:19:42,417 INFO [MainDeployer] Started jboss.system:service=MainDeployer ... 23:20:00,702 INFO [MainDeployer] Starting deployment of package: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial1.ear 23:20:00,704 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial1.ear 23:20:01,478 INFO [EjbModule] Deploying PublicSession 23:20:01,579 INFO [JaasSecurityManagerService] Created securityMgr=org.jboss.security.plugins.JaasSecurityManager@490342 23:20:01,580 INFO [JaasSecurityManagerService] setCachePolicy, c=org.jboss.util.TimedCachePolicy@1751a9e 23:20:01,581 INFO [JaasSecurityManagerService] Added example1, org.jboss.security.plugins.SecurityDomainContext@126ba64 to map 23:20:01,688 INFO [EjbModule] Deploying PrivateSession 23:20:01,934 INFO [StatelessSessionInstancePool] Started jboss.j2ee:jndiName=example1/PublicSession,plugin=pool,service=EJB 23:20:01,935 INFO [StatelessSessionContainer] Started jboss.j2ee:jndiName=example1/PublicSession,service=EJB 23:20:01,945 INFO [StatefulSessionInstancePool] Started jboss.j2ee:jndiName=example1/PrivateSession,plugin=pool,service=EJB 23:20:01,945 INFO [StatefulSessionFilePersistenceManager] Started null 23:20:01,945 INFO [StatefulSessionContainer] Started jboss.j2ee:jndiName=example1/PrivateSession,service=EJB 23:20:01,946 INFO [EjbModule] Started jboss.j2ee:module=ssbean1.jar,service=EjbModule 23:20:01,946 INFO [EJBDeployer] Deployed: file:/tmp/jboss- 3.2.3/server/jaas_howto/tmp/deploy/tmp29859tutorial1.ear-contents/ssbean1.jar 23:20:02,144 INFO [EmbeddedTomcatService] deploy, ctxPath=/jaas-example1, warUrl=file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29859tutorial1.ear- contents/tutorial1.war/ 23:20:02,475 INFO [Engine] SingleSignOnContextConfig[/jaas-example1]: Added certificates -> request attribute Valve 23:20:02,476 INFO [Engine] SingleSignOnContextConfig[/jaas-example1]: Configured an authenticator for method BASIC 23:20:02,502 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on class loader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@a937cd 23:20:02,502 INFO [Engine] StandardManager[/jaas-example1]: Seeding random number generator class java.security.SecureRandom
  • 225. 469 | P a g e 23:20:02,503 INFO [Engine] StandardManager[/jaas-example1]: Seeding of random number generator has been completed 23:20:02,504 INFO [Engine] StandardWrapper[/jaas-example1:default]: Loading container servlet default 23:20:02,505 INFO [Engine] StandardWrapper[/jaas-example1:invoker]: Loading container servlet invoker 23:20:03,020 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial1.ear 23:20:03,020 INFO [MainDeployer] Deployed package: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial1.ear 23:20:03,021 INFO [MainDeployer] Starting deployment of package: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial2.ear 23:20:03,022 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial2.ear 23:20:03,387 INFO [EjbModule] Deploying PublicSession 23:20:03,408 INFO [JaasSecurityManagerService] Created securityMgr=org.jboss.security.plugins.JaasSecurityManager@a6d35 23:20:03,409 INFO [JaasSecurityManagerService] setCachePolicy, c=org.jboss.util.TimedCachePolicy@87d472 23:20:03,409 INFO [JaasSecurityManagerService] Added example2, org.jboss.security.plugins.SecurityDomainContext@18ca663 to map 23:20:03,413 INFO [EjbModule] Deploying PrivateSession 23:20:03,449 INFO [StatelessSessionInstancePool] Started jboss.j2ee:jndiName=example2/PublicSession,plugin=pool,service=EJB 23:20:03,449 INFO [StatelessSessionContainer] Started jboss.j2ee:jndiName=example2/PublicSession,service=EJB 23:20:03,461 INFO [StatefulSessionInstancePool] Started jboss.j2ee:jndiName=example2/PrivateSession,plugin=pool,service=EJB 23:20:03,462 INFO [StatefulSessionFilePersistenceManager] Started null 23:20:03,462 INFO [StatefulSessionContainer] Started jboss.j2ee:jndiName=example2/PrivateSession,service=EJB 23:20:03,462 INFO [EjbModule] Started jboss.j2ee:module=ssbean2.jar,service=EjbModule 23:20:03,463 INFO [EJBDeployer] Deployed: file:/tmp/jboss- 3.2.3/server/jaas_howto/tmp/deploy/tmp29860tutorial2.ear-contents/ssbean2.jar 23:20:03,614 INFO [EmbeddedTomcatService] deploy, ctxPath=/jaas-example2, warUrl=file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29860tutorial2.ear- contents/tutorial2.war/ 23:20:04,011 INFO [Engine] SingleSignOnContextConfig[/jaas-example2]: Added certificates -> request attribute Valve 23:20:04,011 INFO [Engine] SingleSignOnContextConfig[/jaas-example2]: Configured an authenticator for method BASIC 23:20:04,034 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on class loader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@2264da 23:20:04,034 INFO [Engine] StandardManager[/jaas-example2]: Seeding random number
  • 226. 470 | P a g e generator class java.security.SecureRandom 23:20:04,035 INFO [Engine] StandardManager[/jaas-example2]: Seeding of random number generator has been completed 23:20:04,037 INFO [Engine] StandardWrapper[/jaas-example2:default]: Loading container servlet default 23:20:04,038 INFO [Engine] StandardWrapper[/jaas-example2:invoker]: Loading container servlet invoker 23:20:04,520 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial2.ear 23:20:04,521 INFO [MainDeployer] Deployed package: file:/tmp/jboss- 3.2.3/server/jaas_howto/deploy/tutorial2.ear ... 23:20:04,805 INFO [Server] JBoss (MX MicroKernel) [3.2.3 (build: CVSTag=JBoss_3_2_3 date=200311301445)] Started in 22s:945ms  The tutorial1.ear contents tutorial1.ear consists of a single Webpage, a secured servlet, an unsecured servlet, and two secured stateless session beans. As the servlet and session bean code is trivial, I'll leave its inspection as an exercise for you. The interesting aspect of the example is the deployment descriptors' security-related elements and the configuration of the JAAS login module associated with the security domain. tutorial1.ear's contents are shown below with the security-related filesemphasized: tutorial1.ear + META-INF |-- MANIFEST.MF |-- application.xml + ssbean1.jar |-- + META-INF |----- ejb-jar.xml |----- jboss.xml |-- + org/jboss/docs/jaas/howto |----- Session.class |----- SessionHome.class |----- PrivateSessionBean.class |----- PublicSessionBean.class |-- roles.properties |-- users.properties + tutorial1.war |-- + WEB-INF |----- web.xml |----- jboss-web.xml |----+ classes/org/jboss/docs/jaas/howto
  • 227. 471 | P a g e |------ EJBServlet.class |-- index.html We'll look at each file in turn. The tutorial1.ear/ssbean1.jar/META-INF/ejb-jar.xml descriptor The following ejb-jar.xml deployment descriptor declares the tutorial EJBs and their security requirements: <?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <display-name>SecurityTests</display-name> <enterprise-beans> <session> <description>A trivial stateless session echo bean</description> <ejb-name>PublicSession</ejb-name> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-class>org.jboss.docs.jaas.howto.PublicSessionBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <ejb-ref> <ejb-ref-name>ejb/PrivateSession</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-link>PrivateSession</ejb-link> </ejb-ref> <security-role-ref> <role-name>EchoUser</role-name> <role-link>Echo</role-link> </security-role-ref> <security-identity> <run-as> <role-name>InternalUser</role-name> </run-as> </security-identity> </session> <session> <description>A trivial stateful session echo bean</description> <ejb-name>PrivateSession</ejb-name> <home>org.jboss.docs.jaas.howto.SessionHome</home>
  • 228. 472 | P a g e <remote>org.jboss.docs.jaas.howto.Session</remote> <ejb-class>org.jboss.docs.jaas.howto.PrivateSessionBean</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> <security-role-ref> <role-name>InternalUser</role-name> <role-link>InternalUser</role-link> </security-role-ref> </session> </enterprise-beans> <assembly-descriptor> <security-role> <role-name>Coder</role-name> </security-role> <security-role> <role-name>Echo</role-name> </security-role> <security-role> <role-name>InternalUser</role-name> </security-role> <method-permission> <role-name>Echo</role-name> <method> <ejb-name>PublicSession</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>InternalUser</role-name> <method> <ejb-name>PrivateSession</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>Coder</role-name> <method> <ejb-name>PublicSession</ejb-name> <method-name>create</method-name> </method> <method> <ejb-name>PublicSession</ejb-name> <method-name>remove</method-name> </method> </method-permission> <method-permission> <unchecked/> <method>
  • 229. 473 | P a g e <ejb-name>PublicSession</ejb-name> <method-name>noop</method-name> </method> </method-permission> <exclude-list> <description>Methods that cannot be used in this deployment</description> <method> <ejb-name>PublicSession</ejb-name> <method-name>restricted</method-name> </method> </exclude-list> </assembly-descriptor> </ejb-jar> Items of note include:  The security-role-ref element is where the PublicSession bean declares an EchoUser role name, which links to the Echo role name. That element indicates that the PublicSession bean queries the EJBContext.isCallerInRole with a EchoUser role name string.  The security-identity/run-as/role-name InternalUser declaration indicates that a principal with a role named InternalUser handles any EJB calls made by the PublicSession bean.  The PrivateSession bean declares an InternalUser role name to indicate that the bean queries the EJBContext.isCallerInRole with an InternalUser role name string.  In the assembly-descriptor section, logical roles of Echo, Coder, and InternalUser are declared using security-role elements.  The Echo role receives permission to access any method in the PublicSession bean in the first method-permission element.  The InternalUser role receives permission to access any PrivateSession bean method in the second method-permission element.  The fourth method-permission element indicates that any authenticated user can call the PublicSession noop method with the unchecked element instead of a role-name element.  The exclude-list element declares that no one can call the PublicSession restricted method. The tutorial1.ear/ssbean1.jar/META-INF/jboss.xml descriptor The code below is the JBoss-server-specific EJB deployment descriptor: <?xml version="1.0" encoding="UTF-8"?> <jboss> <!-- All bean containers use this security manager by default --> <security-domain>java:/jaas/example1</security-domain> <enterprise-beans> <session> <ejb-name>PublicSession</ejb-name> <jndi-name>example1/PublicSession</jndi-name>
  • 230. 474 | P a g e </session> <session> <ejb-name>PrivateSession</ejb-name> <jndi-name>example1/PrivateSession</jndi-name> </session> </enterprise-beans> </jboss> This descriptor indicates that the security manager located at the JNDI name java:/jaas/example1 secures all EJBs in the ssbean1.jar. The JNDI name's final component (example1) determines which login modules are associated with the security domain. The tutorial1.ear/ssbean1.jar/roles.properties, users.properties files The org.jboss.security.auth.spi.UsersRolesLoginModule custom JAAS login module shipped with the JBossSX framework uses the roles.properties and users.properties files. This simple login module uses Java properties format files for mapping usernames to passwords and usernames to roles names. The roles.properties file maps a username to one or more role names using the format username[.RoleGroup]=role1_name[,role2_name,...]. A RoleGroup names the Group that will be created to hold given roles. With no specified RoleGroup, it defaults to Roles. Here's the roles.properties file for the example: # roles.properties java=Echo duke=Java,Coder java.CallerPrincipal=caller_java duke.CallerPrincipal=caller_duke The code above maps the username java to the role name Echo under the Roles RoleGroup, and the role name caller_java under the CallerPrincipal RoleGroup. The users.properties file maps a username to a user password. Here's theusers.properties file for the example: # users.properties java=echoman duke=javaman The above code maps the username java to the password echoman. The tutorial1.ear/tutorial1.war/WEB-INF/web.xml descriptor The following web.xml deployment descriptor declares the tutorial servlets and their EJB references and security requirements:
  • 231. 475 | P a g e <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <!-- ### Filters --> <filter> <filter-name>JaasLoginFilter</filter-name> <description>A filter that does a JAAS login to establish the identity to use for subsequent ejb calls. </description> <filter-class>org.jboss.docs.jaas.howto.JaasLoginFilter</filter-class> <init-param> <param-name>configName</param-name> <param-value>client-login</param-value> </init-param> <init-param> <param-name>username</param-name> <param-value>java</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>echoman</param-value> </init-param> </filter> <filter-mapping> <filter-name>JaasLoginFilter</filter-name> <url-pattern>/UnsecureServletWithLogin/*</url-pattern> </filter-mapping> <!-- ### Servlets --> <servlet> <servlet-name>SecureServlet</servlet-name> <servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class> </servlet> <servlet> <servlet-name>UnsecureServlet</servlet-name> <servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class> <run-as> <description>The anoymous user role</description> <role-name>nobody</role-name> </run-as> </servlet> <servlet> <servlet-name>UnsecureServletWithLogin</servlet-name> <description>A servlet whose mapping does not exist under the /restricted context that </description>
  • 232. 476 | P a g e <servlet-class>org.jboss.docs.jaas.howto.EJBServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SecureServlet</servlet-name> <url-pattern>/restricted/SecureServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>UnsecureServlet</servlet-name> <url-pattern>/UnsecureServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>UnsecureServletWithLogin</servlet-name> <url-pattern>/UnsecureServletWithLogin</url-pattern> </servlet-mapping> <!-- ### Security --> <security-constraint> <web-resource-collection> <web-resource-name>Restricted</web-resource-name> <description>Declarative security tests</description> <url-pattern>/restricted/*</url-pattern> <http-method>HEAD</http-method> <http-method>GET</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>DELETE</http-method> </web-resource-collection> <auth-constraint> <role-name>Echo</role-name> </auth-constraint> <user-data-constraint> <description>no description</description> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>JAAS Tutorial Servlets</realm-name> </login-config> <security-role> <description>A user allowed to invoke echo methods</description> <role-name>Echo</role-name> </security-role> <security-role> <description>A user with no permissions</description> <role-name>nobody</role-name> </security-role>
  • 233. 477 | P a g e <!-- ### EJB References (java:comp/env/ejb) --> <ejb-ref> <ejb-ref-name>ejb/SecuredEJB</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> </ejb-ref> <ejb-ref> <ejb-ref-name>ejb/PrivateEJB</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>org.jboss.docs.jaas.howto.SessionHome</home> <remote>org.jboss.docs.jaas.howto.Session</remote> </ejb-ref> </web-app> The security items of note include:  The security-constraint/web-resource-collection/url-pattern element declaration indicates that all content under /restricted must be secured for the indicated HTTP methods.  The auth-constraint/role-name element indicates that only users with an Echo role can access the content under /restricted.  The login-config/auth-method element with the BASIC value indicates that BASIC HTTP authorization will authenticate users attempting to access content under /restricted.  The SecureServlet requires authenticated access, since its servlet-mapping/url-pattern element is under the /restricted path.  The JaasLoginFilter servlet filter does a JAAS login to establish the caller identity given the the filter's username/passowrd init-param values using the JAAS login module configuration named by the configName init-param. The tutorial1.ear/tutorial1.war/WEB-INF/jboss-web.xml descriptor Here is the JBoss-server-specific Web application deployment descriptor: <?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>java:/jaas/example1</security-domain> <ejb-ref> <ejb-ref-name>ejb/SecuredEJB</ejb-ref-name> <jndi-name>example1/PublicSession</jndi-name> </ejb-ref> <ejb-ref> <ejb-ref-name>ejb/PrivateEJB</ejb-ref-name> <jndi-name>example1/PrivateSession</jndi-name> </ejb-ref> </jboss-web>
  • 234. 478 | P a g e This code indicates that the security manager located at the JNDI name java:/jaas/example1 handles security for all secured Web content. Since the security-domain element matches that used by the jboss.xml deployment descriptor, the same security manager secures the ear EJBs and Web content. The jboss-3.2.3/server/jaas_howto/conf/login-config.xml login configuration file The final security-related file is outside of tutorial1.ear. The login-config.xml file in the JBoss server configuration directory is the JAAS login configuration file. That file consists of named login configuration entries. Here's the version oflogin-config.xml that we will use for the tutorial: <!-- The JBoss server side JAAS login config file for the examples --> <policy> <!-- Used by clients within the application server VM such as mbeans and servlets that access EJBs. --> <application-policy name = "client-login"> <authentication> <login-module code = "org.jboss.security.ClientLoginModule" flag = "required"> </login-module> </authentication> </application-policy> <application-policy name = "example1"> <authentication> <!-- A properties file LoginModule that supports CallerPrincipal mapping --> <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> </login-module> </authentication> </application-policy> <application-policy name = "example2"> <authentication> <!-- A JDBC based LoginModule LoginModule options: dsJndiName: The name of the DataSource of the database containing the Principals, Roles tables principalsQuery: The prepared statement query equivalent to: "select Password from Principals where PrincipalID=?" rolesQuery: The prepared statement query equivalent to: "select Role, RoleGroup from Roles where PrincipalID=?" --> <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required"> <module-option name = "dsJndiName">java:/DefaultDS</module-option> <module-option name = "principalsQuery">select Password from Principals where
  • 235. 479 | P a g e PrincipalID=?</module-option> <module-option name = "rolesQuery">select Role, RoleGroup from Roles where PrincipalID=?</module-option> </login-module> </authentication> </application-policy> <!-- The security domain for the HSQLDB --> <application-policy name = "HsqlDbRealm"> <authentication> <login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule" flag = "required"> <module-option name = "principal">sa</module-option> <module-option name = "userName">sa</module-option> <module-option name = "password"></module-option> <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option> </login-module> </authentication> </application-policy> </policy> In the example file above, there are three entries, example1, example2 and HsqlDbRealm. The example1 entry contains a single login module whose class name is org.jboss.security.auth.spi.UsersRolesLoginModule, which is required for successful authentication. The UsersRolesLoginModule login module uses the users.properties and roles.properties files included in the ear as discussed earlier. The example2 entry contains a single login module whose class name isorg.jboss.security.auth.spi.DatabaseServerLoginModule. The DatabaseServerLoginModule configuration includes three login module options:  dsJndiName: gives the JNDI name of the javax.sql.DataSource binding for the database to use  principalsQuery: the sql query used to obtain the principal, password value  rolesQuery: the sql query used to obtain the princpal to role, role group name mapping. The role group name for the declarative roles must be 'Roles'. The HsqlDbRealm configuration defines how access to database connections are authorized. This configuration specifies that a fixed username and password are used by the JCA connection pools. Test the tutorial1.ear deployment from Web Client The example's final step is to test that the security constraints do in fact work. If your browser runs on the same host as the JBoss server, launch your Web browser and open the Web application index.html file located athttp://localhost:8080/jaas-example1/index.html. Figure 7 shows what the Webpage should look
  • 236. 480 | P a g e like. Each link is a test case, with the expected result shown as [PASS] or [FAIL] based on the specified security. We'll walk through links 1 and 4 to verify both a passing and failing test. Figure 7. The tutorial1.ear index.html page The first link corresponds to the call sequence illustrated in Figure 8. Each access or method invocation lists the role that the caller must possess for the access to be granted.
  • 237. 481 | P a g e Figure 8. The tutorial1.ear index.html page Traverse Link 1 to invoke the SecureServlet and enter java for the username and echoman as the password in the login dialog. Figure 9 shows the browser result. Figure 9. The expected browser result The JBoss server console should display the following output: 16:09:15,431 INFO [Engine] Authenticator[/jaas-example1]: Security checking request GET /jaas- example1/restricted/SecureServlet 16:09:15,441 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint [Restricted]' against GET /restricted/SecureServlet --> true 16:09:15,461 INFO [Engine] Authenticator[/jaas-example1]: Subject to constraint SecurityConstraint [Restricted] 16:09:15,481 INFO [Engine] Authenticator[/jaas-example1]: Calling checkUserData() 16:09:15,491 INFO [Engine] Authenticator[/jaas-example1]: User data constraint has no restrictions
  • 238. 482 | P a g e 16:09:15,511 INFO [Engine] Authenticator[/jaas-example1]: Calling authenticate() 16:09:15,711 INFO [Engine] Authenticator[/jaas-example1]: Failed authenticate() test 16:09:20,108 INFO [Engine] Authenticator[/jaas-example1]: Security checking request GET /jaas- example1/restricted/SecureServlet 16:09:20,128 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint [Restricted]' against GET /restricted/SecureServlet --> true 16:09:20,148 INFO [Engine] Authenticator[/jaas-example1]: Subject to constraint SecurityConstraint [Restricted] 16:09:20,168 INFO [Engine] Authenticator[/jaas-example1]: Calling checkUserData() 16:09:20,178 INFO [Engine] Authenticator[/jaas-example1]: User data constraint has no restrictions 16:09:20,188 INFO [Engine] Authenticator[/jaas-example1]: Calling authenticate() 16:09:20,228 INFO [Engine] Authenticator[/jaas-example1]: Authenticated 'java' with type 'BASIC' 16:09:20,238 INFO [Engine] Authenticator[/jaas-example1]: Calling accessControl() 16:09:20,258 INFO [Engine] Authenticator[/jaas-example1]: Successfully passed all security constraints 16:09:20,268 INFO [Engine] StandardContext[/jaas-example1]: Mapping contextPath='/jaas-example1' wi th requestURI='/jaas-example1/restricted/SecureServlet' and relativeURI='/restricted/SecureServlet' 16:09:20,288 INFO [Engine] StandardContext[/jaas-example1]: Trying exact match 16:09:20,298 INFO [Engine] StandardContext[/jaas-example1]: Mapped to servlet 'SecureServlet' with servlet path '/restricted/SecureServlet' and path info 'null' and update=true 16:09:20,398 INFO [STDOUT] PublicSessionBean.ejbCreate() called 16:09:20,408 INFO [STDOUT] PublicSessionBean.echo, arg=Hello 16:09:20,418 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java 16:09:20,428 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true 16:09:20,438 INFO [STDOUT] PrivateSessionBean.ejbCreate() called 16:09:20,448 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession 16:09:20,458 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello 16:09:20,468 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java 16:09:20,478 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false The first Failed authenticate() test. line results because Tomcat tried to determine whether the servlet request had a remote user associated with it. That caused a query to the security manager with a null username and password, because the browser was not asked to provide any login information. The null username and password is rejected and this results in a 401 error which causes the browser to display the basic auth login dialog. The following Authenticated 'java' with type 'BASIC' line is the result of the HTTP BASIC authorization login. Note that PrivateSessionBean.echo() method's check to see if the caller has the InternalUser role returns false. This seemingly incorrect result is in accord with our interpretation of the EJB 2.0 spec, which states on page 439: Note that isCallerInRole(String roleName) tests the principal that represents the caller of the enterprise bean, not the principal that corresponds to the run-as security identity for the bean, if any. Now follow Link 4 to try to access the PrivateSession bean's echo method from the SecureServlet. That should fail, since only the PublicSession has been configured to run as the InternalUser role. You should see a 500 error and a root cause exception with the message: java.lang.SecurityException: Insufficient method permissions, principal=java, method=create,
  • 239. 483 | P a g e interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo] at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:214) This message verifies that the method-permission element, which required a InternalUser role, is enforced. The links under the 'JBoss Unsecured Servlet with JAAS Login filter to EJB Tests' heading are to the UnsecureServletWithLogin mapping of the EJBServlet. These mappings use the JaasLoginFilter to perform a JAAS login at that start of the request using a username of java and a password of echoman, and a logout when the request completes. Test the tutorial1.ear deployment from Java Client There are three Ant targets for running test of a Java client accessing the session EJB: 1. example1-test0 this tests access with a valid username and password with a user who can access the PublicSession bean. 2. example1-test1 this tests access with a valid username and password with a user who does not have the correct roles to access the PublicSession bean. 3. example1-test2 this tests access with an invalid password. All testcases run the org.jboss.docs.jaas.howto.SessionClient which does a JAAS login, and then creates a PublicSession instance and invokes the echo method on it. Next the SessionClient attempts to create an instance of the PrivateSession and asserts that this fails. The core code is shown here: try { AppCallbackHandler handler = new AppCallbackHandler(name, password); LoginContext lc = new LoginContext("TestClient", handler); System.out.println("Created LoginContext"); lc.login(); } catch (LoginException le) { System.out.println("Login failed"); le.printStackTrace(); } try { InitialContext iniContext = new InitialContext(); SessionHome home = (SessionHome) iniContext.lookup(example + "/PublicSession"); System.out.println("Found PublicSession home"); Session bean = home.create(); System.out.println("Created PublicSession"); System.out.println("Bean.echo('Hello') -> " + bean.echo("Hello"));
  • 240. 484 | P a g e bean.remove(); } catch (Exception e) { e.printStackTrace(); } try { InitialContext iniContext = new InitialContext(); SessionHome home = (SessionHome) iniContext.lookup(example + "/PrivateSession"); System.out.println("Found PrivateSession home"); Session bean = home.create(); throw new IllegalStateException("Was able to create PrivateSession"); } catch (Exception e) { System.out.println("Failed to create PrivateSession as expected"); } example1-test0 The test example1-test0 accesses the PublicSession bean with a valid username and password with a user with the correct permissions. The expected client side output is shown here: [starksm@dedicated74 example]$ ant example1-test0 Buildfile: build.xml example1-test0: validate: fail_if_not_valid: init: [echo] Using jboss.dist=/tmp/jboss-3.2.3 [echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss- 3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes compile: client-test0: [java] +++ Running SessionClient with username=java, password=echoman,
  • 241. 485 | P a g e example=example1 [java] Created LoginContext [java] Found PublicSession home [java] Created PublicSession [java] Bean.echo('Hello') -> Hello [java] Found PrivateSession home [java] Failed to create PrivateSession as expected BUILD SUCCESSFUL The corresponding server side console output is: 07:41:47,762 INFO [STDOUT] PublicSessionBean.echo, arg=Hello 23:23:09,120 INFO [STDOUT] PublicSessionBean.ejbCreate() called 23:23:09,123 INFO [STDOUT] PublicSessionBean.echo, arg=Hello 23:23:09,124 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java 23:23:09,125 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true 23:23:09,131 INFO [STDOUT] PrivateSessionBean.ejbCreate() called 23:23:09,134 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession 23:23:09,143 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello 23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java 23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false 23:23:09,171 ERROR [SecurityInterceptor] Insufficient method permissions, principal=java, method=create, interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo] 23:23:09,175 ERROR [LogInterceptor] EJBException, causedBy: java.lang.SecurityException: Insufficient method permissions, principal=java, method=create, interface=HOME, requiredRoles=[InternalUser], principalRoles=[Echo] at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:229) at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:81) at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invokeHome(CachedConn ectionInterceptor.java:214) at org.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invokeHome(StatefulSessionInstanceInt erceptor.java:126) at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:88) at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267) at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98)
  • 242. 486 | P a g e at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120) at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderIntercepto r.java:93) at org.jboss.ejb.StatefulSessionContainer.internalInvokeHome(StatefulSessionContainer.java:404) at org.jboss.ejb.Container.invoke(Container.java:720) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284) at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546) at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:367) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261) at sun.rmi.transport.Transport$1.run(Transport.java:148) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:144) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) at java.lang.Thread.run(Thread.java:534) Exploring I encourage you to try the additional test cases in the tutorial1.ear example and investigate the second example, tutorial2.ear, which was created and deployed during the examples build. The tutorial2.ear example differs from tutorial1.ear only in its choice of security domain name and thus login module configuration. tutorial2.ear uses a Java Database Connectivity-based login module to demonstrate how to access security information from a database. The entry point for the tutorial2 web application ishttp://localhost:8080/jaas-example2/index.html. Note 1: Before you can use the tutorial2 web application successfully you must create the password and roles database. To do this, run the buildDB ant target with JBoss running the jaas_howto configuration. The JBoss server must NOT be running because the HSQLDB
  • 243. 487 | P a g e embedded database bundled with JBoss is configured to use a file only mode and the file would be locked if JBoss was running. Running the buildDB target should result in: [starksm@banshee example]$ ant buildDB Buildfile: build.xml validate: fail_if_not_valid: init: [echo] Using jboss.dist=/tmp/jboss-3.2.3 [echo] Using classpath=/tmp/jboss-3.2.3/client/jbossall-client.jar:/tmp/jboss- 3.2.3/server/default/lib/javax.servlet.jar:/tmp/jaashowto/example/output/classes compile: buildDB: [sql] Executing commands [sql] 11 of 11 SQL statements executed successfully BUILD SUCCESSFUL Secure your J2EE apps Although the mapping of application security roles onto a application server deployment environment is currently a nonportable, application-server-specific task, this article has demonstrated how the standard JAAS security could be used to implement the J2EE declarative security model using a simple Subject-based usage pattern. Hopefully, future versions of J2EE will extend the portability of security closer to the deployment layer using similar techniques based on JAAS or equivalent standards-based APIs. This article has peered into the JBossSX security manager implementation of the J2EE declarative security model used by the JBoss EJB and Web containers. It focused on how the JAAS login modules configured for a security domain provide the security information via a Subject usage pattern. I also covered the steps required to create a custom login module for security infrastructures not supported by bundled JBossSX login modules. With this information, you can secure your enterprise applications either by configuring the login modules bundled with JBoss or by writing your own.
  • 244. 488 | P a g e Resources  The EJB 2.0 Specification provides the guidelines that any EJB 2.0-compliant application server must follow: http://java.sun.com/products/ejb/docs.html  You will find a complete listing of the Java Authentication and Authorization Service (JAAS) documents at the JAAS homepage: http://java.sun.com/products/jaas/index-10.html  Java Authentication and Authorization Service (JAAS) 1.0 Developer's Guide: http://java.sun.com/security/jaas/doc/api.html  "PAM: Making Login Services Independent of Authentication Technologies," Vipin Samar and Charlie Lai (Java.sun.com): http://java.sun.com/security/jaas/doc/pam.html  You will find details of the JBossSX architecture in this online documentation: http://www.jboss.org/index.html?module=html&op=userdisplay&id=docs/index  Ant is a Java-based build tool used by many open source Java projects: http://jakarta.apache.org/ant/index.html  "Automate Your Build Process Using Java and Ant," Michael Cymerman (JavaWorld, October 2000): http://www.javaworld.com/javaworld/jw-10-2000/jw-1020-ant.html  "Benefit from Platform-Independent Builds," Sanjay Mahapatra (JavaWorld, August 2000): http://www.javaworld.com/javaworld/jw-08-2000/jw-0804-builds.html  The JBoss project code is housed at Sourceforge. You can obtain JBoss releases from the Files section of the project page: http://sourceforge.net/projects/jboss  For more articles on Java Security, browse our Topical Index: http://www.javaworld.com/channel_content/jw-security-index.shtml  To read more about Enterprise JavaBeans, browse our Topical Index: http://www.javaworld.com/channel_content/jw-ejbs-index.shtml  Sign up for the JavaWorld This Week free weekly email newsletter to learn what's new on JavaWorld: http://www.idg.net/jw-subscribe You'll find a wealth of IT-related articles from our sister publications at IDG.net Removing the Invokers HTTP Invokers If you want to remove the HTTP invokers (which are used if you 'tunnel' your requests through HTTP) simply remove the according deployments/directories from the .../deploy/ directory. Please be aware that HTTP invokers are something different than the Tomcat HTTP Connector (the HTTP invokers need the HTTP connector but the HTTP connector does not need the HTTP invokers).
  • 245. 489 | P a g e HTTPInvoker for JNDI, EJB and JMX Simply remove the .../deploy/http-invoker.sar/ directory from your configuration all together. HTTPInvoker for JMS Remove the .../deploy/jms/jbossmq-httpil.sar directory completly. Other invokers There are a lot of other invokers bound to different ports. If you don't need them you may remove them. Otherwise secure them if they are reachable by folks you don't fully trust. SecureTheInvokers Enabling authentication to the RMIAdaptor service FIXME: this article is about securing Invoker Access to the JMX. Not the general invoker security. Since 3.2.4, the JMX Detached Invoker Service which provides the RMIAdaptor interface into the MBeanServer has supported JAAS authentication of callers. Note, there is a bug in the 4.0.x implementation that is fixed in 4.0.5 GA. To enable this: - in JBossAS 5.0x, see Technical Paper in SecureTheJmxConsole - in JBossAS 4.0.x, edit jmx-invoker-service.xml - in JBossAS 3.2.x, edit jmx-invoker-adaptor-server.sar/META-INF/jboss-service.xml and uncomment the descriptors section of the invoke operation: <operation> <description>The detached invoker entry point</description> <name>invoke</name> <parameter> <description>The method invocation context</description>
  • 246. 490 | P a g e <name>invocation</name> <type>org.jboss.invocation.Invocation</type> </parameter> <return-type>java.lang.Object</return-type> <!-- Uncomment to require authenticated users --> <descriptors> <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securityDomain="java:/jaas/jmx-console"></interceptor> </interceptors> </descriptors> </operation> The value of the securityDomain attribute maps to the security domain name found in the conf/login-config.xml definitions the same way as the jboss.xml, jboss-web.xml security-domain elements do. In this case the jmx-console security domain configuration is being used. Note, in some version of jboss when running under java5+, you may see an error like the following: . This is due to a change in how the jmx descriptor names are stored with case preserved. To work around this isssue simply use all lower case attribute names: ... <descriptors> <interceptors> <interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securitydomain="java:/jaas/jmx-console"></interceptor> </interceptors> </descriptors> This still works under jdk14. Enabling authorization to the RMIAdaptor service Along the lines of the AuthenticationInterceptor, an AuthorizationInterceptor is available in JBoss. The interceptor should be placed after the AuthenticationInterceptor and has the following configuration.  authorizingClass : Fully Qualified Name of a class that does the authorization and which contains a method with the following signature "public void authorize( Principal caller, Subject subject, String objectname,String opname)" that can throw a java.lang.SecurityException An example of an authorizing class is available in JBoss. It is theorg.jboss.jmx.connector.invoker.RolesAuthorization, which looks for an hardcoded "JBossAdmin" role in the authenticated subject. <descriptors> <interceptors>