246
245 | Page 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

Java secure development part 2

Embed Size (px)

Citation preview

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 incode

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) isRequired 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 requirementsProcedure

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 OperationalRequirements for ApprovedScanning 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.2requirement

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 METHODOLOGYT. 8 Risk level assessment routine

Threat ClassificationBasic 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 impactThreat 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 DataT. 10 General statistics Threat Classification

260 | P a g e

Threat ClassificationN 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 rankThreat 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 ClassificationThreat 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 rankThreat 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 ClassificationThreat 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 rankThreat 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 ClassificationThreat 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 rankThreat 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 andconfigured to the application and framework in use. And, at all levels, tool results mustbe 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 properlyescaped for the applicable context.

[V8.1] Verify that that the application does not output error messages containingsensitive data that could assist an attacker, including session id and personalinformation.

[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 codescan

273 | P a g e

[V2.5] Verify that all authentication controls (including libraries that call externalauthentication services) have a centralized implementation.

[V2.13] Verify that account passwords are salted using a salt that is unique to thataccount (e.g., internal user ID, account creation) and hashed before storing.

[V4.4] Verify that direct object references are protected, such that only authorizedobjects 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 whenthis data must be encrypted (both at rest and in transit). Verify that this policy isproperly enforced.

[V14.2] Verify that security control interfaces are simple enough to use that developersare 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 delicateo 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 asvolatile (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 2http://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 interfacesand Exception classes model the mostimportant security functions toenterprise web applications.

org.owasp.esapi.codecs

This package contains codecs forapplication layer encoding/escapingschemes that can be used for bothcanonicalization and output encoding.

org.owasp.esapi.cryptoThis package contains ESAPIcryptography-related classes usedthroughout ESAPI.

org.owasp.esapi.errors

A set of exception classes designed tomodel the error conditions thatfrequently arise in enterprise webapplications and web services.

org.owasp.esapi.filters

This package contains several filtersthat demonstrate ways of using theESAPI security controls in front of yourapplication.

org.owasp.esapi.referenceThis package contains referenceimplementations of the ESAPIinterfaces.

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 referenceimplementation for some of the ESAPIcryptography-related classes usedthroughout ESAPI.

org.owasp.esapi.reference.validationThis package contains data format-specific validation rule functions.

org.owasp.esapi.tags

This package contains sample JSP tagsthat demonstrate how to use the ESAPIfunctions to protect an application fromwithin a JSP page.

org.owasp.esapi.util

This package contains ESAPI utilityclasses used throughout the referenceimplementation of ESAPI but may alsobe directly useful.

org.owasp.esapi.wafThis package contains the ESAPI WebApplication Firewall (WAF).

org.owasp.esapi.waf.actionsThis package contains the Actionobjects that are executed after a Rulesubclass executes.

org.owasp.esapi.waf.configuration

This package contains the both theconfiguration object model and theutility class to create that object modelfrom an existing policy file.

org.owasp.esapi.waf.internalThis package contains all HTTP-relatedclasses used internally by the WAF forthe implementation of its rules.

org.owasp.esapi.waf.rules This package contains all of the Rulesubclasses that correspond to policy file

320 | P a g e

entries.

321 | P a g e

Java & OpenSSOHarden OpenSSO By Disabling ssoadm.jsp

Notwithstanding that it is still a secret, we've just added a property that allows you to disablethe ssoadm.jsp to harden your system and reduce attack vectors. The property isssoadm.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 theDefault 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) andmultiple JVMs, you need to import the root CA certificate into the JVM trust store (by defaultJAVA_HOME/jre/lib/security/cacerts) and restart the OpenSSO web container beforeperforming any configurations.

For example, to configure a second instance of OpenSSO in a defined Site (when the firstinstance of OpenSSO is SSL-enabled), the root Certificate Authority (CA) certificate for the firstOpenSSO server certificate must be imported into the JVM key store of the web container inwhich the second instance of OpenSSO is deployed. (Restart the web container of the secondinstance 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 SecurityJBoss 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 serveroperates cross-platform: usable on any operating system that supports Java. JBoss AS was developedby JBoss, now a division of Red Hat.

J2EE Security Configuration and Architecture

Security is a fundamental part of any enterprise application. You need to beable to restrict who is allowed to access your applications and control whatoperations application users may perform. The J2EE specifications define asimple role-based security model for EJBs and web components. The JBosscomponent 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 securityvia a security proxy layer. The default implementation of the declarativesecurity model is based on Java Authentication and Authorization Service(JAAS) login modules and subjects. The security proxy layer allows customsecurity that cannot be described using the declarative model to be added toan EJB in a way that is independent of the EJB business object. Before gettinginto the JBoss security implementation details, we will revie EJB and Servletspecification security models as well as JAAS to establish the foundation forthese 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 astandard XML descriptor rather than embedding security into your businesscomponent. This isolates security from business-level code because securitytends to be a more a function of where the component is deployed, ratherthan 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. Thesecurity requirements, roles and permissions will vary independent of howone 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 applicationsecurity requirements via the standard J2EE deployment descriptors. Yousecure access to EJBs and web components in an enterprise application byusing the ejb-jar.xml and web.xml deployment descriptors. Figure 8.1, “Asubset of the EJB 2.0 deployment descriptor content model that shows thesecurity related elements.” and Figure 8.2, “A subset of the Servlet 2.2deployment descriptor content model that shows the security relatedelements.” illustrate the security-related elements in the EJB 2.0 and Servlet2.2 deployment descriptors, respectively.

337 | P a g e

Figure 8.1. A subset of the EJB 2.0 deployment descriptor content model thatshows the security related elements.

338 | P a g e

Figure 8.2. A subset of the Servlet 2.2 deployment descriptor content modelthat shows the security related elements.

The purpose and usage of the various security elements given in Figure 8.1, “Asubset of the EJB 2.0 deployment descriptor content model that shows thesecurity related elements.” and Figure 8.2, “A subset of the Servlet 2.2deployment descriptor content model that shows the security relatedelements.” 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. Thiselement is used to declare that a component is using the role-name value asan argument to the isCallerInRole(String) method. Using the isCallerInRole method, acomponent can verify if the caller is in a role that has been declared witha security-role-ref/role-name element. The role-name element value must link toa security-role element through the role-link element. The typical use ofisCallerInRole isto perform a security check that cannot be defined using the role based method-permissions elements. However, use of isCallerInRole is discouraged because thisresults in security logic embedded inside of the component code. Exampledescriptor fragments that illustrate the security-role-ref element usage arepresented in Example 8.4, “An example ejb-jar.xml descriptor fragments whichillustrate the security-role element usage.” and Example 8.5, “An exampleweb.xml descriptor fragment which illustrate the security-role elementusage.”.

Example 8.1. An example ejb-jar.xml descriptor fragments which illustratethe 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 thesecurity-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 thecapability to specify what identity an EJB should use when it invokes methodson other components. The invocation identity can be that of the current caller,or a specific role. The application assembler uses the security-identity elementwith a use-caller-identity child element to indicate the current caller's identityshould be propagated as the security identity for method invocations made bythe EJB. Propagation of the caller's identity is the default used in the absenceof an explicit security-identity element declaration.

Alternatively, the application assembler can use the run-as/role-name childelement to specify that a specific security role given by the role-name valueshould be used as the security identity for method invocations made by theEJB. Note that this does not change the caller's identity as seenby EJBContext.getCallerPrincipal(). Rather, the caller's security roles are set to thesingle role specified by the run-as/role-name element value. One use case forthe run-as element is to prevent external clients from accessing internal EJBs.This is accomplished by assigning the internal EJB method-permission elementsthat restrict access to a role never assigned to an external client. EJBs thatneed to use internal EJB are then configured with a run-as/role-nameequal to therestricted role. An example descriptor fragment that illustrates security-identity element usage is presented in Example 8.3, “An example ejb-jar.xmldescriptor fragment which illustrates the security-identity element usage.”.

Example 8.3. An example ejb-jar.xml descriptor fragment which illustratesthe 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. Anapplication assembler defines logical security roles by declaring security-role elements. Therole-name value is a logical application role name likeAdministrator, Architect, SalesManager, etc.

What is a role? The J2EE specifications note that it is important to keep inmind that the security roles in the deployment descriptor are used to definethe logical security view of an application. Roles defined in the J2EEdeployment descriptors should not be confused with the user groups, users,principals, and other concepts that exist in the target enterprise's operationalenvironment. The deployment descriptor roles are application constructs withapplication domain specific names. For example, a banking application mightuse role names like BankManager, Teller, and Customer.

In JBoss, a security-role is only used to map security-role-ref/role-name values to thelogical role that the component role referenced. The user's assigned roles area dynamic function of the application's security manager, as you will see whenwe discuss the JBossSX implementation details. JBoss does not require thedefinition of security-roles in order to declare method permissions. Therefore, thespecification of security-role elements is simply a good practice to ensureportability across application servers and for deployment descriptor

342 | P a g e

maintenance. Example descriptor fragments that illustrate security-role usage arepresented in Example 8.4, “An example ejb-jar.xml descriptor fragments whichillustrate the security-role element usage.”and Example 8.5, “An exampleweb.xml descriptor fragment which illustrate the security-role elementusage.”.

Example 8.4. An example ejb-jar.xml descriptor fragments which illustratethe 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 thesecurity-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'shome and remote interface methods through method-permission elementdeclarations. Each method-permission element contains one or more role-namechild elements that define the logical roles allowed access the EJB methods asidentified by method child elements. As of EJB 2.0, you can now specify anunchecked element instead of the role-name element to declare that anyauthenticated user can access the methods identified by method childelements. In addition, you can declare that no one should have access to amethod 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 EJBmethods default to being excluded from use. This is equivalent to defaultingthe 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 interfacemethods 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 orcomponent interface of the named enterprise bean. If there aremultiple methods with the same overloaded name, this style refers toall 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 methodswith an overloaded name. The method must be defined in the specifiedenterprise bean's home or remote interface. The method-paramelement values are the fully qualified name of the correspondingmethod parameter type. If there are multiple methods with the sameoverloaded signature, the permission applies to all of the matchingoverloaded 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 withthe same name and signature that are defined in both the home and remoteinterfaces of an enterprise bean. Example 8.6, “An example ejb-jar.xmldescriptor fragment which illustrates the method-permission elementusage.” provides examples of the method-permission element usage.

Example 8.6. An example ejb-jar.xml descriptor fragment which illustratesthe 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 ofthe 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 theEmployeeServiceAdmin 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 theEmployeeServiceHelp 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 beused 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 contentby a URL pattern that identifies the protected content. This set of informationis declared using the web.xml security-constraint element. The content to be securedis declared using one or more web-resource-collection elements. Each web-resource-collection element contains an optional series of url-pattern elements followed byan optional series of http-method elements. The url-pattern element value specifiesa URL pattern against which a request URL must match for the request tocorrespond to an attempt to access secured content. The http-method elementvalue specifies a type of HTTP request to allow.

The optional user-data-constraint element specifies the requirements for thetransport layer of the client to server connection. The requirement may be forcontent 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 communicationbetween client and server should be protected. Its values are NONE, INTEGRAL,or CONFIDENTIAL. A value of NONE means that the application does not require anytransport 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'tbe changed in transit. A value of CONFIDENTIAL means that the applicationrequires the data be transmitted in a fashion that prevents other entities fromobserving the contents of the transmission. In most cases, the presence ofthe INTEGRAL or CONFIDENTIAL flag indicates that the use of SSL is required.

The optional login-config is used to configure the authentication method thatshould be used, the realm name that should be used for this application, andthe attributes that are needed by the form login mechanism. The auth-method child element specifies the authentication mechanism for the webapplication. As a prerequisite to gaining access to any web resources that areprotected by an authorization constraint, a user must have authenticatedusing the configured mechanism. Legal values for auth-methodareBASIC, DIGEST, FORM, or CLIENT-CERT. The realm-name child element specifies therealm 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 beused in form-based login. If the auth-method value is not FORM, form-login-config andits child elements are ignored.

As an example, the web.xml descriptor fragment given in Example 8.7, “ Aweb.xml descriptor fragment which illustrates the use of the security-constraint and related elements.” indicates that any URL lying under the webapplication /restricted path requires an AuthorizedUser role. There is no requiredtransport guarantee and the authentication method used for obtaining theuser identity is BASIC HTTP authentication.

Example 8.7. A web.xml descriptor fragment which illustrates the use of thesecurity-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 securityrequirements from the application's perspective. Since J2EE security elementsdeclare logical roles, the application deployer maps the roles from theapplication domain onto the deployment environment. The J2EE specificationsomit these application-server-specific details. In JBoss, mapping theapplication roles onto the deployment environment entails specifying asecurity manager that implements the J2EE security model using JBoss serverspecific deployment descriptors. We will avoid discussion the details of thisstep for now. The details behind the security configuration will be discussedwhen 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 JAASAPI. It is important that you understand the basic elements of the JAAS API tounderstand the implementation details of JBossSX. This section provides anintroduction to JAAS to prepare you for the JBossSX architecture discussion.Additional details on the JAAS package can be found at the JAAS home pageat: 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 userauthentication and authorization. It implements a Java version of the standardPluggable Authentication Module (PAM) framework and compatibly extendsthe Java 2 Platform's access control architecture to support user-basedauthorization. JAAS was first released as an extension package for JDK 1.3 andis bundled with JDK 1.4+. Because the JBossSX framework uses only theauthentication capabilities of JAAS to implement the declarative role-basedJ2EE 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 JBossSXarchitecture discussion in Section 8.4, “The JBoss Security ExtensionArchitecture”

JAAS authentication is performed in a pluggable fashion. This permits Javaapplications to remain independent from underlying authenticationtechnologies and allows the JBossSX security manager to work in differentsecurity infrastructures. Integration with a security infrastructure can beachieved without changing the JBossSX security manager implementation. Allthat needs to change is the configuration of the authentication stack that JAASuses.

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 thecommon and authentication classes because these are the specific classesused 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 therequest's source. The JAAS framework defines the term subject to represent arequest'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 privatecredentials. The JAAS APIs use the existing Java 2 java.security.Principal interface torepresent a principal, which is essentially just a typed name.

During the authentication process, a subject is populated with associatedidentities, or principals. A subject may have many principals. For example, aperson may have a name principal (John Doe), a social security numberprincipal (123-45-6789), and a username rincipal (johnd), all of which helpdistinguish the subject from other subjects. To retrieve the principalsassociated 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 secondmethod only returns those principals that are instances of Class c or one of itssubclasses. An empty set will be returned if the subject has no matchingprincipals. Note that thejava.security.acl.Group interface is a subinterfaceof java.security.Principal, and so an instance in the principals set may represent alogical 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 consistsof the following steps:

350 | P a g e

An application instantiates a LoginContext passing in the name of the loginconfiguration and a CallbackHandler to populate the Callback objects asrequired by the configuration LoginModules.

The LoginContext consults a Configuration to load all ofthe LoginModules included in the named login configuration. If no suchnamed 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 thehandle method on the associated CallbackHandler to obtain the informationrequired for the authentication process. The required information ispassed to the handle method in the form of an array of Callback objects.Upon success, the LoginModules associate relevant principals andcredentials with the subject.

The LoginContext returns the authentication status to the application.Success is represented by a return from the login method. Failure isrepresented through a LoginException being thrown by the loginmethod.

If authentication succeeds, the application retrieves the authenticatedsubject using the LoginContext.getSubject method.

After the scope of the subject authentication is complete, all principalsand related information associated with the subject by the loginmethod may be removed by invoking the LoginContext.logout method.

The LoginContext class provides the basic methods for authenticating subjectsand offers a way to develop an application independent of the underlyingauthentication technology. The LoginContext consults a Configuration to determinethe authentication services configured for a particularapplication. LoginModule classes represent the authentication services.Therefore, you can plug in different login modules into an application withoutchanging the application itself. Example 8.8, “An illustration of the steps of theauthentication process from the application perspective.” provides codefragments that illustrate the steps required by an application to authenticate asubject.

Example 8.8. An illustration of the steps of the authentication process fromthe 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 infotry {

lc.logout();} catch(LoginException e) {

System.out.println("logout failed");e.printStackTrace();

}

// A sample MyHandler classclass MyHandler

implements CallbackHandler{

public void handle(Callback[] callbacks) throwsIOException, 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 animplementation of the LoginModule interface. This allows differentauthentication technologies to be plugged into an application byadministrator. 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. Forexample, one LoginModule may perform username/password-basedauthentication, while another may interface to hardware devices such assmart card readers or biometric authenticators. The life cycle of a LoginModule isdriven by the LoginContext object against which the client creates and issues thelogin method. The process consists of a two phases. The steps of the processare 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. TheSubject argument is guaranteed to be non-null. The signature of theinitialize method is: public void initialize(Subject subject, CallbackHandler callbackHandler,Map sharedState, Map options).

The login method is then called to start the authentication process. Anexample method implementation might prompt the user for ausername and password, and then verify the information against datastored in a naming service such as NIS or LDAP. Alternativeimplementations might interface to smart cards and biometric devices,or simply extract user information from the underlying operatingsystem. The validation of user identity by each LoginModule is consideredphase 1 of JAAS authentication. The signature of the login methodis: boolean login() throws LoginException. Failure is indicated by throwinga LoginException. A return of true indicates that the method succeeded,while a return of false indicates that the login module should beignored.

If the LoginContext's overall authentication succeeds, commit is invokedon each LoginModule. If phase 1 succeeded for a LoginModule, then thecommit method continues with phase 2: associating relevant principals,public credentials, and/or private credentials with the subject. If phase1 fails for a LoginModule, then commit removes any previously storedauthentication state, such as usernames or passwords. The signature ofthe commit method is: boolean commit() throws LoginException. Failure tocomplete the commit phase is indicated by throwing a LoginException. Areturn of true indicates that the method succeeded, while a return offalse indicates that the login module should be ignored.

353 | P a g e

If the LoginContext's overall authentication failed, then the abort method isinvoked on each LoginModule. The abort method removes/destroys anyauthentication state created by the login or initialize methods. Thesignature of the abort method is:boolean abort() throws LoginException. Failureto complete the abort phase is indicated by throwing a LoginException. Areturn of true indicates that the method succeeded, while a return offalse indicates that the login module should be ignored.

Removal of the authentication state after a successful login isaccomplished 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 originallyassociated with the subject during the commit operation. Credentialsshould be destroyed upon removal. The signature of the logout methodis: boolean logout() throws LoginException. Failure to complete the logout processis indicated by throwing a LoginException. A return of true indicates thatthe method succeeded, while a return of false indicates that the loginmodule should be ignored.

When a LoginModule must communicate with the user to obtain authenticationinformation, it uses a CallbackHandler object. Applications implementthe CallbackHandler interface and pass it to the LoginContext, which forwards itdirectly to the underlying login modules. Login modules usethe CallbackHandler both to gather input from users, such as a password or smart-card PIN number, and to supply information to users, such as statusinformation. By allowing the application to specify theCallbackHandler,underlying LoginModules remain independent from the different waysapplications interact with users. For example, a CallbackHandler's implementationfor a GUI application might display a window to solicit user input. On the otherhand, a callbackhandler's implementation for a non-GUI environment, such as anapplication server, might simply obtain credential information using anapplication server API. The callbackhandler interface has one method toimplement:

void handle(Callback[] callbacks)throws java.io.IOException, UnsupportedCallbackException;

The last authentication class to cover is the Callback interface. This is a tagginginterface for which several default implementations are provided,

354 | P a g e

including NameCallback and PasswordCallback that were used in Example 8.8, “Anillustration of the steps of the authentication process from the applicationperspective.” LoginModule s use a Callback to request information required bythe authentication mechanism the LoginModule encapsulates. LoginModule s passan array of Callback s directly to theCallbackHandler.handle method during theauthentication's login phase. If a callbackhandler does not understand how to usea Callback object passed into the handle method, it throwsan UnsupportedCallbackException to abort the login call.

The JBoss Security Model

Similar to the rest of the JBoss architecture, security at the lowest level isdefined as a set of interfaces for which alternate implementations may beprovided. There are three basic interfaces that define the JBoss server securitylayer:org.jboss.security.AuthenticationManager, org.jboss.security.RealmMapping,and org.jboss.security.SecurityProxy. Figure 8.3, “The key security model interfacesand their relationship to the JBoss server EJB container elements.”shows aclass diagram of the security interfaces and their relationship to the EJBcontainer architecture.

355 | P a g e

Figure 8.3. The key security model interfaces and their relationship to theJBoss server EJB container elements.

The light blue classes represent the security interfaces while the yellow classesrepresent the EJB container layer. The two interfaces required for theimplementation of the J2EE security model arethe org.jboss.security.AuthenticationManager andorg.jboss.security.RealmMapping. The roles ofthe security interfaces presented in Figure 8.3, “The key security modelinterfaces and their relationship to the JBoss server EJB containerelements.” are summarized in the following list.

AuthenticationManager is an interface responsible for validating credentialsassociated with principals. Principals are identities and examples

356 | P a g e

include usernames, employee numbers, social security numbers, and soon. Credentials are proof of the identity and examples includepasswords, session keys, digital signatures, and so on. The isValid methodis invoked to see if a user identity and associated credentials as knownin the operational environment are valid proof of the user identity.

RealmMapping is an interface responsible for principal mapping and rolemapping. The getPrincipal method takes a user identity as known in theoperational environment and returns the application domain identity.The doesUserHaveRole method validates that the user identity in theoperation environment has been assigned the indicated role from theapplication domain.

SecurityProxy is an interface describing the requirements for a customSecurityProxyInterceptor plugin. A SecurityProxy allows for theexternalization of custom security checks on a per-method basis forboth the EJB home and remote interface methods.

SubjectSecurityManager is a subinterface of AuthenticationManager that simplyadds accessor methods for obtaining the security domain name of thesecurity 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 comprehensivesecurity interface based on the JAAS Subject, a java.security.KeyStore, andtheJSSE com.sun.net.ssl.KeyManagerFactory and com.sun.net.ssl.TrustManagerFactory interfaces. This interface is still a work in progress that will be the basis of amulti-domain security architecture that will better support ASP styledeployments of applications and resources.

Note that the AuthenticationManager, RealmMapping and SecurityProxy interfaces have noassociation to JAAS related classes. Although the JBossSX framework is heavilydependent on JAAS, the basic security interfaces required for implementationof the J2EE security model are not. The JBossSX framework is simply animplementation of the basic security plug-in interfaces that are based on JAAS.The component diagram presented in Figure 8.4, “The relationship betweenthe JBossSX framework implementation classes and the JBoss server EJBcontainer layer.” illustrates this fact. The implication of this plug-inarchitecture is that you are free to replace the JAAS-based JBossSXimplementation 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 seehow to do this when you look at the JBossSX MBeans available for theconfiguration of JBossSX in Figure 8.4, “The relationship between the JBossSXframework implementation classes and the JBoss server EJB container layer.”.

Figure 8.4. The relationship between the JBossSX frameworkimplementation 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 arequirement for the use of JBoss server specific deployment descriptor toenable security. The details of this configuration is presented here, as this ispart of the generic JBoss security model. Figure 8.5, “The security elementsubsets of the JBoss server jboss.xml and jboss-web.xml deploymentdescriptors.” shows the JBoss-specific EJB and web application deploymentdescriptor's security-related elements.

Figure 8.5. The security element subsets of the JBoss server jboss.xml andjboss-web.xml deployment descriptors.

359 | P a g e

The value of a security-domain element specifies the JNDI name of the securitymanager interface implementation that JBoss uses for the EJB and webcontainers. This is an object that implements both ofthe AuthenticationManager and RealmMappinginterfaces. When specified as a top-levelelement it defines what security domain in effect for all EJBs in thedeployment unit. This is the typical usage because mixing security managerswithin a deployment unit complicates inter-component operation andadministration.

To specify the security domain for an individual EJB, you specify the security-domain at the container configuration level. This will override any top-levelsecurity-domain element.

The unauthenticated-principal element specifies the name to use forthe Principal object returned by the EJBContext.getUserPrincpal method when anunauthenticated user invokes an EJB. Note that this conveys no specialpermissions to an unauthenticated caller. Its primary purpose is to allowunsecured servlets and JSP pages to invoke unsecured EJBs and allow thetarget EJB to obtain a non-null Principal for the caller usingthe getUserPrincipal method. This is a J2EE specification requirement.

The security-proxy element identifies a custom security proxy implementationthat allows per-request security checks outside the scope of the EJBdeclarative security model without embedding security logic into the EJBimplementation. This may be an implementation ofthe org.jboss.security.SecurityProxy interface, or just an object that implementsmethods in the home, remote, local home or local interfaces of the EJB tosecure without implementing any common interface. If the given class doesnot implement the SecurityProxy interface, the instance must be wrapped ina SecurityProxy implementation that delegates the method invocations to theobject. The org.jboss.security.SubjectSecurityProxy is anexample SecurityProxyimplementation used by the default JBossSX installation.

Take a look at a simple example of a custom SecurityProxy in the context of atrivial stateless session bean. The custom SecurityProxy validates that no oneinvokes the bean's echo method with a four-letter word as its argument. This isa check that is not possible with role-based security; you cannot definea 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 givenin Example 8.9, “The example 1 custom EchoSecurityProxy implementationthat enforces the echo argument-based security constraint.”, and the fullsource code is available in the src/main/org/jboss/chap8/ex1 directory of the bookexamples. The associated jboss.xml descriptor that installs the EchoSecurityProxy asthe custom proxy for the EchoBean is given in Example 8.10, “The jboss.xmldescriptor which configures the EchoSecurityProxy as the custom securityproxy for the EchoBean.”.

Example 8.9. The example 1 custom EchoSecurityProxy implementation thatenforces 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 [email protected]* @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 invoketry {

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 methodif (m.equals(echo)) {

// Validate that the msg arg is not 4 letter wordString 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 theEchoSecurityProxy 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 instancecorresponds to the echo(String) method loaded the init method. If there is amatch, 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 acontrived example, but only in its application. It is a common requirement thatapplications must perform security checks based on the value of methodarguments. The point of the example is to demonstrate how custom securitybeyond the scope of the standard declarative security model can beintroduced independent of the bean implementation. This allows thespecification and coding of the security requirements to be delegated tosecurity experts. Since the security proxy layer can be done independent ofthe bean implementation, security can be changed to match the deploymentenvironment requirements.

Now test the custom proxy by running a client that attempts to invokethe EchoBean.echo method with the arguments Hello and Four as illustrated in thisfragment:

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 factthat Four is a four-letter word. Run the client as follows using Ant from theexamples directory:

[nr@toki examples]$ ant -Dchap=chap8 -Dex=1 run-examplerun-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 andthe echo('Four') method call results in a rather messy looking exception, which isalso expected. The above output has been truncated to fit in the book. Thekey part to the exception is that the SecurityException("No 4 letter words") generatedby the EchoSecurityProxy was thrown to abort the attempted method invocationas desired.

8.4. The JBoss Security Extension Architecture

The preceding discussion of the general JBoss security layer has stated thatthe JBossSX security extension framework is an implementation of the securitylayer interfaces. This is the primary purpose of the JBossSX framework. Thedetails of the implementation are interesting in that it offers a great deal ofcustomization for integration into existing security infrastructures. A securityinfrastructure can be anything from a database or LDAP server to asophisticated security software suite. The integration flexibility is achievedusing the pluggable authentication model available in the JAAS framework.

The heart of the JBossSX framework is org.jboss.security.plugins.JaasSecurityManager. Thisis the default implementation ofthe AuthenticationManager and RealmMapping interfaces. Figure 8.6, “The relationshipbetween the security-domain component deployment descriptor value, thecomponent container and the JaasSecurityManager.” shows howthe JaasSecurityManager integrates into the EJB and web container layers based onthe security-domain element of the corresponding component deploymentdescriptor.

364 | P a g e

Figure 8.6. The relationship between the security-domain componentdeployment descriptor value, the component container and theJaasSecurityManager.

Figure 8.6, “The relationship between the security-domain componentdeployment descriptor value, the component container and theJaasSecurityManager.” depicts an enterprise application that contains bothEJBs and web content secured under the security domain jwdomain. The EJB andweb containers have a request interceptor architecture that includes asecurity 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 associatedwith the container. The security interceptor then uses the security manager toperform its role. When a secured component is requested, the securityinterceptor delegates security checks to the security manager instanceassociated with the container.

The JBossSX JaasSecurityManager implementation, shown in Figure 8.6, “Therelationship between the security-domain component deployment descriptorvalue, the component container and the JaasSecurityManager.” asthe JaasSecurityMgr component, performs security checks based on theinformation associated with the Subject instance that results from executing theJAAS login modules configured under the name matching the security-domainelement value. We will drill into the JaasSecurityManagerimplementation and itsuse of JAAS in the following section.

8.4.1. How the JaasSecurityManager Uses JAAS

The JaasSecurityManager uses the JAAS packages to implementthe AuthenticationManager and RealmMapping interface behavior. In particular, itsbehavior derives from the execution of the login module instances that areconfigured under the name that matches the security domain to whichthe JaasSecurityManager has been assigned. The login modules implement thesecurity domain's principal authentication and role-mapping behavior. Thus,you can use the JaasSecurityManager across different security domains simply byplugging in different login module configurations for the domains.

To illustrate the details of the JaasSecurityManager's usage of the JAASauthentication process, you will walk through a client invocation of an EJBhome method invocation. The prerequisite setting is that the EJB has beendeployed in the JBoss server and its home interface methods have beensecured using method-permission elements in the ejb-jar.xml descriptor, and it hasbeen assigned a security domain named jwdomain usingthe jboss.xml descriptor security-domain element.

366 | P a g e

Figure 8.7. An illustration of the steps involved in the authentication andauthorization of a secured EJB home method invocation.

Figure 8.7, “An illustration of the steps involved in the authentication andauthorization 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 stepsshown are:

1. The client first has to perform a JAAS login to establish the principal andcredentials for authentication, and this is labeled Client Side Login in thefigure. This is how clients establish their login identities in JBoss.Support for presenting the login information viaJNDI InitialContext properties is provided via an alternate configuration. AJAAS login entails creating a LoginContext instance and passing the name ofthe configuration to use. The configuration name is other. This one-timelogin associates the login principal and credentials with all subsequentEJB method invocations. Note that the process might not authenticatethe user. The nature of the client-side login depends on the loginmodule configuration that the client uses. In this example,theother client-side login configuration entry is set up to usethe ClientLoginModule module (an org.jboss.security.ClientLoginModule). This is thedefault client side module that simply binds the username andpassword to the JBoss EJB invocation layer for later authentication onthe server. The identity of the client is not authenticated on the client.

2. Later, the client obtains the EJB home interface and attempts to createa bean. This event is labeled as Home Method Invocation. This results ina home interface method invocation being sent to the JBoss server. Theinvocation includes the method arguments passed by the client alongwith the user identity and credentials from the client-side JAAS loginperformed in step 1.

3. On the server side, the security interceptor first requires authenticationof the user invoking the call, which, as on the client side, involves a JAASlogin.

4. The security domain under which the EJB is secured determines thechoice of login modules. The security domain name is used as the loginconfiguration entry name passed to the LoginContext constructor. The EJBsecurity domain is jwdomain. If the JAAS login authenticates the user, aJAAS Subject is created that contains the following in its PrincipalsSet:

A java.security.Principal that corresponds to the client identity asknown in the deployment security environment.

A java.security.acl.Group named Roles that contains the role namesfrom the application domain to which the user has been

368 | P a g e

assigned. org.jboss.security.SimplePrincipal objects are used to representthe role names;SimplePrincipal is a simple string-basedimplementation of Principal. These roles are used to validate theroles assigned to methods in ejb-jar.xml andthe EJBContext.isCallerInRole(String) method implementation.

An optional java.security.acl.Group named CallerPrincipal, which containsa single org.jboss.security.SimplePrincipal that corresponds to the identityof the application domain's caller. The CallerPrincipal sole groupmember will be the value returned bythe EJBContext.getCallerPrincipal() method. The purpose of this mappingis to allow a Principal as known in the operational securityenvironment to map to a Principal with a name known to theapplication. In the absence of a CallerPrincipal mapping thedeployment security environment principal is used asthe getCallerPrincipal method value. That is, the operational principalis the same as the application domain principal.

5. The final step of the security interceptor check is to verify that theauthenticated user has permission to invoke the requested method Thisis labeled as Server Side Authorization in Figure 8.7, “An illustration ofthe steps involved in the authentication and authorization of a securedEJB home method invocation.”. Performing the authorization thisentails the following steps:

Obtain the names of the roles allowed to access the EJB methodfrom 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 inan exclude-list element, then access to the method is denied.Otherwise, the doesUserHaveRole method is invoked on the securitymanager by the security interceptor to see if the caller has one ofthe assigned role names. This method iterates through the rolenames and checks if the authenticated user's Subject Roles groupcontains a SimplePrincipal with the assigned role name. Access isallowed if any role name is a member of the Roles group. Access isdenied if none of the role names are members.

If the EJB was configured with a custom security proxy, themethod 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. Ifno SecurityException is thrown, access to the EJB method is allowedand the method invocation passes to the next containerinterceptor. Note that the SecurityProxyInterceptor handles this checkand this interceptor is not shown.

Every secured EJB method invocation, or secured web content access, requiresthe authentication and authorization of the caller because securityinformation is handled as a stateless attribute of the request that must bepresented and validated on each request. This can be an expensive operationif the JAAS login involves client-to-server communication. Because of this,the JaasSecurityManager supports the notion of an authentication cache that isused to store principal and credential information from previous successfullogins. You can specify the authentication cache instance to use as part ofthe JaasSecurityManager configuration as you will see when the associated MBeanservice is discussed in following section. In the absence of any user-definedcache, a default cache that maintains credential information for a configurableperiod 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 notuse JAAS in their implementation. The name arose from the fact that thedefault security manager implementation is the JaasSecurityManager. The primaryrole of the JaasSecurityManagerService is to externalize the security managerimplementation. You can change the security manager implementation byproviding an alternate implementation oftheAuthenticationManager and RealmMapping interfaces. Of course this is optionalbecause, by default, the JaasSecurityManager implementation is used.

The second fundamental role of the JaasSecurityManagerService is to provide aJNDI javax.naming.spi.ObjectFactory implementation to allow for simple code-freemanagement of the JNDI name to security manager implementation mapping.It has been mentioned that security is enabled by specifying the JNDI name ofthe security manager implementation via the security-domain deploymentdescriptor 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 ofsecurity manager instances to names by binding a next naming systemreference with itself as the JNDI ObjectFactory under the name java:/jaas. Thisallows one to use a naming convention of the form java:/jaas/XYZ as the value forthe security-domain element, and the security manager instance forthe XYZ security domain will be created as needed for you. The securitymanager for the domain XYZ is created on the first lookup againstthe java:/jaas/XYZ binding by creating an instance of the class specified bythe SecurityManagerClassName attribute using a constructor that takes the name ofthe security domain. For example, consider the following container securityconfiguration 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 instancethat has been associated with the security domain named hades. This securitymanager will implement the AuthenticationManager and RealmMappingsecurity interfaces and will be of the type specified bythe JaasSecurityManagerService SecurityManagerClassName attribute.

The JaasSecurityManagerService MBean is configured by default for use in thestandard JBoss distribution, and you can often use the default configuration asis. The configurable attributes of the JaasSecurityManagerService include:

SecurityManagerClassName: The name of the class that provides thesecurity manager implementation. The implementation must supportboththe org.jboss.security.AuthenticationManager and org.jboss.security.RealmMappinginterfaces. If not specified this defaults to the JAAS-based org.jboss.security.plugins.JaasSecurityManager.

CallbackHandlerClassName: The name of the class that providesthe javax.security.auth.callback.CallbackHandler implementation used bythe JaasSecurityManager. You can override the handler used bythe 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 beset unless you know what you are doing.

SecurityProxyFactoryClassName: The name of the class that providesthe org.jboss.security.SecurityProxyFactory implementation. If not specified thisdefaults to org.jboss.security.SubjectSecurityProxyFactory.

AuthenticationCacheJndiName: Specifies the location of the securitycredential cache policy. This is first treated as an ObjectFactory locationcapable of returning CachePolicy instances on a per-security-domain basis.This is done by appending the name of the security domain to this namewhen looking up the CachePolicy for a domain. If this fails, the location istreated as a single CachePolicy for all security domains. As a default, atimed cache policy is used.

DefaultCacheTimeout: Specifies the default timed cache policy timeoutin seconds. The default value is 1800 seconds (30 minutes). The valueyou use for the timeout is a tradeoff between frequent authenticationoperations and how long credential information may be out of synchwith respect to the security information store. If you want to disablecaching of security credentials, set this to 0 to force authentication tooccur every time. This has no affect if the AuthenticationCacheJndiName hasbeen changed from the default value.

DefaultCacheResolution: Specifies the default timed cache policyresolution in seconds. This controls the interval at which the cachecurrent timestamp is updated and should be less thanthe DefaultCacheTimeout in order for the timeout to be meaningful. Thedefault resolution is 60 seconds(1 minute). This has no affect ifthe AuthenticationCacheJndiName has been changed from the default value.

The JaasSecurityManagerService also supports a number of useful operations. Theseinclude flushing any security domain authentication cache at runtime, gettingthe list of active users in a security domain authentication cache, and any ofthe security manager interface methods.

Flushing a security domain authentication cache can be used to drop allcached credentials when the underlying store has been updated and you wantthe store state to be used immediately. The MBean operation signatureis: 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 asecurity domain authentication cache that are not expired. The MBeanoperation 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 thecorresponding AuthenticationManager and RealmMapping interface method of theassociated security domain named by the securityDomain argument.

8.4.3. The JaasSecurityDomain MBean

The org.jboss.security.plugins.JaasSecurityDomain is an extension of JaasSecurityManager thatadds the notion of a KeyStore, aJSSE KeyManagerFactory and a TrustManagerFactory forsupporting SSL and other cryptographic use cases. The additional configurableattributes of the JaasSecurityDomain include:

JKS

373 | P a g e

KeyStoreType: The type of the KeyStore implementation. This is the typeargument passed to the java.security.KeyStore.getInstance(String type) factorymethod.

KeyStoreURL: A URL to the location of the KeyStore database. This is usedto obtain an InputStream to initialize the KeyStore. If the string is not a valueURL, it iss treated as a file.

KeyStorePass: The password associated with the KeyStore databasecontents. The KeyStorePass is also used in combination withthe Salt and IterationCount attributes to create a PBE secret key used withthe encode/decode operations. TheKeyStorePass attribute value format isone of the following:

o The plaintext password for the KeyStore The toCharArray() value of thestring is used without any manipulation.

o A command to execute to obtain the plaintext password. Theformat is {EXT}... where the ... is the exact command line that willbe passed to the Runtime.exec(String) method to execute a platform-specific command. The first line of the command output is usedas the password.

o A class to create to obtain the plaintext password. The formatis {CLASS}classname[:ctorarg] where the [:ctorarg] is an optional string thatwill be passed to the constructor when instantiating thethe classname. The password is obtained from classname byinvoking 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 registerthe JaasSecurityDomain as a the security managerunder java:/jaas/<domain> where <domain> is the name passed to the MBeanconstructor. The name defaults to jboss.security:service=JaasSecurityManager.

LoadSunJSSEProvider: A flag indicating if theSun com.sun.net.ssl.internal.ssl.Provider security provider should be loaded onstartup. This is needed when using the Sun JSSE jars without theminstalled as an extension with JDK 1.3. This should be set to false withJDK 1.4 or when using an alternate JSSE provider. This flag currentlydefaults 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 classthat is provided by the org.jboss.security.auth.login.XMLLoginConfig MBean. Thisconfiguration implementation uses an XML format that conforms to the DTDgiven 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, controlimmediately returns to the application (authentication does notproceed down the LoginModule list).

sufficient: the LoginModule is not required to succeed. If it does succeed,control immediately returns to the application (authentication does notproceed down the LoginModule list). If it fails, authentication continuesdown 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 ofa login-module. These define name/value string pairs that are made available tothe login module during initialization. The name attribute specifies the optionname while themodule-option body provides the value. An example loginconfiguration is given in Example 8.11, “A sample login module configurationsuitable for use with XMLLoginConfig”.

Example 8.11. A sample login module configuration suitable for use withXMLLoginConfig

<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 thatshould be loaded by this MBean on startup. This must be a valid URLstring representation.

ConfigResource: specifies the resource name of the XML loginconfiguration file that should be loaded by this MBean on startup. Thename is treated as a classpath resource for which a URL is located usingthe thread context class loader.

ValidateDTD: a flag indicating if the XML configuration should bevalidated against its DTD. This defaults to true.

376 | P a g e

The MBean also supports the following operations that allow one todynamically extend the login configurations at runtime. Note that anyoperation that attempts to alter login configuration requiresajavax.security.auth.AuthPermission("refreshLoginConfiguration") when running with asecurity manager. The org.jboss.chap8.service.SecurityConfig service demonstrates howthis can be used to add/remove a deployment specific scurity configurationdynamically.

void addAppConfig(String appName, AppConfigurationEntry[] entries): this adds the givenlogin module configuration stack to the current configuration under thegiven appName. This replaces any existing entry under that name.

void removeAppConfig(String appName): this removes the login moduleconfiguration registered under the given appName.

String[] loadConfig(URL configURL) throws Exception: this loads one or more loginconfigurations from a URL representing either an XML or legacy Sunlogin configuration file. Note that all login configurations must be addedor none will be added. It returns the names of the login configurationsthat were added.

void removeConfigs(String[] appNames): this removes the login configurationsspecified appNames array.

String displayAppConfig(String appName): this operation displays a simple stringformat 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 bythe org.jboss.security.plugins.SecurityConfig MBean. There is one configurable attribute:

LoginConfig: Specifies the JMX ObjectName string of the that provides thedefault JAAS login configuration. When the SecurityConfig is started, thismean is queried for its javax.security.auth.login.Configuration by callingitsgetConfiguration(Configuration currentConfig) operation. Ifthe LoginConfig attribute is not specified then the defaultSun Configuration implementation described in the Configuration classJavaDocs 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 loginconfigurations into a default JBoss installation. Pusing a new configuration isdone using:

public void pushLoginConfig(String objectName) throwsJMException, 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 theauthentication mechanism using JAAS login module configurations. Bydefining the login module configuration entry that corresponds to the securitydomain name you have used to secure access to your J2EE components, youdefine the authentication mechanism and integration implementation.

The JBossSX framework includes a number of bundled login modules suitablefor integration with standard security infrastructure store protocols such asLDAP and JDBC. It also includes standard base class implementations that helpenforce the expectedLoginModule to Subject usage pattern that was described intheSection 8.4.7, “Writing Custom Login Modules”. These implementationsallow for easy integration of your own authentication protocol, if none of thebundled login modules prove suitable. In this section we will first describe theuseful bundled login modules and their configuration, and then end with adiscussion of how to create your own custom LoginModule implementations foruse with JBoss.

8.4.6.1. org.jboss.security.auth.spi.IdentityLoginModule

The IdentityLoginModule is a simple login module that associates the principalspecified in the module options with any subject authenticated against themodule. It creates a SimplePrincipal instance using the name specified bythe principal option. Although this is certainly not an appropriate login modulefor 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 givenprincipal and associated roles.

The supported login module configuration options include:

principal=string: The name to use for the SimplePrincipal all users areauthenticated as. The principal name defaults to guest if no principaloption is specified.

roles=string-list: The names of the roles that will be assigned to theuser principal. The value is a comma-delimited list of role names.

password-stacking=useFirstPass: When password-stacking option isset, this module first looks for a shared username under the propertyname javax.security.auth.login.name in the login module shared state map. Iffound this is used as the principal name. If not found the principal nameset by this login module is stored under the propertyname javax.security.auth.login.name.

A sample legacy Sun format login configuration entry that would authenticateall users as the principal named jduke and assign role names of TheDuke,and AnimatedCharacter is:

testIdentity {org.jboss.security.auth.spi.IdentityLoginModule requiredprincipal=jdukeroles=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 defaultconfiguration file set you would modify the conf/default/auth.conf file of the JBossdistribution.

8.4.6.2. org.jboss.security.auth.spi.UsersRolesLoginModule

The UsersRolesLoginModule is another simple login module that supports multipleusers and user roles, and is based on two Java Properties formatted text files.The username-to-password mapping file is called users.properties and theusername-to-roles mapping file is called roles.properties. The properties files areloaded during initialization using the initialize method thread context classloader. This means that these files can be placed into the J2EE deploymentJAR, the JBoss configuration directory, or any directory on the JBoss server orsystem classpath. The primary purpose of this login module is to easily test thesecurity settings of multiple users and roles using properties files deployedwith the application.

The users.properties file uses a username=password format with each user entry on aseparate line as show here:

username1=password1username2=password2...

The roles.properties file uses as username=role1,role2,... format with an optionalgroup 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 toa particular named group of roles where the XXX portion of the property nameis the group name. The username=... form is an abbreviation for username.Roles=...,where the Roles group name is the standard name the JaasSecurityManager expectsto 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 shouldbe assigned to requests that contain no authentication information.This can be used to allow unprotected servlets to invoke methods onEJBs that do not require a specific role. Such a principal has noassociated roles and so can only access either unsecured EJBs or EJBmethods that are associated with the unchecked permission constraint.

password-stacking=useFirstPass: When password-stacking option isset, this module first looks for a shared username and password underthe propertynames javax.security.auth.login.name and javax.security.auth.login.passwordrespectively in the login module shared state map. If found these are used as theprincipal name and password. If not found the principal name andpassword are set by this login module and stored under the propertynamesjavax.security.auth.login.name and javax.security.auth.login.password respectively.

hashAlgorithm=string: The name of the java.security.MessageDigest algorithmto use to hash the password. There is no default so this option must bespecified to enable hashing. When hashAlgorithm is specified, the clear textpassword obtained from the callbackhandler is hashed before it is passedto UsernamePasswordLoginModule.validatePassword as the inputPasswordargument. The expectedPassword as stored in the users.properties file must becomparably hashed.

hashEncoding=base64|hex: The string format for the hashed pass andmust be either base64 or hex. Base64 is the default.

hashCharset=string: The encoding used to convert the clear textpassword to a byte array. The platform default encoding is the default.

usersProperties=string: The name of the properties resource containingthe username to password mappings. This defaults to users.properties.

rolesProperties=string: The name of the properties resource containingthe username to roles mappings. This defaults to roles.properties.

A sample legacy Sun format login configuration entry that assignedunauthenticated users the principal name nobody and contains based64encoded, MD5 hashes of the passwords in a usersb64.properties file is:

381 | P a g e

testUsersRoles {org.jboss.security.auth.spi.UsersRolesLoginModule requiredusersProperties=usersb64.propertieshashAlgorithm=MD5hashEncoding=base64unauthenticatedIdentity=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 anLDAP server using JNDI login using the login module configuration options. Youwould use the LdapLoginModule if your username and credential information arestore in an LDAP server that is accessible using a JNDI LDAP provider.

The LDAP connectivity information is provided as configuration options thatare passed through to the environment object used to create JNDI initialcontext. The standard LDAP JNDI properties used include the following:

java.naming.factory.initial: The classname ofthe InitialContextFactory implementation. This defaults to the Sun LDAPprovider 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 thecaller to the service. This is built from other properties as describedbelow.

java.naming.security.credentials: The value of the property depends onthe authentication scheme. For example, it could be a hashedpassword, 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 theuser distinguished name. See principalDNSuffix for more info.

principalDNSuffix=string: A suffix to add to the username when formingthe user distiguished name. This is useful if you prompt a user for ausername and you don't want the user to have to enter the fullydistinguished name. Using this property andprincipalDNSuffix the userDN willbe formed as:

String userDN = principalDNPrefix + username + principalDNSuffix;

useObjectCredential=true|false: Indicates that the credential should beobtained as an opaque Object usingthe org.jboss.security.auth.callback.ObjectCallback type of Callback rather than asa 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 tosearch for user roles.

userRolesCtxDNAttributeName=string: The name of an attribute in theuser object that contains the distinguished name to the context tosearch for user roles. This differs from rolesCtxDN in that the context tosearch for a user's roles can be unique for each user.

roleAttributeID=string: The name of the attribute that contains theuser roles. If not specified this defaults to roles.

roleAttributeIsDN=string: A flag indicating whetherthe roleAttributeID contains the fully distinguished name of a role object, orthe role name. If false, the role name is taken from the valueof roleAttributeID. If true, the role attribute represents the distinguishedname of a role object. The role name is taken from the value ofthe roleNameAttributeId attribute of the context name by the distinguished

383 | P a g e

name. In certain directory schemas (e.g., MS ActiveDirectory), roleattributes in the user object are stored as DNs to role objects instead ofas simple names, in which case, this property should be set to true. Thedefault is false.

roleNameAttributeID=string: The name of the attribute of the in thecontext pointed to by the roleCtxDN distiguished name value whichcontains the role name. If the roleAttributeIsDN property is set to true, thisproperty is used to find the role object's name attribute. The defaultis group.

uidAttributeID=string: The name of the attribute in the objectcontaining the user roles that corresponds to the userid. This is used tolocate the user roles. If not specified this defaults to uid.

matchOnUserDN=true|false: A flag indicating if the search for userroles should match on the user's fully distinguished name. If false, justthe username is used as the match value againstthe uidAttributeName attribute. If true, the full userDN is used as the matchvalue.

unauthenticatedIdentity=string: The principal name that should beassigned to requests that contain no authentication information. Thisbehavior is inherited from the UsernamePasswordLoginModule superclass.

password-stacking=useFirstPass: When the password-stacking option isset, this module first looks for a shared username and password underthe propertynames javax.security.auth.login.name andjavax.security.auth.login.password respectively in the login module shared state map. If found these are used as theprincipal name and password. If not found the principal name andpassword are set by this login module and stored under the propertynames javax.security.auth.login.name and javax.security.auth.login.password respectively.

hashAlgorithm=string: The name of the java.security.MessageDigest algorithmto use to hash the password. There is no default so this option must bespecified to enable hashing. When hashAlgorithm is specified, the clear textpassword obtained from the callbackhandler is hashed before it is passedto UsernamePasswordLoginModule.validatePassword as the inputPassword argument.The expectedPassword as stored in the LDAP server must be comparablyhashed.

384 | P a g e

hashEncoding=base64|hex: The string format for the hashed pass andmust be either base64 or hex. Base64 is the default.

hashCharset=string: The encoding used to convert the clear textpassword to a byte array. The platform default encoding is the default.

allowEmptyPasswords: A flag indicating if empty (length 0) passwordsshould be passed to the LDAP server. An empty password is treated asan anonymous login by some LDAP servers and this may not be adesirable feature. Set this to false to reject empty passwords, true tohave the LDAP server validate the empty password. The default is true.

The authentication of a user is performed by connecting to the LDAP serverbased on the login module configuration options. Connecting to the LDAPserver is done by creating an InitialLdapContext with an environment composed ofthe LDAP JNDI properties described previously in this section.The Context.SECURITY_PRINCIPAL is set to the distinguished name of the user asobtained by the callback handler in combination withthe principalDNPrefix and principalDNSuffix option values, andthe Context.SECURITY_CREDENTIALS property is either set to the String password orthe Object credential depending on the useObjectCredential option.

Once authentication has succeeded by virtue of being able to createan InitialLdapContext instance, the user's roles are queried by performing a searchon the rolesCtxDN location with search attributes set tothe roleAttributeName anduidAttributeName option values. The roles names areobtaining by invoking the toString method on the role attributes in the searchresult set.

A sample Sun legacy format login configuration entry is:

testLdap {org.jboss.security.auth.spi.LdapLoginModule requiredjava.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactoryjava.naming.provider.url="ldap://ldaphost.jboss.org:1389/"java.naming.security.authentication=simpleprincipalDNPrefix=uid=uidAttributeID=useridroleAttributeID=roleNameprincipalDNSuffix=,ou=People,o=jboss.orgrolesCtxDN=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 thesample LDAP server data shown in Figure 8.9, “An LDAP server configurationcompatible with the testLdap sample configuration.”. This figure correspondsto the testLdaplogin configuration just shown.

386 | P a g e

Figure 8.9. An LDAP server configuration compatible with the testLdapsample configuration.

Take a look at the testLdap login module configuration in comparision tothe Figure 8.9, “An LDAP server configuration compatible with the testLdapsample configuration.” schema.The java.naming.factory.initial, java.naming.factory.url andjava.naming.security options indicatethe Sun LDAP JNDI provider implementation will be used, the LDAP server islocated on host ldaphost.jboss.org on port 1389, and that simple username andpassword will be used to authenticate clients connecting to the LDAP server.

When the LdapLoginModule performs authentication of a user, it does so byconnecting to the LDAP server specified by the java.naming.factory.url.The java.naming.security.principal property is built from the principalDNPrefix, passed inusername and principalDNSuffix as described above. For the testLdap configurationexample and a username of jduke, the java.naming.security.principal string wouldbe uid=jduke,ou=People,o=jboss.org. This corresponds to the LDAP context on thelower right of Figure 8.9, “An LDAP server configuration compatible with thetestLdap sample configuration.” labeled as Principal Context.The java.naming.security.credentials property would be set to the passed in passwordand 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 ofthejava.naming.security.credentials property differently.

Once authentication succeeds, the roles on which authorization will be basedare retrieved by performing a JNDI search of the LDAP context whosedistinguished name is given by the rolesCtxDN option value. Forthe testLdap configuration this iscn=JBossSX Tests,ou=Roles,o=jboss.org and correspondsto the LDAP context on the lower left of Figure 8.9, “An LDAP serverconfiguration compatible with the testLdap sampleconfiguration.” labeled Roles Context. The search attempts to locate anysubcontexts that contain an attribute whose name is given bythe uidAttributeID option, and whose value matches the username passed to thelogin module. For any matching context, all values of the attribute whosename is given by theroleAttributeID option are obtained. Forthe testLdap configuration the attribute name that contains the roles iscalled roleName. The resulting roleName values are stored in theJAAS Subject associated with the LdapLoginModule as the Roles group principals thatwill be used for role-based authorization. For the LDAP schema shownin Figure 8.9, “An LDAP server configuration compatible with the testLdapsample configuration.”, the roles that will be assigned to theuser jduke are TheDuke andAnimatedCharacter.

8.4.6.4. org.jboss.security.auth.spi.DatabaseServerLoginModule

The DatabaseServerLoginModule is a JDBC based login module that supportsauthentication and role mapping. You would use this login module if you haveyour 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 andthe Roles table associates the user PrincipalID with its role sets. The roles used foruser permissions must be contained in rows with a RoleGroup column valueofRoles. The tables are logical in that you can specify the SQL query that thelogin module uses. All that is required is that the java.sql.ResultSet has the samelogical 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 accessedbased on the column index. To clarify this notion, consider a database withtwo tables, Principals and Roles, as already declared. The following statementsbuild the tables to contain aPrincipalID java with a Password of echoman inthe Principals table, a PrincipalID java with a role named Echo in the Roles RoleGroup inthe Roles table, and a PrincipalID java with a role named caller_java inthe 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 databasecontaining the logical Principals and Roles tables. If not specified thisdefaults to java:/DefaultDS.

principalsQuery: The prepared statement query equivalent to: selectPassword from Principals where PrincipalID=?. If not specified this is the exactprepared 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 exactprepared statement that will be used.

unauthenticatedIdentity=string: The principal name that should beassigned to requests that contain no authentication information.

password-stacking=useFirstPass: When password-stacking option is set, thismodule first looks for a shared username and password under thepropertynames javax.security.auth.login.name andjavax.security.auth.login.password respectively in the login module shared state map. If found these are used as theprincipal name and password. If not found the principal name andpassword are set by this login module and stored under the propertynames javax.security.auth.login.name and javax.security.auth.login.password respectively.

hashAlgorithm=string: The name of the java.security.MessageDigest algorithmto use to hash the password. There is no default so this option must bespecified to enable hashing. When hashAlgorithm is specified, the clear textpassword obtained from the callbackhandler is hashed before it is passed

389 | P a g e

to UsernamePasswordLoginModule.validatePassword as the inputPasswordargument. The expectedPassword as obtained from the database must becomparably hashed.

hashEncoding=base64|hex: The string format for the hashed pass andmust be either base64 or hex. Base64 is the default.

hashCharset=string: The encoding used to convert the clear textpassword to a byte array. The platform default encoding is the default

ignorePasswordCase=true|false: A boolean flag indicating if thepassword comparison should ignore case. This can be useful for hashedpassword encoding where the case of the hashed password is notsignificant.

principalClass: An option that specifies a Principal implementationclass. This must support a constructor taking a string argument for theprincpal name.

As an example DatabaseServerLoginModule configuration, consider a custom tableschema 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 DatabaseServerLoginModuleconfiguration would be:

testDB {org.jboss.security.auth.spi.DatabaseServerLoginModule requireddsJndiName="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. Atypical usecase for this login module is CLIENT-CERT authentication in the webtier. This login module only performs authentication. You need to combine itwith another login module capable of acquiring the authorization roles tocompletely define access to a secured web or EJB component. Two subclassesof this loginmodule, CertRolesLoginModule and DatabaseCertLoginModule extend thebehavior to obtain the authorization roles from either a properties file ordatabase.

The BaseCertLoginModule needs a KeyStore to perform user validation. This isobtained through a org.jboss.security.SecurityDomain implementation.Typically, the SecurityDomain implementation is configured usingtheorg.jboss.security.plugins.JaasSecurityDomain MBean as shown inthis 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 thename java:/jaas/jmx-console following the JBossSX security domain namingpattern. To secure a web application such as thejmx-console.war using clientcerts and role based authorization, one would first modify the web.xml todeclare the resources to be secured, along with the allowed roles and securitydomain 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 webapplication </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-consolesecurity 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, andthe 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 theclient cert. By default, the principal is created using the client certificatedistinguished name. Consider the following certificate:

[starksm@banshee9100 conf]$ keytool -printcert -file unit-tests-client.exportOwner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=USIssuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, [email protected], OU=QA, O=JBoss Inc.Serial number: 100103Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005Certificate fingerprints:

MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:ABSHA1: 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 wouldalso need an entry for the same entry. Since the DN contains many charactersthat are normally treated as delimiters, you will need to escape the problemcharacters using a backslash ('\') as shown here:

# A sample roles.properties file for use with the UsersRolesLoginModuleCN\=unit-tests-client,\ OU\=JBoss\ Inc.,\ O\=JBoss\ Inc.,\ ST\=Washington,\ C\=US=JBossAdminadmin=JBossAdmin

8.4.6.6. org.jboss.security.auth.spi.ProxyLoginModule

The ProxyLoginModule is a login module that loads a delegate LoginModule usingthe current thread context class loader. The purpose of this module is to workaround the current JAAS 1.0 class loader limitation that requires LoginModules tobe on the system classpath[2]. Some custom LoginModules use classes that areloaded from the JBoss server lib/ext directory and these are not available ifthe LoginModule is placed on the system classpath. To work around thislimitation 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 isto be bootstrapped. Any number of additional configuration options may bespecified, and they will be passed to the bootstrapped login module.

As an example, consider a custom login module that makes use of someservice that is loaded from the JBoss lib/ext directory. The class name of thecustom login module is com.biz.CustomServiceLoginModule. A suitable Sun legacyformatProxyLoginModule configuration entry for bootstrapping this custom loginmodule would be:

testProxy {org.jboss.security.auth.spi.ProxyLoginModule requiredmoduleName=com.biz.CustomServiceLoginModulecustomOption1=value1customOption2=value2customOption3=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 rolefor the duration of the login phase of authentication, and pops the run as rolein either the commit or abort phase. The purpose of this login module is toprovide a role for other login modules that need to access secured resourcesin 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 ofthe 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 loginphase. 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 clientsfor the establishment of the caller identity and credentials. This simply setsthe org.jboss.security.SecurityAssociation.principal to the value of theNameCallback filled inby the callbackhandler, and the org.jboss.security.SecurityAssociation.credential to the valueof the PasswordCallback filled in by the callbackhandler. This is the only supportedmechanism for a client to establish the current thread's caller. Both stand-alone client applications and server environments, acting as JBoss EJB clientswhere the security environment has not been configured to use JBossSXtransparently, need to use the ClientLoginModule. Of course, you could always setthe org.jboss.security.SecurityAssociation information directly, but this is considered aninternal API that is subject to change without notice.

Note that this login module does not perform any authentication. It merelycopies the login information provided to it into the JBoss server EJB invocationlayer for subsequent authentication on the server. If you need to performclient-side authentication of users you would need to configure another loginmodule 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 totrue, each login thread has its own principal and credential storage. Thisis useful in client environments where multiple user identities are activein separate threads. When true, each separate thread must perform itsown login. When set to false the login identity and credentials areglobal variables that apply to all threads in the VM. The default for thisoption is false.

395 | P a g e

password-stacking=useFirstPass: When password-stacking option is set, thismodule first looks for a shared username and passwordusing javax.security.auth.login.name and javax.security.auth.login.password respectivelyin the login module shared state map. This allows a module configuredprior to this one to establish a valid username and password thatshould be passed to JBoss. You would use this option if you want toperform client-side authentication of clients using some other loginmodule such as the LdapLoginModule.

restore-login-identity=[true|false]: When restore-login-identity is true,the SecurityAssociation principal and credential seen on entry tothe login() method are saved and restored on either abort or logout.When false (the default), the abort and logout simply clearthe SecurityAssociation. A restore-login-identity of true is needed if one need tochange identities and then restore the original caller identity.

A sample login configuration for ClientLoginModule is the default configurationentry found in the JBoss distribution client/auth.conf file. The configuration is:

other {// Put your login modules that work without jBoss here

// jBoss LoginModuleorg.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 withyour security environment, you can write your own custom login moduleimplementation that does.

Recall from the section on the JaasSecurityManager architecture thatthe JaasSecurityManager expected a particular usage pattern of the Subject principalsset. You need to understand the JAAS Subject class's information storagefeatures and the expected usage of these features to be able to write a loginmodule that works with the JaasSecurityManager. This section examines thisrequirement and introduces two abstract base LoginModule implementationsthat 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 usingthe 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). Theusage pattern is as follows:

User identities (username, social security number, employee ID, and soon) are stored as java.security.Principal objects in the SubjectPrincipals set.The Principal implementation that represents the user identity must basecomparisons and equality on the name of the principal. A suitableimplementation 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 aregrouped in named role sets using java.security.acl.Group instances.The Group interface defines a collection of Principals and/or Groups, and is asubinterface ofjava.security.Principal. Any number of role sets can beassigned to a Subject. Currently, the JBossSX framework uses two well-known role sets with the names Roles and CallerPrincipal. The Roles Group isthe collection of Principals for the named roles as known in theapplication domain under which the Subject has been authenticated. Thisrole set is used by methods like the EJBContext.isCallerInRole(String), which EJBscan use to see if the current caller belongs to the named applicationdomain role. The security interceptor logic that performs methodpermission checks also uses this role set. The CallerPrincipalGroup consists ofthe single Principal identity assigned to the user in the applicationdomain. TheEJBContext.getCallerPrincipal() method uses the CallerPrincipal toallow the application domain to map from the operation environmentidentity to a user identity suitable for the application. If a Subject doesnot have aCallerPrincipalGroup, the application identity is the same asoperational 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 inthe preceding section, JBossSX includes two abstract login modules thathandle the population of the authenticated Subject with a template pattern thatenforces correct Subjectusage. The most generic of the two isthe org.jboss.security.auth.spi.AbstractServerLoginModule class. It provides a concreteimplementation of the javax.security.auth.spi.LoginModule interface and offersabstract methods for the key tasks specific to an operation environmentsecurity infrastructure. The key details of the class are highlighted in thefollowing class fragment. The JavaDoc comments detail the responsibilities ofsubclasses.

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 AbstractServerLoginModuleimplements 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 setto true if the login succeeds, false otherwise by any subclasses that overridethe login method. Failure to set this variable correctly will result in the commitmethod either not updating the Subject when it should, or updatingthe Subject when it should not. Tracking the outcome of the login phase wasadded to allow login module to be chained together with control flags that donot require that the login module succeed in order for the overall login tosucceed.

The second abstract base login module suitable for custom login modules isthe org.jboss.security.auth.spi.UsernamePasswordLoginModule. The login module furthersimplifies custom login module implementation by enforcing a string-basedusername as the user identity and a char[] password as the authenticationcredential. It also supports the mapping of anonymous users (indicated by anull username and password) to a Principal with no roles. The key details of theclass are highlighted in the following class fragment. The JavaDoc commentsdetail 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 UsernamePasswordLoginModuleextends 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 subclassingthe AbstractServerLoginModule versus UsernamePasswordLoginModule is simply based onwhether a String based username and String credential are usable for theauthentication technology you are writing the login module for. If the stringbased semantic is valid, then subclass UsernamePasswordLoginModule, elsesubclass AbstractServerLoginModule.

The steps you are required to perform when writing a custom login moduleare summerized in the following depending on which base login module classyou choose. When writing a custom login module that integrates with yoursecurity infrastructure, you should start bysubclassing AbstractServerLoginModule or UsernamePasswordLoginModule to ensure thatyour login module provides the authenticated Principal information in the formexpected by the JBossSX security manager.

When subclassing the AbstractServerLoginModule, you need to override thefollowing:

402 | P a g e

void initialize(Subject, CallbackHandler, Map, Map): if you have custom options toparse.

boolean login(): to perform the authentication activity. Be sure to setthe loginOk instance variable to true if login succeeds, false if it fails.

Principal getIdentity(): to return the Principal object for the user authenticatedby the log() step.

Group[] getRoleSets(): to return at least one Group named Roles that containsthe roles assigned to the Principal authenticated during login(). A secondcommon Group is named CallerPrincipal and provides the user's applicationidentity rather than the security domain identity.

When subclassing the UsernamePasswordLoginModule, you need to override thefollowing:

void initialize(Subject, CallbackHandler, Map, Map): if you have custom options toparse.

Group[] getRoleSets(): to return at least one Group named Roles that containsthe roles assigned to the Principal authenticated during login(). A secondcommon Group is named CallerPrincipal and provides the user's applicationidentity rather than the security domain identity.

String getUsersPassword(): to return the expected password for the currentusername available via the getUsername() method.The getUsersPassword() method is called from within login() afterthe 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 extendthe UsernamePasswordLoginModule and obtains a user's password and role namesfrom a JNDI lookup. The idea is that there is a JNDI context that will return auser's password if you perform a lookup on the context using a name of theform password/<username> where <username> is the current user beingauthenticated. Similary, a lookup of the form roles/<username> returns therequested user's roles.

The source code for the example is located inthe src/main/org/jboss/chap8/ex2 directory of the book examples. Example 8.12, “ AJndiUserAndPass custom login module” shows the source code for

403 | P a g e

the JndiUserAndPass custom login module. Note that because this extends theJBoss UsernamePasswordLoginModule, all the JndiUserAndPass does is obtain the user'spassword and roles from the JNDI store. The JndiUserAndPass does not concernitself 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 [email protected]* @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 inthe 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 lookupoperations done against it by checking the prefix of the lookup nameagainst password and roles. When the name begins with password, a user'spassword is being requested. When the name begins with roles the user's rolesare being requested. The example implementation always returns a passwordof theduke and an array of roles names equal to {"TheDuke", "Echo"} regardless ofwhat the username is. You can experiment with other implementations as youwish.

The example code includes a simple session bean for testing the custom loginmodule. To build, deploy and run the example, execute the followingcommand from the examples directory. Make sure you have the JBoss serverrunning. 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 isshown in Example 8.14, “The chap8-ex2 server side behavior of theJndiUserAndPass”.

Example 8.13. The chap8-ex2 secured client access output

[nr@toki examples]$ ant -Dchap=chap8 -Dex=2 run-exampleBuildfile: 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 EchoBean217:48:11,890 INFO [JndiStore] Start, bound security/store17:48:11,896 INFO [SecurityConfig] Using JAAS AuthConfig: jar:file:/private/tmp/jboss-3.2.6/server/default/tmp/deploy/tmp22821chap8-ex2.jar-contents/chap8-ex2.sar!/META-INF/login-config.xml17: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 sideauthentication 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 thesecurity domain and the sar META-INF/login-config.xml descriptor defines the loginmodule configuration. The contents of these descriptors are shownin Example 8.15, “The chap8-ex2 security domain and login moduleconfiguration”.

Example 8.15. The chap8-ex2 security domain and login moduleconfiguration

<?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-ex2application

<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 areread when JBoss starts up, but there is no easy way to add a new securitydomain 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 (orjust 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 touse. 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 theconfigurations.

SecurityManagerService: The SecurityManagerService name used to flush theregistered security domains. This service must supporta flushAuthenticationCache(String) operation to flush the case for the argumentsecurity domain. Setting this triggers the flush of the authenticationcaches 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.xmlconfigurations.

--><depends optional-attribute-name="LoginConfigService">

jboss.security:service=XMLLoginConfig </depends><!-- Optionally specify the security mgr service to use whenthis service is stopped to flush the auth caches of the domainsregistered by this service.

--><depends optional-attribute-name="SecurityManagerService">

jboss.security:service=JaasSecurityManager </depends></mbean>

</server>

This will load the specified AuthConfig resource using thespecified LoginConfigService MBean by invoking loadConfig with the apropriateresource URL. When the service is stopped the configurations are removed.The resource specified may be either an XML file, or a Sun JAAS loginconfiguration.

8.5. The Secure Remote Password (SRP) Protocol

The SRP protocol is an implementation of a public key exchange handshakedescribed in the Internet standards working group request for comments2945(RFC2945). The RFC2945 abstract states:

This document describes a cryptographically strong network authenticationmechanism 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 traditionallyassociated with reusable passwords. This system also performs a secure keyexchange in the process of authentication, allowing security layers (privacyand/or integrity protection) to be enabled during the session. Trusted keyservers and certificate infrastructures are not required, and clients are notrequired to store or manage any long-term keys. SRP offers both security anddeployment advantages over existing challenge-response techniques, makingit an ideal drop-in replacement where secure password authentication isneeded.

Note: The complete RFC2945 specification can be obtainedfrom http://www.rfc-editor.org/rfc.html. Additional information on the SRPalgorithm 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 away that does not require a clear text password to exist on the server. This isin contrast to other public key-based algorithms that require client certificatesand the corresponding certificate management infrastructure.

Algorithms like Diffie-Hellman and RSA are known as public key exchangealgorithms. 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 knownonly to you. When someone wants to send encrypted information to you, thenencrpyt the information using your public key. Only you are able to decryptthe information using your private key. Contrast this with the more traditionalshared password based encryption schemes that require the sender andreceiver to know the shared password. Public key algorithms eliminate theneed to share passwords. For more information on public key algorithms aswell 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 thefollowing elements:

409 | P a g e

An implementation of the SRP handshake protocol that is independentof any particular client/server protocol

An RMI implementation of the handshake protocol as the defaultclient/server SRP implementation

A client side JAAS LoginModule implementation that uses the RMIimplementation for use in authenticating clients in a secure fashion

A JMX MBean for managing the RMI server implementation. The MBeanallows the RMI server implementation to be plugged into a JMXframework and externalizes the configuration of the verificationinformation store. It also establishes an authentication cache that isbound into the JBoss server JNDI namespace.

A server side JAAS LoginModule implementation that uses theauthentication cache managed by the SRP JMX MBean.

Figure 8.10, “The JBossSX components of the SRP client-serverframework.” gives a diagram of the key components involved in the JBossSXimplementation 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 implementationthat communicates to the authentication server throughan org.jboss.security.srp.SRPServerInterface proxy. A client enables authentication usingSRP by creating a login configuration entry that includesthe org.jboss.security.srp.jaas.SRPLoginModule. This module supports the followingconfiguration options:

principalClassName: This option is no longer supported. The principalclass is now always org.jboss.security.srp.jaas.SRPPrincipal.

srpServerJndiName: The JNDI name of the SRPServerInterface object to usefor 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 ofthe SRPServerInterface proxy to use for communicating with the SRPauthentication server.

externalRandomA: A true/false flag indicating if the randomcomponent of the client public key A should come from the usercallback. This can be used to input a strong cryptographic randomnumber coming from a hardware token for example.

hasAuxChallenge: A true/false flag indicating an that a string will besent to the server as an additional challenge for the server to validate. Ifthe client session supports an encryption cipher then a temporarycipher will be created using the session private key and the challengeobject sent as a javax.crypto.SealedObject.

multipleSessions: a true/false flag indicating if a given client may havemultiple SRP login sessions active simultaneously.

Any other options passed in that do not match one of the previous namedoptions is treated as a JNDI property to use for the environment passed tothe IntialContext constructor. This is useful if the SRP server interface is notavailable from the defaultIntialContext.

The SRPLoginModule needs to be configured along with thestandard ClientLoginModule to allow the SRP authentication credentials to be usedfor validation of access to security J2EE components. An example loginconfiguration entry that demonstrates such a setup is:

srp {org.jboss.security.srp.jaas.SRPLoginModule requiredsrpServerJndiName="SRPServerInterface";

org.jboss.security.ClientLoginModule requiredpassword-stacking="useFirstPass";

};

On the JBoss server side, there are two MBeans that manage the objects thatcollectively make up the SRP server. The primary service isthe 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 SRPauthentication session cache. The configurable SRPService MBean attributesinclude the following:

JndiName: The JNDI name from which the SRPServerInterface proxyshould be available. This is the location where the SRPService binds theserializable dynamic proxy to the SRPServerInterface. If not specified itdefaults tosrp/SRPServerInterface.

VerifierSourceJndiName: The JNDI name ofthe SRPVerifierSource implementation that should be used by the SRPService.If not set it defaults to srp/DefaultVerifierSource.

AuthenticationCacheJndiName: The JNDI name under which theauthentication org.jboss.util.CachePolicy implementation to be used forcaching authentication information is bound. The SRP session cache ismade available for use through this binding. If not specified it defaultsto srp/AuthenticationCache.

ServerPort: RMI port for the SRPRemoteServerInterface. If not specified itdefaults to 10099.

ClientSocketFactory: An optionalcustom java.rmi.server.RMIClientSocketFactory implementation class name usedduring the export of the SRPServerInterface. If not specified thedefault RMIClientSocketFactory is used.

ServerSocketFactory: An optionalcustom java.rmi.server.RMIServerSocketFactory implementation class name usedduring the export of the SRPServerInterface. If not specified thedefault RMIServerSocketFactory is used.

AuthenticationCacheTimeout: Specifies the timed cache policy timeoutin seconds. If not specified this defaults to 1800 seconds(30 minutes).

AuthenticationCacheResolution: Specifies the timed cache policyresolution in seconds. This controls the interval between checks fortimeouts. If not specified this defaults to 60 seconds(1 minute).

RequireAuxChallenge: Set if the client must supply an auxillarychallenge as part of the verify phase. This gives control over whetherthe SRPLoginModule configuration used by the client must havethe useAuxChallenge option enabled.

OverwriteSessions: A flag indicating if a successful user auth for anexisting 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 enabledthe multiple session per user mode. The default is false meaning thatthe second attempt by a user to authentication will succeeed, but theresulting SRP session will not overwrite the previous SRP session state.

The one input setting is the VerifierSourceJndiName attribute. This is the location ofthe SRP password information store implementation that must be providedand made available through JNDI. The org.jboss.security.srp SRPVerifierStoreService is anexample MBean service that binds an implementation ofthe SRPVerifierStore interface that uses a file of serialized objects as the persistentstore. Although not realistic for a production environment, it does allow fortesting of the SRP protocol and provides an example of the requirements foran SRPVerifierStore service. The configurable SRPVerifierStoreService MBean attributesinclude the following:

JndiName: The JNDI name from which the SRPVerifierStore implementationshould be available. If not specified it defaults to srp/DefaultVerifierSource.

StoreFile: The location of the user password verifier serialized objectstore file. This can be either a URL or a resource name to be found inthe classpath. If not specified it defaults to SRPVerifierStore.ser.

The SRPVerifierStoreService MBean also supports addUser and delUser operations foraddition 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, “TheSecure Remote Password (SRP) Protocol”.

8.5.1. Providing Password Information for SRP

The default implementation of the SRPVerifierStore interface is not likely to besuitable for you production security environment as it requires all passwordhash information to be available as a file of serialized objects. You need toprovide an MBean service that provides an implementation ofthe SRPVerifierStore interface that integrates with your existing securityinformation 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 tothe SRPVerifierStore.VerifierInfo object for a given username.The getUserVerifier(String) method is called by the SRPService at that start of a userSRP session to obtain the parameters needed by the SRP algorithm. Theelements 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 hasa calculateVerifier method that performs that password hashing algorithm.The output passwordH(salt | H(username | ':' | password)) as defined byRFC2945. Here H is the SHA secure hash function. The username isconverted from a string to a byte[] using the UTF-8 encoding.

salt: This is a random number used to increase the difficulty of a bruteforce dictionary attack on the verifier password database in the eventthat the database is compromised. It is a value that should begenerated from a cryptographically strong random number algorithmwhen the user's existing clear-text password is hashed.

g: The SRP algorithm primitive generator. In general this can be a wellknown fixed parameter rather than a per-user setting.The org.jboss.security.srp.SRPConf utility class provides several settings for gincluding a good default which can obtainedvia SRPConf.getDefaultParams().g().

N: The SRP algorithm safe-prime modulus. In general this can be a wellknown fixed parameter rather than a per-user setting.The org.jboss.security.srp.SRPConf utility class provides several settingsfor N including a good default which can obtainedvia SRPConf.getDefaultParams().N().

So, step 1 of integrating your existing password store is the creation of ahashed version of the password information. If your passwords are alreadystore in an irreversible hashed form, then this can only be done on a per-userbasis as part of an upgrade proceedure for example. Note thatthe 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 anexception stating that the store is read-only.

Step 2 is the creation of the custom SRPVerifierStore interface implementationthat 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 theclient SRPLoginModule configuration specifies the hasAuxChallenge option. This can beused to integrate existing hardware token based schemes like SafeWord orRadius into the SRP algorithm.

Step 3 is the creation of an MBean that makes the step 2 implementation ofthe SRPVerifierStore interface available via JNDI, and exposes any configurableparameters you need. In addition to thedefaultorg.jboss.security.srp.SRPVerifierStoreService example, the SRP example presentedlater in this chapter provides a Java properties filebased SRPVerifierStore implementation. Between the two examples you shouldhave 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 ofclient and server using simple text passwords without a secure communicationchannel. You might be wondering how this is done. If you want the completedetails and theory behind the algorithm, refer to the SRP referencesmentioned in a note earlier. There are six steps that are performed tocomplete authentication:

1. The client side SRPLoginModule retrieves the SRPServerInterface instancefor the remote authentication server from the naming service.

2. The client side SRPLoginModule next requests the SRP parametersassociated with the username attempting the login. There are a numberof parameters involved in the SRP algorithm that must be chosen whenthe user password is first transformed into the verifier form used by theSRP algorithm. Rather than hard-coding the parameters (which could bedone with minimal security risk), the JBossSX implementation allows auser to retrieve this information as part of the exchange protocol.ThegetSRPParameters(username) call retrieves the SRP parameters for thegiven username.

417 | P a g e

3. The client side SRPLoginModule begins an SRP session by creatingan SRPClientSession object using the login username, clear-text password,and SRP parameters obtained from step 2. The client then creates arandom 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 invokingthe SRPServerInterface.init method and passes in the username and clientgenerated random number A. The server returns its own randomnumber B. This step corresponds to the exchange of public keys.

4. The client side SRPLoginModule obtains the private SRP session key that hasbeen generated as a result of the previous messages exchanges. This issaved as a private credential in the login Subject. The server challengeresponse M2 from step 4 is verified by invokingthe SRPClientSession.verify method. If this succeeds, mutual authentication ofthe client to server, and server to client have been completed.The clientside SRPLoginModule next creates a challenge M1 to the server byinvokingSRPClientSession.response method passing the server randomnumber B as an argument. This challenge is sent to the server viathe SRPServerInterface.verify method and server's response is saved as M2.This step corresponds to an exchange of challenges. At this point theserver has verified that the user is who they say they are.

5. The client side SRPLoginModule saves the login username and M1 challengeinto the LoginModule sharedState map. This is used as the Principal nameand credentials by the standard JBoss ClientLoginModule. The M1 challengeis used in place of the password as proof of identity on any methodinvocations on J2EE components. The M1 challenge is acryptographically strong hash associated with the SRP session. Itsinterception via a third partly cannot be used to obtain the user'spassword.

6. At the end of this authentication protocol, the SRPServerSession hasbeen placed into the SRPService authentication cache for subsequentuse by the SRPCacheLoginModule.

Although SRP has many interesting properties, it is still an evolving componentin the JBossSX framework and has some limitations of which you should beaware. Issues of note include the following:

418 | P a g e

Because of how JBoss detaches the method transport protocol from thecomponent container where authentication is performed, anunauthorized user could snoop the SRP M1 challenge and effectively usethe challenge to make requests as the associated username. Custominterceptors that encrypt the challenge using the SRP session key can beused to prevent this issue.

The SRPService maintains a cache of SRP sessions that time out after aconfigurable period. Once they time out, any subsequent J2EEcomponent access will fail because there is currently no mechanism fortransparently renegotiating the SRP authentication credentials. Youmust either set the authentication cache timeout very long (up to2,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 thatcan be used for encryption/decryption between the client and server,the session is effectively a stateful one. JBoss supports for multiple SRPsessions per user, but you cannot encrypt data with one session key andthen decrypt it with another.

To use end-to-end SRP authentication for J2EE component calls, you need toconfigure the security domain under which the components are secured touse the org.jboss.security.srp.jaas.SRPCacheLoginModule. The SRPCacheLoginModule has asingle configuration option named cacheJndiName that sets the JNDI location ofthe SRP authentication CachePolicy instance. This must correspond tothe AuthenticationCacheJndiName attribute value of the SRPService MBean.TheSRPCacheLoginModule authenticates user credentials by obtaining the clientchallenge from the SRPServerSession object in the authentication cache andcomparing this to the challenge passed as the user credentials. Figure 8.11, “Asequence diagram illustrating the interaction of the SRPCacheLoginModulewith the SRP session cache.” illustrates the operation of theSRPCacheLoginModule.login method implementation.

419 | P a g e

Figure 8.11. A sequence diagram illustrating the interaction of theSRPCacheLoginModule 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 todemonstrate SRP in practice with an example. The example demonstratesclient side authentication of the user via SRP as well as subsequent securedaccess 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 ofthe server side login module configuration and SRP services. As in the previousexamples we will dynamically install the server side login moduleconfiguration using the SecurityConfig MBean. In this example we also use acustom implementation of the SRPVerifierStore interface that uses an in memorystore that is seeded from a Java properties file rather than a serialized objectstore as used by the SRPVerifierStoreService. This custom serviceis org.jboss.chap8.ex3.service.PropertiesVerifierStore. The following shows the contents ofthe 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.jaroutput/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 servicesconfiguration, 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 serverside XMLLoginConfig configuration” give the example client side and serverside login module configurations.

Example 8.18. The chap8-ex3.sar jboss-service.xml descriptor for the SRPservices

<server><!-- The custom JAAS login configuration that installs

a Configuration capable of dynamically updating theconfig 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 sideauthentication 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 verifierinformation -->

<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 requiredsrpServerJndiName="srp-test/SRPServerInterface";

org.jboss.security.ClientLoginModule requiredpassword-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 andthe PropertiesVerifierStore and SRPService MBeans. Note that the JndiName attribute ofthe PropertiesVerifierStore is equal to the VerifierSourceJndiName attribute ofthe SRPService, and that the SRPService depends on the PropertiesVerifierStore. This isrequired because the SRPService needs an implementation of

422 | P a g e

the SRPVerifierStore interface for accessing user password verificationinformation.

The client side login module configuration makes use of the SRPLoginModule witha srpServerJndiName option value that corresponds to the JBoss servercomponent SRPService JndiName attribute value(srp-test/SRPServerInterface). Alsoneeded is the ClientLoginModule configured with the password-stacking="useFirstPass" value to propagate the user authentication credentialsgenerated 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 tellsthe SRPCacheLoginModule the location of the CachePolicy that containstheSRPServerSession for users who have authenticated against the SRPService. Thisvalue 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 loginmodule with the SRPCacheLoginModule because SRP is only an authenticationtechnology. A second login module needs to be configured that accepts theauthentication credentials validated by the SRPCacheLoginModule to set theprincipal's roles that determines the principal's permissions.The UsersRolesLoginModule is augmenting the SRP authentication with propertiesfile based authorization. The user's roles are coming the roles.properties fileincluded in the EJB JAR.

Now, run the example 3 client by executing the following command from thebook examples directory:

[starksm@banshee examples]$ ant -Dchap=chap8 -Dex=3 run-exampleBuildfile: 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 adetailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key andverification.

Note that the client has taken a long time to run relative to the other simpleexamples. The reason for this is the construction of the client's public key. Thisinvolves the creation of a cryptographically strong random number, and thisprocess takes quite a bit of time the first time it occurs. If you were to log outand log in again within the same VM, the process would be much faster. Alsonote that Echo.echo()#2 fails with an authentication exception. The client codesleeps for 15 seconds after making the first call to demonstrate the behaviorof the SRPService cache expiration. The SRPService cache policy timeout has beenset to a mere 10 seconds to force this issue. As stated earlier, you need tomake 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. Ifyou want to restrict privileges of code using Java 2 permissions you need toconfigure the JBoss server to run under a security manager. This is done byconfiguring the Java VM options in the run.bat or run.sh scripts in the JBoss serverdistribution bin directory. The two required VM options are as follows:

java.security.manager: This is used without any value to specify thatthe default security manager should be used. This is the preferredsecurity manager. You can also pass a value tothe java.security.manager option to specify a custom security managerimplementation. The value must be the fully qualified class name of asubclass of java.lang.SecurityManager. This form specifies that the policy fileshould augment the default security policy as configured by the VMinstallation.

java.security.policy: This is used to specify the policy file that willaugment the default security policy information for the VM. This optiontakes twoforms: java.security.policy=policyFileURL and java.security.policy==policyFileURL. The firstform specifies that the policy file should augment the default securitypolicy 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 valuecan be any URL for which a protocol handler exists, or a file pathspecification.

Example 8.21, “The modifications to the Win32 run.bat start script to runJBoss with a Java 2 security manager.” illustrates a fragment of the standardrun.bat start script for Win32 that shows the addition of these two options tothe command line used to start JBoss.

Example 8.21. The modifications to the Win32 run.bat start script to runJBoss with a Java 2 security manager.

...

set CONFIG=%1@if "%CONFIG%" == "" set CONFIG=defaultset PF=../conf/%CONFIG%/server.policyset OPTS=-Djava.security.managerset 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 runJBoss with a Java 2 security manager.” shows a fragment of the standardrun.sh start script for UNIX/Linux systems that shows the addition of thesetwo options to the command line used to start JBoss.

Example 8.22. The modifications to the UNIX/Linux run.sh start script to runJBoss with a Java 2 security manager.

# ...

CONFIG=$1if [ "$CONFIG" == "" ]; then CONFIG=default; fiPF=../conf/$CONFIG/server.policyOPTS=-Djava.security.managerOPTS="$OPTS -Djava.security.policy=$PF"echo JBOSS_CLASSPATH=$JBOSS_CLASSPATHjava $HOTSPOT $JAXP $OPTS -classpath $JBOSS_CLASSPATH org.jboss.Main $@

Both start scripts are setting the security policy file to the server.policy filelocated in the JBoss configuration file set directory that corresponds to theconfiguration 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 modifythe start script.

Enabling Java 2 security is the easy part. The difficult part of Java 2 security isestablishing the allowed permissions. If you look at the server.policy file that iscontained in the default configuration file set, you'll see that it contains thefollowing permission grant statement:

grant {// Allow everything for nowpermission java.security.AllPermission;

};

This effectively disables security permission checking for all code as it says anycode can do anything, which is not a reasonable default. What is a reasonableset of permissions is entirely up to you.

The current set of JBoss specific java.lang.RuntimePermissions that are requiredinclude:

TargetName What the permission allows Risks

org.jboss.security.SecurityAssociation.getPrincipalInfo

Access to theorg.jboss.security.SecurityAssociation getPrincipal() and getCredentials()methods.

The ability to see thecurrent thread caller andcredentials.

org.jboss.security.SecurityAssociation.setPrincipalInfo

Access to theorg.jboss.security.SecurityAssociation setPrincipal() and setCredentials()methods.

The ability to set thecurrent thread caller andcredentials.

org.jboss.security.SecurityAssociation.setServer

Access to theorg.jboss.security.SecurityAssociation setServer method.

The ability to enable ordisable multithreadstorage of the callerprincipal and credential.

org.jboss.security.SecurityAssociation.setRunAsRole

Access to theorg.jboss.security.SecurityAssociation pushRunAsRole and popRunAsRole

The ability to change thecurrent 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 securitypolicy settings. There are various debugging flag that you can set to determinehow the security manager is using your security policy file as well as whatpolicy files are contributing permissions. Running the VM as follows shows thepossible debugging flag settings:

[nr@toki bin]$ java -Djava.security.debug=help

all turn on all debuggingaccess print all checkPermission resultscombiner SubjectDomainCombiner debuggingjar jar verificationlogincontext login context resultspolicy loading and grantingprovider security provider debuggingscl permissions SecureClassLoader assigns

The following can be used with access:

stack include stack tracedomain dumps all domains in contextfailure 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 outputvolume is torrential. This might be a good place to start if you don'tunderstand a given security failure at all. A less verbose setting that helpsdebug permission failures is to use -Djava.security.debug=access,failure. This is stillrelatively verbose, but not nearly as bad as the all mode as the securitydomain 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 withJBoss and it comes with JDK 1.4. For more information on JSSEsee: 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 thefollowing:

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 thefollowing 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 inthe form of an X509 certificate for use by the SSL server sockets. For thepurpose of this example we have created a self-signed certificate using theJDK keytool and included the resulting keystore file in the chap8 sourcedirectory as chap8.keystore. It was created using the following command andinput:

[nr@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore -validity 3650[orb@toki examples]$ keytool -genkey -alias rmi+ssl -keyalg RSA -keystore chap8.keystore -validity 3650Enter keystore password: rmi+sslWhat is your first and last name?[Unknown]: Chapter 8 SSL ExampleWhat is the name of your organizational unit?[Unknown]: JBoss BookWhat is the name of your organization?[Unknown]: JBoss, Inc.What is the name of your City or Locality?[Unknown]: IssaquahWhat is the name of your State or Province?[Unknown]: WAWhat is the two-letter country code for this unit?[Unknown]: USIs CN=Chapter 8 SSL Example, OU=JBoss Book, O="JBoss, Inc.", L=Issaquah, ST=WA, C=US correct?[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 ofsecurity keys. There are two different types of entries in a keystore:

key entries: each entry holds very sensitive cryptographic keyinformation, which is stored in a protected format to preventunauthorized access. Typically, a key stored in this type of entry is asecret key, or a private key accompanied by the certificate chain for thecorresponding public key. The keytool and jarsigner tools only handle thelater type of entry, that is private keys and their associated certificatechains.

trusted certificate entries: each entry contains a single public keycertificate belonging to another party. It is called a trusted certificatebecause the keystore owner trusts that the public key in the certificateindeed belongs to the identity identified by the subject (owner) of thecertificate. The issuer of the certificate vouches for this, by signing thecertificate.

Listing the src/main/org/jboss/chap8/chap8.keystore examples file contents using thekeytool shows one self-signed certificate:

[nr@toki examples]$ keytool -list -v -keystore src/main/org/jboss/chap8/chap8.keystoreEnter keystore password: rmi+ssl

Keystore type: jksKeystore provider: SUN

Your keystore contains 1 entry

Alias name: rmi+sslCreation date: Nov 8, 2001Entry type: keyEntryCertificate chain length: 1Certificate[1]:Owner: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C=USIssuer: CN=Chapter8 SSL Example, OU=JBoss Book, O="JBoss Group, LLC", L=Issaquah, ST=WA, C=USSerial number: 3beb5271Valid from: Thu Nov 08 21:50:09 CST 2001 until: Sun Nov 06 21:50:09 CST 2011Certificate fingerprints:MD5: F6:1B:2B:E9:A5:23:E7:22:B2:18:6F:3F:9F:E7:38:AESHA1: 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 JBossserver, your are ready to configure JBoss to use SSL for EJB access. This is doneby configuring the EJB invoker RMI socket factories. The JBossSX frameworkincludes implementations ofthe java.rmi.server.RMIServerSocketFactory and java.rmi.server.RMIClientSocketFactory interfacesthat enable the use of RMI over SSL encrypted sockets. The implementationclassesareorg.jboss.security.ssl.RMISSLServerSocketFactory and org.jboss.security.ssl.RMISSLClientSocketFactory respectively. There are two steps to enable the use of SSL for RMI access toEJBs. The first is to enable the use of a keystore as the database for the SSLserver certificate, which is done by configuringan org.jboss.security.plugins.JaasSecurityDomain MBean. The jboss-service.xml descriptor inthe chap8/ex4 directory includes the JaasSecurityDomain definition shownin 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 thatadds the notions of a keystore as wellJSSE KeyManagerFactory and TrustManagerFactory access. It extends the basic securitymanager to allow support for SSL and other cryptographic operations thatrequire security keys. This configuration simply loads the chap8.keystore fromthe example 4 MBean sar using the indicated password.

The second step is to define an EJB invoker configuration that uses the JBossSXRMI socket factories that support SSL. To do this you need to define a customconfiguration for the JRMPInvoker we saw in Chapter 5, EJBs on JBoss as well asan 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 youin Example 8.24, “The jboss-service.xml configurations to enable SSL with theexample 4 stateless session bean.” andExample 8.25, “The jboss.xmlconfiguration to enable SSL with the example 4 stateless session bean.” Thetop of the listing shows the jboss-service.xml descriptor that defines thecustom JRMPInovker, and the bottom shows the example 4 EchoBean4configurationneeded to use the SSL invoker. You will use this configuration in a statelesssession bean example.

Example 8.24. The jboss-service.xml configurations to enable SSL with theexample 4 stateless session bean.

<mbean code="org.jboss.invocation.jrmp.server.JRMPInvokername="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 sessionbean.<?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 ofthe book examples. This is another simple stateless session bean with an echomethod that returns its input argument. It is hard to tell when SSL is in useunless 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 JBossserver 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 ofthe example. Note that the exception stack trace has been edited to fit intothe book format, so expect some difference. The key item to notice about theexception is it clearly shows you are using the Sun JSSE classes tocommunicate with the JBoss EJB container. The exception is saying that theself-signed certificate you are using as the JBoss server certificate cannot bevalidated as signed by any of the default certificate authorities. This isexpected because the default certificate authority keystore that ships with theJSSE package only includes well known certificate authorities such as VeriSign,Thawte, and RSA Data Security. To get the EJB client to accept your self-signedcertificate as valid, you need to tell the JSSE classes to use your chap8.keystore asits truststore. A truststore is just a keystore that contains public keycertificates 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 usingthe 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.RMISSLClientSocketFactory - 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 SSLhandshakeCompleted message. This is coming from the RMISSLClientSocketFactory class asa debug level log message. If you did not have the client configured to printout log4j debug level messages, there would be no direct indication that SSLwas 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 ofcryptographically strong random numbers that take time to seed the first timethey 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 slowerthan the one used to run the examples for the book, such as when runningexample 4b, you may seen an exception similar to the following:

javax.naming.NameNotFoundException: EchoBean4 not boundat sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServerat sun.rmi.transport.StreamRemoteCall.executeCallat sun.rmi.server.UnicastRef.invokeat org.jnp.server.NamingServer_Stub.lookupat org.jnp.interfaces.NamingContext.lookupat org.jnp.interfaces.NamingContext.lookupat javax.naming.InitialContext.lookupat org.jboss.chap8.ex4.ExClient.main(ExClient.java:29)

The problem is that the JBoss server has not finished deploying the exampleEJB in the time the client allowed. This is due to the initial setup time of thesecure random number generator used by the SSL server socket. If you seethis issue, simply rerun the example again or increase the deployment waittime 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 thissection we list the services that open ports that might need to be configuredto work when accessing JBoss behind a firewall. The following table shows theports, socket type, associated service for the services in the defaultconfiguration 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 existin 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 ofthe port or bind interface.

[b] This service binds to an anonymous UDP port and does not support configuration ofthe 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 theother cannot be set.

8.9. How to Secure the JBoss Server

JBoss comes with several admin access points that need to be secured orremoved 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 theJMX microkernel. As such, it provides access to arbitrary admin type accesslike shutting down the server, stopping services, deploying new services, etc. Itshould 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 webapplication view into the JMX microkernel. This uses a combination of anapplet and a HTML view and provides the same level of access to adminfunctionality as the jmx-console.war. As such, it should either be secured orremoved. The web-console.war contains commented out templates for basicsecurity in its WEB-INF/web.xml as well as commented out setup for a securitydomain 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 providesRMI/HTTP access for EJBs and the JNDI Naming service. This includes a servletthat processes posts of marshalled org.jboss.invocation.Invocation objects thatrepresent invocations that should be dispatched onto the MBeanServer.Effectively this allows access to MBeans that support the detached invokeroperation via HTTP since one could figure out how to format an approriateHTTP post. To security this access point you would need to securethe JMXInvokerServlet servlet found in the http-invoker.sar/invoker.war/WEB-INF/web.xml descriptor. There is a secure mapping defined forthe /restricted/JMXInvokerServlet path by default, one would simply have to removethe 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 MBeanServerinterface via an RMI compatible interface using the RMI/JRMP detachedinvoker service. The only way for this service to be secured currently would beto switch the protocol to RMI/HTTP and secure the http-invoker.sar as describedin the previous section. In the future this service will be deployed as anXMBean with a security interceptor that supports role based access checks. Ifyour so inclined this is a configuration that can setup today following theproceedure 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 ConsoleThe jmx-console is the default console that is available with the JBoss Application Server. Itdisplays the various MBean Services that are running in a JBoss Application Server instance. Auser is able to get and set attributes and invoke operations on the various services. For moreinformation, please refer to the 'JBoss Application Server User or Administrator's Guide'. Thefollowing 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 ConsoleIf you want to have simple secured jmx console where the user/password and user/roles comefrom properties files, then you can follow the following steps:

1. Locate the jmx-console.war directory in the deploy directory of your serverconfiguration. If you are just using the default configuration, then it will be underJBOSS_DIR/server/default/deploy directory and you are using the clusteredconfiguration, 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 uncommentthe security constraint block as shown below:

<!-- A security constraint that restricts access to the HTML JMX consoleto users with the role JBossAdmin. Edit the roles to what you want anduncomment the WEB-INF/jboss-web.xml/security-domain element to enablesecured 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 therole 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 shownbelow:

<jboss-web>JBoss 1.0 1<!-- Uncomment the security-domain to enable security. You willneed to edit the htmladaptor login configuration to setup thelogin 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 configurationunder the props sub-directory('default', 'all' or 'custom'). An example of the location willbe /server/default/conf/props.

3. In the jmx-console-users.properties, you can add/change the user/passwordcombination.

4. In the jmx-console-roles.properties, you will need to assign roles to the users you addedor 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 upappear that will ask you to enter the username and password. You can use one of theusers/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 ConsoleThe previous chapter talked about securing the jmx console. The security provided there appliedto the entire consolewith no controls on what an user can do with reference to the various JMX operations possibleon the console.

2.2. DetailsYou 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 areusing (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 thejmx console(action will invoke operations), then the user needs to have 'InvokeOpRole'. If the user isallowed to click the'Apply Changes' button(action will update the jmx attributes of the service), then the user needsto have 'updateAttributeRole'.For this to apply, you will need to update the jmx-console-roles.properties file. An example isshown below:# A sample roles.properties file for use with the UsersRolesLoginModuleadmin=JBossAdmin,HttpInvoker,UpdateAttributeRole

439 | P a g e

JBoss 1.0 3admin2=JBossAdmin,HttpInvoker,InvokeOpRole

2.3. Referencehttp://wiki.jboss.org/wiki/Wiki.jsp?page=AccessControlForJMXConsoleSecure JMX Console (Access Control)JBoss 1.0 4

Secure the JMX Invokers (Authentication Only)

3.1. IntroductionThe JMX invokers are the entry points to the MBean Server. If there is a need to restrict externalaccess to theMBean Server, then there is a need to secure the invokers.

3.2. Enable Authentication for the JMX InvokerThe JMX invoker can be made to authenticate against the JBoss Security JAAS framework likethe web or ejb layers.

3.2.1. Modifications RequiredYou will need to edit the jmx-invoker-service.xml file under the deploy directory of your serverconfiguration (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 canresuse the security domainused to restrict access to the jmx-console.

3.2.2. TroubleshootingWhen 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 5This is due to a change in how the jmx descriptor names are stored with case preserved. To workaround this isssuesimply 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. IntroductionIn the last chapter, you enabled authentication on the JMX invoker. This would basically restrictaccess to just theactors that have identified themselves. There may need for fine-grained access control on theJMX invoker. Youmay want to restrict access to users who have certain roles.

4.2. Enable Access Control or Authorization for the JMX InvokerThe 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 serverconfiguration (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 bythe 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 7You will need to edit the jmx-invoker-service.xml file under the deploy directory of your serverconfiguration (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 togain access. Theprevious 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" ina jar file or place

442 | P a g e

Integrate security infrastructures with JBossSX

JBossSX uses JAAS to integrate application servers and security infrastructures

SummaryThe current Enterprise JavaBean and Servlet specifications omit integration between the applicationserver and existing security infrastructures. This article describes how version 3.2.x of the open sourceJBoss application server security extension project (JBossSX) uses Java Authentication and AuthorizationService (JAAS) login modules as its integration API. JAAS allows for integration without programming,using security infrastructures that use Java Database Connectivity, the lightweight directory accessprotocol (LDAP), or properties-based login modules bundled with JBoss. For security infrastructures thatdo 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 simpledeclarative 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 theapplication security roles from the deployment environment's security implementation. At the applicationlevel, the ejb-jar.xml and web.xml deployment descriptors define security. Although this model allows foran independent, simple specification of the application server's security requirements, mapping theapplication-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. Onesuch tool is the Java Authentication and Authorization Service (JAAS). In this article, I describe how theJBoss security extension, JBossSX, uses the standard JAAS to integrate with the deployment environment'ssecurity infrastructure. By configuring the JAAS login modules bundled with JBoss, you can complete theintegration without custom programming. If the bundled login modules don't work with your securityinfrastructure, 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 modeland 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 thestandard J2EE deployment descriptors. You secure access to EJBs and Web components in an enterpriseapplication by using the ejb-jar.xml and web.xml deployment descriptors. Figures 1 and 2 illustrate thesecurity-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 anenterprise 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 thesecurity 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 EJBcan access the caller principal and ask if the caller belongs to a role by name. The caller principal isobtained from theEJBContext.getCallerPrincipal() method as a java.security.Principal instance. Usingthe EJBContext.isCallerInRole(String) method, an EJB checks if a caller is in a role that has been declaredwith a security-role-ref element. The role-name element value must link to a security role in theassembly-descriptor section of ejb-jar.xml through the role-link element. You typicallyuse isCallerInRole() to perform a security check that cannot be defined using method permissions. Seesection 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 EJB2.0 is the ability to specify what identity an EJB should use when it invokes methods on other EJBs. Theapplication assembler uses the security-identity element to indicate that the current caller's identityshould be propagated by using a use-caller-identity element as security-identity's value. Alternatively, theapplication assembler can use the run-as element with thesecurity-identity's value as role-name to specifythat EJB calls are performed with the security role given by the role-name value. Note that this does notchange the caller's identity as seen by EJBContext.getCallerPrincipal(). Rather, the caller's security rolesare set to the single role specified by the run-as/role-name element value. You can use a run-as identity tokeep external clients from accessing internal EJBs. To do that, assign the internal EJB method permissionsthat 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 oneof the application's declared roles. An application assembler defines logical security roles byadding security-role elements to theassembly-descriptor element. In JBoss, a security-role is only used tomap an EJB security-role-ref/role-name to the logical role to which the EJB role name refers. The user'sassigned roles are a dynamic function of the application's security manager, as you will see when I discussthe JBossSX implementation. JBoss does not require defined security-roles to identify methodpermissions. 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 componentinterface methods through method-permission elements. Each method-permission element contains oneor more role-name elements that define the logical roles allowed access to one or more EJB methods asidentified by method elements. With EJB 2.0, you can now specify the unchecked element instead ofthe role-name element to declare that an authenticated user can access one or more methods. Inaddition, you can declare that no one should have access to a method with the exclude-list element. Formethod 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 usedin 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 thisdeployment</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 identifiesthe protected content. For example, the web.xml descriptor fragment below indicates that any URL lyingunder 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 JBossThe 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 rolesfrom the application domain onto the deployment environment. The EJB specification omits these

application-server-specific details. In JBoss, mapping the application roles onto the deploymentenvironment entails specifying a security manager that implements the J2EE security model. Figure 3shows 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 thesecurity manager interface implementation that JBoss uses for the EJB and Web containers. You mayspecify 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-requestsecurity checks outside the scope of the EJB declarative security model without embedding security logicinto the EJB implementation. I won't go into detail about that JBoss-specific feature, as this article focuseson using JAAS to implement the standard declarative security model.

A JBoss security manager implementation requiresthe org.jboss.security.EJBSecurityManager and org.jboss.security.RealmMapping interfaces presented inFigure 4.

Figure 4. JBoss security manager interfaces

For the remainder of this article, I focus on the JBossSX org.jboss.security.plugins.JaasSecurityManager, aJAAS-based implementation of the security manager interfaces. But first, I'll present a brief introductionto 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. Itimplements a Java version of the standard Pluggable Authentication Module (PAM) framework andcompatibly 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 comprehensiveoverview, see the JAAS material in Resources. I took much of this section's material from the JAAS 1.0Developers Guide.

JAAS authentication is performed in a pluggable fashion. This permits Java applications to remainindependent from underlying authentication technologies and allows the JBossSX security manager towork in different security infrastructures. Integration with a security infrastructure can succeed withoutchanging 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 andpassword 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. Thelist below presents the common and authentication classes, since the JBossSX functionality covered in thisarticle 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 JAASframework defines the term Subject to represent the request's source. Subject is the key JAAS class; itrepresents information for a single entity, such as a person or service. It encompasses the entity'sprincipals, public credentials, and private credentials. The JAAS APIs use the existing Java2 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 havemany Principals. For example, a person may have a name Principal (John Doe) and a social securitynumber Principal (123-45-6789), both of which help distinguish it from other Subjects. To retrievethe 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 returnsthose Principals that are instances of Class c or Class c's subclasses. An empty set will return ifthe Subject has no associated Principals. Note that the java.security.acl.Group interface is a subinterfaceof java.security.Principal, and so an instance in the Principals set may represent a logical grouping of otherprincipals 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 andcredentials 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 todevelop 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 anapplication without changing the application itself.

All LoginContext constructors share a common parameter: name. The LoginContext uses name to indexthe 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 performauthentication. If authentication succeeds, the following method can retrieve theauthenticated 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 usingthe LoginModules configured under the name jwdomain:

// let the LoginContext instantiate a new SubjectLoginContext lc = new LoginContext("jwdomain");try{

// authenticate the Subjectlc.login();System.out.println("authentication successful");

// get the authenticated SubjectSubject subject = lc.getSubject();

...

// all finished -- logoutlc.logout();

}catch (LoginException le){

System.out.println("authentication unsuccessful");le.printStackTrace();

}

With the LoginModule interface, developers can implement different authentication technologies thatcan 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 orbiometric authenticators. To instantiate a LoginModule, a LoginContext expects each LoginModule toprovide a public constructor that takes no arguments. Then, to initialize aLoginModule with the relevantinformation, a LoginContext calls the LoginModule's initialize() method. The subject argument isguaranteed 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 thenverify the information against data stored in a naming service such as NIS or LDAP. Alternativeimplementations might interface to smart cards and biometric devices or simply extract user informationfrom the underlying operating system. The validation of user identity by each LoginModule is consideredPhase 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() throwsLoginException; 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 thecommit operation. Credentials should be destroyed upon removal.

When a LoginModule must communicate with the user to obtain authentication information, it usesa 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 togather input from users (such as a password or smart-card PIN number) and to supply information tousers (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 solicituser input. On the other hand, a CallbackHandler's implementation for a non-GUI environment, such as anapplication 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 featuresseveral implementations, including NameCallback and PasswordCallback. LoginModules use a Callback torequest information required by the authentication mechanism the LoginModule encapsulates.

LoginModules pass an array of Callbacks directly to the CallbackHandler's handle method during theauthentication'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 theJBoss security components interact. Figure 5 shows the main components and how the security domainassigned 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 thesecurity domain jwdomain. The EJB and Web containers have a request interceptor architecture thatincludes a security interceptor, which enforces the container security model. At deployment time, thesecurity domain in the jboss.xml and jboss-web.xml descriptors is used to obtain the security managerinstance associated with the container and used by the security interceptor. When a secured componentis requested, the security interceptor delegates security checks to the security manager instanceassociated with the container.

458 | P a g e

For the JBossSX default security manager implementation, shown in Figure 5 asthe JaasSecurityMgr component, security checks are based on the information associated withthe javax.security.auth.Subject instance. That instance results from executing the JAAS login modulesconfigured under the name matching the security-domain element value. We will drill intothe JaasSecurityManager implementation and its use of JAAS in the following sections.

The JAAS in JaasSecurityManager

The default JBossSX security managerimplementation org.jboss.security.plugins.JaasSecurityManager uses the JAAS packages to implement itsbehavior. 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 hasbeen 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 simplyby 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 forsecurity. Figure 6 illustrates some components involved in the security check; the security check's keysteps 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 forauthentication, which is how clients establish their login identities in JBoss. Support forpresenting the login information via the JNDIInitialContext properties is not provided. A JAASlogin entails creating a javax.security.auth.login.LoginContext instance and passing theconfiguration's name to use. In Figure 6, the configuration name is other. This one-time loginassociates the login principal and credentials with all subsequent EJB method invocations. Notethat the process might not authenticate the user. The nature of the client-side login depends onthe login module configuration that the client uses. In Figure 6, the other client-side loginconfiguration entry is set up to usethe ClientLoginModule (org.jboss.security.ClientLoginModule); that module does not performclient-side authentication, but simply binds the username and password to the JBoss EJBinvocation 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 ahome interface method invocation sent to the JBoss server. The invocation includes the methodarguments passed by the client along with the user identity and credentials from the client-sideJAAS 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 issecured determines the choice of login modules. The security domain's name is used as the loginconfiguration 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 thatcontains 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 objectsare used to represent the role names; SimplePrincipalis a simple string-basedimplementation of Principal. These roles are used to validate the roles assigned tomethods in ejb-jar.xml and the EJBContext.isCallerInRole(String) method.

o An optional java.security.acl.Group named CallerPrincipal, which contains asingle org.jboss.security.SimplePrincipal that corresponds to the identity of theapplication domain's caller. The CallerPrincipal sole group member is the value returnedby the EJBContext.getCallerPrincipal() method. The purpose of this mapping is to allowa Principal known in the deployment security environment to map to a Principal with aname known to the application. In the absence of a CallerPrincipal mapping thedeployment security environment, Principal returns.

4. The final step of the security check is to verify the authenticated user has permission to invokethe 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 thecaller principal has one of the assigned role names. The method iterates through therole names and checks if the user javax.security.auth.Subject's Roles group containsa SimplePrincipal with the assigned role name. Access is allowed if any role name is amember 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 isdelegated to it. If the security proxy wants to deny access to the caller, it will throwa SecurityException. If no SecurityException is thrown, access to the EJB method isallowed; the SecurityInterceptor passes the method invocation to the next containerinterceptor.

Note that you can configure the JaasSecurityManager to use a cache of authentication information so thata JAAS login is not performed on every method invocation. If no cache is specified inthe 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 forauthentication and authorization. The security manager authorizes users with the information stored inthe Subject. If theLoginModules that ship with the JBoss server do not integrate into your existing securityinfrastructure, you can write a custom LoginModule that does. Writing a custom login module entailsmapping your security infrastructure information onto a javax.security.auth.Subject using the usagepattern 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 asecurity domain. Since these modules run inside the JBoss server, they are called server-side loginmodules. When you write a custom LoginModule, you write a server-side login module. To understandhow server-side login modules are used in JBoss, you need to understand the JAAS Subject class'sinformation 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 obtainedvia getPrincipals() and getPrincipals(java.lang.Class). The usage pattern follows:

User identities (username, social security number, employee ID, and so on) are storedas java.security.Principal objects in the Subject Principals set. The assigned user roles are also stored inthe Principals set, but in named role sets usingjava.security.acl.Group instances. The Group interface -- acollection of Principals and/or Groups -- is a subinterface of java.security.Principal. Any number of rolesets can be assigned to a Subject. Currently, the JBossSX framework uses two well-known rolesets: Roles and CallerPrincipal. The Roles set is the Principal set for the named roles as known in theapplication domain under which the Subject has been authenticated. This role set is used by methods liketheEJBContext.isCallerInRole(String), which EJBs use to see if the current caller belongs to the namedapplication domain role. The security interceptor logic that performs method permission checks also usesthe role set. The CallerPrincipal role set consists of the single Principal identity assigned to the user in theapplication domain. The EJBContext.getCallerPrincipal() method uses CallerPrincipal to allow theapplication domain to map from the operation environment identity to a user identity suitable for theapplication. If a Subject does not have a CallerPrincipal role set, the application identity is the operationalenvironment 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 atemplate pattern. Theorg.jboss.security.auth.spi.AbstractLoginModule class provides concreteimplementations of the javax.security.auth.spi.LoginModule interface and offers abstract methods for thekey 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 JAASserver-side LoginModule and implements the JBossSX standard Subject usagepattern of storing identities and roles. Subclass this module to create yourown 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 overrideif 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 thejavax.security.auth.login.name value of the sharedState map, andthe proof of identity from the javax.security.auth.login.passwordvalue 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.passwordvalues in the sharedState map if the useFirstPass option was true and returnstrue 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 tothe 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 atleast a Group named "Roles" that contains the roles assigned to the user.A second common group is "CallerPrincipal," which provides the applicationidentity 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 loginmodule implementation by using the string-based username as the user identity and the char[] passwordas the authentication credential. It also maps anonymous users (indicated by a null username andpassword) to a Principal. You would typically support anonymous users by settingthe 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 aan identity == String username, credentials == String password view onthe login process. Subclasses override the getUsersPassword()and getUsersRoles() methods to return the expected password and rolesfor the user.*/

public abstract class UsernamePasswordLoginModuleextends 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 unauthenticatedIdentityproperty. This method first invokes the super version.@param options,@option unauthenticatedIdentity: the name of the principal to assignand 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 inputpassword against the expected password. This version checks thatneither inputPassword or expectedPassword are null and thatinputPassword.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 viathe getUsername() method. This is called from within the login()method after the CallbackHandler has returned the username andcandidate 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 bysubclassing org.jboss.security.auth.spi.AbstractLoginModule or one of its subclasses to ensure that yourlogin module provides the authenticated Principal information in the form expected by the JBossSXsecurity 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 fromwithin 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 tothe 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 articlearchive in the jw-0831-jaas/example directory and I'll walk you through it. You will set up and deploy theexample to a JBoss/Tomcat 3.2.1 bundle. You'll also look at the application from the secure andunsecured servlet accessing a secured EJB to demonstrate many of the security features presented in thisarticle. 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 createa 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 theexamples root directory. The default location is /tmp/jboss-3.2.3, so if you unarchive theJBoss/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 outputshould look something like this:

[starksm@dedicated74 example]$ antBuildfile: 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 SUCCESSFULTotal time: 4 secondsTotal time: 2 seconds

If you see something similar to this:

[starksm@banshee example]$ antBuildfile: 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 distdirectory

you need to correct the jboss.dist property's value in the Ant build.xml file in the exampledirectory as indicated in the previous step.

<>Now start the JBoss server with the jaas_howto configuration, which contains the JAAS loginconfiguration 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 operatingsystem, passing in the jaas_howto config name. Here's an example from a Linux system with keyoutput 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_3date=200311301445)23:19:41,850 INFO [Server] Home Dir: /tmp/jboss-3.2.323: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: null23:19:41,852 INFO [Server] Server Name: jaas_howto23:19:41,852 INFO [Server] Server Home Dir: /tmp/jboss-3.2.3/server/jaas_howto23: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/data23:19:41,853 INFO [Server] Server Temp Dir: /tmp/jboss-3.2.3/server/jaas_howto/tmp23: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,SunMicrosystems Inc.23:19:42,276 INFO [ServerInfo] OS-System: Linux 2.4.20-9smp,i38623:19:42,323 INFO [ServiceController] Controller MBean online23: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.ear23:20:00,704 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial1.ear23:20:01,478 INFO [EjbModule] Deploying PublicSession23:20:01,579 INFO [JaasSecurityManagerService] CreatedsecurityMgr=org.jboss.security.plugins.JaasSecurityManager@49034223:20:01,580 INFO [JaasSecurityManagerService] setCachePolicy,c=org.jboss.util.TimedCachePolicy@1751a9e23:20:01,581 INFO [JaasSecurityManagerService] Added example1,org.jboss.security.plugins.SecurityDomainContext@126ba64 to map23:20:01,688 INFO [EjbModule] Deploying PrivateSession23:20:01,934 INFO [StatelessSessionInstancePool] Startedjboss.j2ee:jndiName=example1/PublicSession,plugin=pool,service=EJB23:20:01,935 INFO [StatelessSessionContainer] Startedjboss.j2ee:jndiName=example1/PublicSession,service=EJB23:20:01,945 INFO [StatefulSessionInstancePool] Startedjboss.j2ee:jndiName=example1/PrivateSession,plugin=pool,service=EJB23:20:01,945 INFO [StatefulSessionFilePersistenceManager] Started null23:20:01,945 INFO [StatefulSessionContainer] Startedjboss.j2ee:jndiName=example1/PrivateSession,service=EJB23:20:01,946 INFO [EjbModule] Started jboss.j2ee:module=ssbean1.jar,service=EjbModule23:20:01,946 INFO [EJBDeployer] Deployed: file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29859tutorial1.ear-contents/ssbean1.jar23: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 Valve23:20:02,476 INFO [Engine] SingleSignOnContextConfig[/jaas-example1]: Configured anauthenticator for method BASIC23:20:02,502 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on classloader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@a937cd23:20:02,502 INFO [Engine] StandardManager[/jaas-example1]: Seeding random numbergenerator class java.security.SecureRandom

469 | P a g e

23:20:02,503 INFO [Engine] StandardManager[/jaas-example1]: Seeding of random numbergenerator has been completed23:20:02,504 INFO [Engine] StandardWrapper[/jaas-example1:default]: Loading containerservlet default23:20:02,505 INFO [Engine] StandardWrapper[/jaas-example1:invoker]: Loading containerservlet invoker23:20:03,020 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial1.ear23:20:03,020 INFO [MainDeployer] Deployed package: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial1.ear23:20:03,021 INFO [MainDeployer] Starting deployment of package: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial2.ear23:20:03,022 INFO [EARDeployer] Init J2EE application: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial2.ear23:20:03,387 INFO [EjbModule] Deploying PublicSession23:20:03,408 INFO [JaasSecurityManagerService] CreatedsecurityMgr=org.jboss.security.plugins.JaasSecurityManager@a6d3523:20:03,409 INFO [JaasSecurityManagerService] setCachePolicy,c=org.jboss.util.TimedCachePolicy@87d47223:20:03,409 INFO [JaasSecurityManagerService] Added example2,org.jboss.security.plugins.SecurityDomainContext@18ca663 to map23:20:03,413 INFO [EjbModule] Deploying PrivateSession23:20:03,449 INFO [StatelessSessionInstancePool] Startedjboss.j2ee:jndiName=example2/PublicSession,plugin=pool,service=EJB23:20:03,449 INFO [StatelessSessionContainer] Startedjboss.j2ee:jndiName=example2/PublicSession,service=EJB23:20:03,461 INFO [StatefulSessionInstancePool] Startedjboss.j2ee:jndiName=example2/PrivateSession,plugin=pool,service=EJB23:20:03,462 INFO [StatefulSessionFilePersistenceManager] Started null23:20:03,462 INFO [StatefulSessionContainer] Startedjboss.j2ee:jndiName=example2/PrivateSession,service=EJB23:20:03,462 INFO [EjbModule] Started jboss.j2ee:module=ssbean2.jar,service=EjbModule23:20:03,463 INFO [EJBDeployer] Deployed: file:/tmp/jboss-3.2.3/server/jaas_howto/tmp/deploy/tmp29860tutorial2.ear-contents/ssbean2.jar23: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 Valve23:20:04,011 INFO [Engine] SingleSignOnContextConfig[/jaas-example2]: Configured anauthenticator for method BASIC23:20:04,034 WARN [EmbeddedTomcatService] Unable to invoke setDelegate on classloader:org.jboss.web.tomcat.tc4.WebCtxLoader$ENCLoader@2264da23:20:04,034 INFO [Engine] StandardManager[/jaas-example2]: Seeding random number

470 | P a g e

generator class java.security.SecureRandom23:20:04,035 INFO [Engine] StandardManager[/jaas-example2]: Seeding of random numbergenerator has been completed23:20:04,037 INFO [Engine] StandardWrapper[/jaas-example2:default]: Loading containerservlet default23:20:04,038 INFO [Engine] StandardWrapper[/jaas-example2:invoker]: Loading containerservlet invoker23:20:04,520 INFO [EARDeployer] Started J2EE application: file:/tmp/jboss-3.2.3/server/jaas_howto/deploy/tutorial2.ear23: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_3date=200311301445)] Started in 22s:945ms

The tutorial1.ear contents

tutorial1.ear consists of a single Webpage, a secured servlet, an unsecured servlet, and two securedstateless session beans. As the servlet and session bean code is trivial, I'll leave its inspection as anexercise for you. The interesting aspect of the example is the deployment descriptors' security-relatedelements and the configuration of the JAAS login module associated with the securitydomain. 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 securityrequirements:

<?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 thisdeployment</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 queriesthe EJBContext.isCallerInRole with a EchoUser role name string.

The security-identity/run-as/role-name InternalUser declaration indicates that a principal with arole named InternalUser handles any EJB calls made by the PublicSession bean.

The PrivateSession bean declares an InternalUser role name to indicate that the bean queriesthe EJBContext.isCallerInRole with an InternalUser role name string.

In the assembly-descriptor section, logical roles of Echo, Coder, and InternalUser are declaredusing security-role elements.

The Echo role receives permission to access any method in the PublicSession bean in thefirst method-permission element.

The InternalUser role receives permission to access any PrivateSession bean method in thesecond method-permission element.

The fourth method-permission element indicates that any authenticated user can callthe 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 descriptorThe 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 securesall EJBs in the ssbean1.jar. The JNDI name's final component (example1) determines which login modulesare 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 theJBossSX framework uses the roles.properties and users.properties files. This simple login module uses Javaproperties 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 theformat username[.RoleGroup]=role1_name[,role2_name,...]. A RoleGroup names the Group that will becreated to hold given roles. With no specified RoleGroup, it defaults to Roles. Here'sthe roles.properties file for the example:

# roles.propertiesjava=Echoduke=Java,Coderjava.CallerPrincipal=caller_javaduke.CallerPrincipal=caller_duke

The code above maps the username java to the role name Echo under the Roles RoleGroup, and the rolename caller_java under the CallerPrincipal RoleGroup. The users.properties file maps a username to auser password. Here's theusers.properties file for the example:

# users.propertiesjava=echomanduke=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 andsecurity 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 theidentity 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 /restrictedcontext 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 thatall 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 accessthe content under /restricted.

The login-config/auth-method element with the BASIC value indicates that BASICHTTP authorization will authenticate users attempting to access content under /restricted.

The SecureServlet requires authenticated access, since its servlet-mapping/url-pattern element isunder the /restricted path.

The JaasLoginFilter servlet filter does a JAAS login to establish the caller identity given the thefilter's username/passowrd init-param values using the JAAS login module configuration namedby the configName init-param.

The tutorial1.ear/tutorial1.war/WEB-INF/jboss-web.xml descriptorHere 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 handlessecurity for all secured Web content. Since the security-domain element matches that used bythe 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 serverconfiguration directory is the JAAS login configuration file. That file consists of named login configurationentries. 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 asmbeans 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 LoginModuleLoginModule options:

dsJndiName: The name of the DataSource of the database containing the Principals, Roles tablesprincipalsQuery: 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 nameis org.jboss.security.auth.spi.UsersRolesLoginModule, which is required for successfulauthentication. The UsersRolesLoginModule login module uses the users.properties androles.properties files included in the ear as discussed earlier. The example2 entry contains asingle 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 databaseto 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 connectionpools.

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 thesame host as the JBoss server, launch your Web browser and open the Web application index.html filelocated 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 specifiedsecurity. 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 invocationlists 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 thepassword 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/SecureServlet16:09:15,441 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint[Restricted]' against GET /restricted/SecureServlet --> true16: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() test16:09:20,108 INFO [Engine] Authenticator[/jaas-example1]: Security checking request GET /jaas-example1/restricted/SecureServlet16:09:20,128 INFO [Engine] Authenticator[/jaas-example1]: Checking constraint 'SecurityConstraint[Restricted]' against GET /restricted/SecureServlet --> true16: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 restrictions16: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 constraints16:09:20,268 INFO [Engine] StandardContext[/jaas-example1]: Mapping contextPath='/jaas-example1' with requestURI='/jaas-example1/restricted/SecureServlet' and relativeURI='/restricted/SecureServlet'16:09:20,288 INFO [Engine] StandardContext[/jaas-example1]: Trying exact match16:09:20,298 INFO [Engine] StandardContext[/jaas-example1]: Mapped to servlet 'SecureServlet' withservlet path '/restricted/SecureServlet' and path info 'null' and update=true16:09:20,398 INFO [STDOUT] PublicSessionBean.ejbCreate() called16:09:20,408 INFO [STDOUT] PublicSessionBean.echo, arg=Hello16:09:20,418 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java16:09:20,428 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true16:09:20,438 INFO [STDOUT] PrivateSessionBean.ejbCreate() called16:09:20,448 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession16:09:20,458 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello16:09:20,468 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java16:09:20,478 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false

The first Failed authenticate() test. line results because Tomcat tried to determine whether the servletrequest had a remote user associated with it. That caused a query to the security manager with a nullusername and password, because the browser was not asked to provide any login information. The nullusername and password is rejected and this results in a 401 error which causes the browser to display thebasic auth login dialog. The following Authenticated 'java' with type 'BASIC' line is the result of the HTTPBASIC authorization login.

Note that PrivateSessionBean.echo() method's check to see if the caller has the InternalUser role returnsfalse. This seemingly incorrect result is in accord with our interpretation of the EJB 2.0 spec, which stateson page 439:

Note that isCallerInRole(String roleName) tests the principal that represents the caller of the enterprisebean, 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. Thatshould fail, since only the PublicSession has been configured to run as the InternalUser role. You shouldsee 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, isenforced.

The links under the 'JBoss Unsecured Servlet with JAAS Login filter to EJB Tests' heading are to theUnsecureServletWithLogin mapping of the EJBServlet. These mappings use the JaasLoginFilter to performa JAAS login at that start of the request using a username of java and a password of echoman, and alogout 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 accessthe PublicSession bean.

2. example1-test1 this tests access with a valid username and password with a user who does nothave 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 aPublicSession instance and invokes the echo method on it. Next the SessionClient attempts to create aninstance 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-test0The test example1-test0 accesses the PublicSession bean with a valid username and passwordwith a user with the correct permissions. The expected client side output is shown here:

[starksm@dedicated74 example]$ ant example1-test0Buildfile: 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=Hello23:23:09,120 INFO [STDOUT] PublicSessionBean.ejbCreate() called23:23:09,123 INFO [STDOUT] PublicSessionBean.echo, arg=Hello23:23:09,124 INFO [STDOUT] PublicSessionBean.echo, callerPrincipal=caller_java23:23:09,125 INFO [STDOUT] PublicSessionBean.echo, isCallerInRole('EchoUser')=true23:23:09,131 INFO [STDOUT] PrivateSessionBean.ejbCreate() called23:23:09,134 INFO [STDOUT] PublicSessionBean.echo, created PrivateSession23:23:09,143 INFO [STDOUT] PrivateSessionBean.echo, arg=Hello23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, callerPrincipal=caller_java23:23:09,144 INFO [STDOUT] PrivateSessionBean.echo, isCallerInRole('InternalUser')=false23: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]

atorg.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(CachedConnectionInterceptor.java:214)

atorg.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invokeHome(StatefulSessionInstanceInterceptor.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(ProxyFactoryFinderInterceptor.java:93)

atorg.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 thesecond example, tutorial2.ear, which was created and deployed during the examples build. Thetutorial2.ear example differs from tutorial1.ear only in its choice of security domain name andthus login module configuration. tutorial2.ear uses a Java Database Connectivity-based loginmodule to demonstrate how to access security information from a database. The entry point forthe tutorial2 web application ishttp://localhost:8080/jaas-example2/index.html.

Note 1: Before you can use the tutorial2 web application successfully you must create thepassword and roles database. To do this, run the buildDB ant target with JBoss running thejaas_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 wouldbe locked if JBoss was running. Running the buildDB target should result in:

[starksm@banshee example]$ ant buildDBBuildfile: 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 deploymentenvironment is currently a nonportable, application-server-specific task, this article hasdemonstrated how the standard JAAS security could be used to implement the J2EE declarativesecurity model using a simple Subject-based usage pattern. Hopefully, future versions of J2EE willextend the portability of security closer to the deployment layer using similar techniques basedon JAAS or equivalent standards-based APIs. This article has peered into the JBossSX securitymanager implementation of the J2EE declarative security model used by the JBoss EJB and Webcontainers. It focused on how the JAAS login modules configured for a security domain providethe security information via a Subject usage pattern. I also covered the steps required to create acustom login module for security infrastructures not supported by bundled JBossSX loginmodules. With this information, you can secure your enterprise applications either byconfiguring 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 servermust 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 andCharlie 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, October2000):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 Filessection 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 newon JavaWorld:http://www.idg.net/jw-subscribeYou'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 throughHTTP) 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 HTTPinvokers).

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 mayremove 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 theMBeanServer 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 theconf/login-config.xml definitions the same way as the jboss.xml, jboss-web.xml security-domainelements 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 thefollowing:. This is due to a change in how the jmx descriptor names are stored with case preserved. Towork 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 inJBoss. The interceptor should be placed after the AuthenticationInterceptor and has thefollowing configuration.

authorizingClass : Fully Qualified Name of a class that does the authorization and whichcontains a method with the following signature"public void authorize( Principal caller, Subject subject, String objectname,Stringopname)" that can throw a java.lang.SecurityException

An example of an authorizing class is available in JBoss. It istheorg.jboss.jmx.connector.invoker.RolesAuthorization, which looks for an hardcoded"JBossAdmin" role in the authenticated subject.

<descriptors><interceptors>