SecServerRequestInterceptorpublic class SecServerRequestInterceptor extends org.omg.CORBA.LocalObject implements ServerRequestInterceptorThis class is a server side request interceptor for CSIV2.
It is used to send and receive the service context in a
a service context element in the service context list in
an IIOP header. |
Fields Summary |
---|
private static Logger | _logger | private static com.sun.enterprise.util.LocalStringManagerImpl | localStrings | private InheritableThreadLocal | counterForCalls | protected static final int | SECURITY_ATTRIBUTE_SERVICE_IDHard code the value of 15 for SecurityAttributeService until
it is defined in IOP.idl.
sc.context_id = SecurityAttributeService.value; | private static final int | INVALID_MECHANISM_MAJOR | private static final int | INVALID_MECHANISM_MINOR | private static final boolean | NO_REPLACE | private String | prname | private String | name | private Codec | codec | private ORB | orb | SecurityService | secsvc |
Constructors Summary |
---|
public SecServerRequestInterceptor(String name, Codec codec) // Security Service
this.name = name;
this.codec = codec;
this.prname = name + "::";
|
Methods Summary |
---|
private void | createAuthCred(SecurityContext sc, byte[] authtok)Create an auth credential from authentication token and store
it as a private credential in the JAAS subject in the security
context.
Set the authcls field in the security context.
This method currently only works for PasswordCredential tokens.
_logger.log(Level.FINE,"Constructing a PasswordCredential from client authentication token");
/* create a GSSUPToken from the authentication token */
GSSUPToken tok = GSSUPToken.getServerSideInstance(orb, codec, authtok);
final PasswordCredential pwdcred = tok.getPwdcred();
final SecurityContext fsc = sc;
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,"Password credential = " + pwdcred.toString());
_logger.log(Level.FINE,"Adding PasswordCredential to subject's PrivateCredentials");
}
java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
public java.lang.Object run() {
fsc.subject.getPrivateCredentials().add(pwdcred);
return null;
}
});
sc = fsc;
sc.authcls = PasswordCredential.class;
| private SASContextBody | createCompleteEstablishContext(int status)Create a CompleteEstablishContext Message. This currently works only
for the GSSUP mechanism.
/**
* CSIV2 SPEC NOTE:
*
* Check CSIV2 spec to make sure that there is no
* final_context_token for GSSUP mechanism
*/
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Creating CompleteEstablishContext message");
}
byte[] final_context_token = {} ;
CompleteEstablishContext cec = new CompleteEstablishContext(
0, // stateless client id
false, // for stateless
final_context_token);
SASContextBody sasctxtbody = new SASContextBody();
sasctxtbody.complete_msg(cec);
return sasctxtbody;
| private SASContextBody | createContextError(int status)Create a ContextError message. This is currently designed to work only
for the GSSUP mechanism.
/**
* CSIV2 SPEC NOTE:
*
* Check that CSIV2 spec does not require an error token to be sent
* for the GSSUP mechanism.
*/
return createContextError(1, status);
| private SASContextBody | createContextError(int major, int minor)
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,"Creating ContextError message: major code = "+ major+ "minor code= "+ minor);
}
byte error_token[] = {} ;
ContextError ce = new ContextError(0, /* stateless client id */
major, // major
minor, // minor
error_token);
SASContextBody sasctxtbody = new SASContextBody();
sasctxtbody.error_msg(ce);
return sasctxtbody;
| private void | createIdCred(SecurityContext sc, IdentityToken idtok)Create an identity from an Identity Token and stores it as a
public credential in the JAAS subject in a security context.
Set the identcls field in the security context.
byte[] derenc ; // used to hold DER encodings
Any any; // Any object returned from codec.decode_value()
switch (idtok.discriminator()) {
case ITTAbsent.value:
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Identity token type is Absent");
}
sc.identcls = null;
break;
case ITTAnonymous.value:
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Identity token type is Anonymous");
_logger.log(Level.FINE,"Adding AnonyCredential to subject's PublicCredentials");
}
sc.subject.getPublicCredentials().add(new AnonCredential());
sc.identcls = AnonCredential.class;
break;
case ITTDistinguishedName.value:
/* Construct a X500Name */
derenc = idtok.dn();
/* Issue 5766: Decode CDR encoding if necessary */
if (isCDR(derenc)) {
any = codec.decode_value(derenc, X501DistinguishedNameHelper.type());
/* Extract CDR encoding */
derenc = X501DistinguishedNameHelper.extract(any);
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Create an X500Name object from identity token");
}
X500Name name = new X500Name(derenc);
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,"Identity to be asserted is " + name.toString());
_logger.log(Level.FINE,"Adding X500Name to subject's PublicCredentials");
}
sc.subject.getPublicCredentials().add(name);
sc.identcls = X500Name.class;
break;
case ITTX509CertChain.value:
/* Construct a X509CertificateChain */
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Identity token type is a X509 Certificate Chain");
}
derenc = idtok.certificate_chain();
/* Issue 5766: Decode CDR encoding if necessary */
if (isCDR(derenc)) {
/* Decode CDR encoding */
any = codec.decode_value(derenc, X509CertificateChainHelper.type());
/* Extract DER encoding */
derenc = X509CertificateChainHelper.extract(any);
}
DerInputStream din = new DerInputStream(derenc);
/**
* Size specified for getSequence() is 1 and is just
* used as a guess by the method getSequence().
*/
DerValue[] derval = din.getSequence(1);
X509Certificate[] certchain =
new X509CertImpl[derval.length];
/**
* X509Certificate does not have a constructor which can
* be used to instantiate objects from DER encodings. So
* use X509CertImpl extends X509Cerificate and also implements
* DerEncoder interface.
*/
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Contents of X509 Certificate chain:");
}
for (int i = 0; i < certchain.length; i++) {
certchain[i] = new X509CertImpl(derval[i]);
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE," " + certchain[i].getSubjectDN().getName());
}
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Creating a X509CertificateCredential object from certchain");
}
/**
* The alias field in the X509CertificateCredential is currently ignored
* by the RI. So it is set to "dummy".
*
*/
X509CertificateCredential cred =
new X509CertificateCredential(certchain, certchain[0].getSubjectDN().getName(), "default");
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Adding X509CertificateCredential to subject's PublicCredentials");
}
sc.subject.getPublicCredentials().add(cred);
sc.identcls = X509CertificateCredential.class;
break;
case ITTPrincipalName.value:
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Identity token type is GSS Exported Name");
}
byte[] expname = idtok.principal_name();
/* Issue 5766: Decode CDR encoding if necessary */
if (isCDR(expname)) {
/* Decode CDR encoding */
any = codec.decode_value(expname, GSS_NT_ExportedNameHelper.type());
expname = GSS_NT_ExportedNameHelper.extract(any);
}
if ( ! GSSUtils.verifyMechOID(GSSUtils.GSSUP_MECH_OID, expname)) {
throw new SecurityException(
localStrings.getLocalString("secserverreqinterceptor.err_unknown_idassert_type",
"Unknown identity assertion type."));
}
GSSUPName gssname = new GSSUPName(expname);
sc.subject.getPublicCredentials().add(gssname);
sc.identcls = GSSUPName.class;
_logger.log(Level.FINE,"Adding GSSUPName credential to subject");
break;
default:
_logger.log(Level.SEVERE,"iiop.unknown_identity");
throw new SecurityException(
localStrings.getLocalString("secserverreqinterceptor.err_unknown_idassert_type",
"Unknown identity assertion type."));
}
| private ServiceContext | createSvcContext(SASContextBody sasctxtbody)CDR encode a SAS Context body and then construct a service context
element.
ServiceContext sc = null;
Any a = orb.create_any();
SASContextBodyHelper.insert(a, sasctxtbody);
byte[] cdr_encoded_saselm = {};
try {
cdr_encoded_saselm = codec.encode_value(a);
} catch (Exception e) {
_logger.log(Level.SEVERE,"iiop.encode_exception",e);
}
sc = new ServiceContext();
sc.context_id = SECURITY_ATTRIBUTE_SERVICE_ID;
sc.context_data = cdr_encoded_saselm;
return sc;
| public void | destroy()
| private void | handle_null_service_context(ServerRequestInfo ri, ServiceContext sc)
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"No SAS context element found in service context list");
}
int secStatus = secsvc.setSecurityContext(null, ri.object_id(),
ri.operation());
if (secStatus == SecurityService.STATUS_FAILED){
SASContextBody sasctxbody = createContextError(INVALID_MECHANISM_MAJOR,
INVALID_MECHANISM_MINOR);
sc = createSvcContext(sasctxbody);
ri.add_reply_service_context(sc, NO_REPLACE);
if(_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"SecServerRequestInterceptor.receive_request: NO_PERMISSION");
}
throw new NO_PERMISSION();
}
| private boolean | isCDR(byte[] bytes)Check if given byte is CDR encapsulated.
return (bytes != null && bytes.length > 0 &&
(bytes[0] == 0x0 || bytes[0] == 0x1));
| public java.lang.String | name()
return name;
| public void | receive_request(ServerRequestInfo ri)
SecurityContext seccontext = null; // SecurityContext to be sent
ServiceContext sc = null; // service context
int status = 0;
boolean raise_no_perm = false;
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "++++ Entered " + prname + "receive_request");
}
secsvc = Csiv2Manager.getSecurityService();
orb = ORBManager.getORB();
try {
sc = ri.get_request_service_context(SECURITY_ATTRIBUTE_SERVICE_ID);
if (sc == null) {
handle_null_service_context(ri, sc);
return;
}
} catch (org.omg.CORBA.BAD_PARAM e) {
handle_null_service_context(ri,sc);
return;
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Received a non null SAS context element");
}
/* Decode the service context field */
Any SasAny = orb.create_any();
try {
SasAny = codec.decode_value(sc.context_data, SASContextBodyHelper.type());
} catch (Exception e) {
_logger.log(Level.SEVERE,"iiop.decode_exception",e);
throw new SecurityException(
localStrings.getLocalString("secserverreqinterceptor.err_cdr_decode",
"CDR Decoding error for SAS context element."));
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Successfully decoded CDR encoded SAS context element.");
}
SASContextBody sasctxbody = SASContextBodyHelper.extract(SasAny);
short sasdiscr = sasctxbody.discriminator();
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"SAS context element is a/an " + SvcContextUtils.getMsgname(sasdiscr)+ " message");
}
/* Check message type received */
/**
* CSIV2 SPEC NOTE:
*
* Section 4.3 "TSS State Machine" , table 4-4 "TSS State Table"
* shows that a MessageInContext can be received. In this case
* the table is somewhat unclear. But in this case a ContextError
* with the status code "No Context" ( specified in
* section 4.5 "ContextError Values and Exceptions" must be sent back.
* A NO_PERMISSION exception must also be raised.
*
* ISSUE: should setSecurityContext(null) be called ?
*/
if (sasdiscr == MTMessageInContext.value) {
sasctxbody = createContextError(SvcContextUtils.MessageInContextMinor);
sc = createSvcContext(sasctxbody);
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Adding ContextError message to service context list");
_logger.log(Level.FINE,"SecurityContext set to null");
}
ri.add_reply_service_context(sc, NO_REPLACE);
// no need to set the security context
// secsvc.setSecurityContext(null, ri.object_id(), ri.operation());
throw new NO_PERMISSION();
}
/**
* CSIV2 SPEC NOTE:
*
* CSIV2 spec does not specify the actions for any message other than
* a MessageInContext and EstablishContext message.So for such messages,
* this implementation simply drops the message on the floor. No
* other message is sent back. Neither is an exception raised.
*
* ISSUE: Should there be some other action ?
*/
if (sasdiscr != MTEstablishContext.value) {
_logger.log(Level.SEVERE,"iiop.not_establishcontext_msg");
throw new SecurityException(
localStrings.getLocalString("secserverreqinterceptor.err_not_ec_msg",
"Received message not an EstablishContext message."));
}
EstablishContext ec = sasctxbody.establish_msg();
seccontext = new SecurityContext();
seccontext.subject = new Subject();
try {
if (ec.client_authentication_token.length != 0) {
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Message contains Client Authentication Token");
}
createAuthCred(seccontext, ec.client_authentication_token);
}
} catch (Exception e) {
_logger.log(Level.SEVERE,"iiop.authentication_exception",e);
throw new SecurityException(
localStrings.getLocalString("secsercverreqinterceptor.err_cred_create",
"Error while creating a JAAS subject credential."));
}
try{
if (ec.identity_token != null) {
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Message contains an Identity Token");
}
createIdCred(seccontext, ec.identity_token);
}
} catch (SecurityException secex){
_logger.log(Level.SEVERE,"iiop.security_exception",secex);
sasctxbody = createContextError(INVALID_MECHANISM_MAJOR,
INVALID_MECHANISM_MINOR);
sc = createSvcContext(sasctxbody);
ri.add_reply_service_context(sc, NO_REPLACE);
throw new NO_PERMISSION();
} catch (Exception e) {
_logger.log(Level.SEVERE,"iiop.generic_exception",e);
throw new SecurityException(
localStrings.getLocalString("secsercverreqinterceptor.err_cred_create",
"Error while creating a JAAS subject credential."));
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Invoking setSecurityContext() to set security context");
}
status = secsvc.setSecurityContext(seccontext, ri.object_id(), ri.operation());
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"setSecurityContext() returned status code " + status);
}
/**
* CSIV2 SPEC NOTE:
*
* If ec.client_context_id is non zero, then this is a stateful
* request. As specified in section 4.2.1, a stateless server must
* attempt to validate the security tokens in the security context
* field. If validation succeeds then CompleteEstablishContext message
* is sent back. If validation fails, a ContextError must be sent back.
*/
if (status == SecurityService.STATUS_FAILED) {
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"setSecurityContext() returned STATUS_FAILED");
}
sasctxbody = createContextError(status);
sc = createSvcContext(sasctxbody);
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Adding ContextError message to service context list");
}
ri.add_reply_service_context(sc, NO_REPLACE);
throw new NO_PERMISSION();
}
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"setSecurityContext() returned SUCCESS");
}
sasctxbody = createCompleteEstablishContext(status);
sc = createSvcContext(sasctxbody);
if(_logger.isLoggable(Level.FINE)){
_logger.log(Level.FINE,"Adding CompleteEstablisContext message to service context list");
}
ri.add_reply_service_context(sc, NO_REPLACE);
| public void | receive_request_service_contexts(ServerRequestInfo ri)
// cannot set this in receive_request due to the PI flow control
// semantics. e.g. if receive_req for some other PI throws an
// exception - the send_exception will be called that will muck
// the stack up
Counter cntr = (Counter)counterForCalls.get();
if (cntr == null){
cntr = new Counter();
counterForCalls.set(cntr);
}
if (cntr.count == 0){
SecurityService secsvc = Csiv2Manager.getSecurityService();
secsvc.unsetSecurityContext();
}
cntr.increment();
| public void | send_exception(ServerRequestInfo ri)
unsetSecurityContext();
| public void | send_other(ServerRequestInfo ri)
unsetSecurityContext();
| public void | send_reply(ServerRequestInfo ri)
unsetSecurityContext();
| private void | unsetSecurityContext()
Counter cntr = (Counter)counterForCalls.get();
if (cntr == null){ // sanity check
cntr = new Counter(1);
}
cntr.decrement();
if (cntr.count == 0){
SecurityService secsvc = Csiv2Manager.getSecurityService();
secsvc.unsetSecurityContext();
}
|
|