Discussion:
Clarification on nsHTMLInputElement/ certificates
Anderson Walls
2012-04-18 13:23:18 UTC
Permalink
I am currently working on a research project that requires me to
modify a browser in order to return a website's certificate (to
stdout/ stderr) when the user clicks into a password field.

As of right now I have added the following into the switch statement
(aVisitor.mEvent->message) in the PostHandleEvent method of
nsHTMLElement.

Case NS_FOCUS_CONTENT:{

// start of my addition
if( IsPasswordTextControl() ){
std::cerr << "Entered Password Field" << std::endl;
}

// continue mozilla source

So I now know when ever I have clicked into a password field which is
great but I have been trying for the last few weeks to sift through
the DOM in order to find where I can grab the certificate or determine
that there is not one for the document/tab/frame that the user is
currently in. Im sure there is a method out there that does exactly
this and can be added into the if statement just not sure what it is/
where to find it.

Hopefully this is explained clearly, any assistance would be greatly
appreciated.
Boris Zbarsky
2012-04-18 14:59:23 UTC
Permalink
Post by Anderson Walls
// start of my addition
if( IsPasswordTextControl() ){
std::cerr<< "Entered Password Field"<< std::endl;
}
// continue mozilla source
So I now know when ever I have clicked into a password field which is
great but I have been trying for the last few weeks to sift through
the DOM in order to find where I can grab the certificate or determine
that there is not one for the document/tab/frame that the user is
currently in
Getting a representation of the certificate for the "tab" is a bit of work.

Getting it for the document the <input> is in goes like this:

nsCOMPtr<nsISupports> cert;
NodePrincipal()->GetCertificate(getter_AddRefs(cert));
if (cert) {
// Can now QI cert to nsIX509Cert, nsIX509Cert2, nsIX509Cert3,
// extract whatever you want.
}

-Boris
Anderson Walls
2012-04-19 19:10:15 UTC
Permalink
Post by Boris Zbarsky
Post by Anderson Walls
// start of my addition
if( IsPasswordTextControl() ){
   std::cerr<<  "Entered Password Field"<<  std::endl;
}
// continue mozilla source
So I now know when ever I have clicked into a password field which is
great but I have been trying for the last few weeks to sift through
the DOM in order to find where I can grab the certificate or determine
that there is not one for the document/tab/frame that the user is
currently in
Getting a representation of the certificate for the "tab" is a bit of work.
   nsCOMPtr<nsISupports> cert;
   NodePrincipal()->GetCertificate(getter_AddRefs(cert));
   if (cert) {
     // Can now QI cert to nsIX509Cert, nsIX509Cert2, nsIX509Cert3,
     // extract whatever you want.
   }
-Boris
Thanks for the helpful reply Boris.

Would you be able to tell me how to take cert and literally print out
the x509 cert to stderr, PEM, DEM, doesn't matter the format I can
script it pem with openssl. Been looking through the security
directory trying to figure out the mozilla query interface and it is
giving me some trouble and you would look like the guy who could tell
me where to go.

My use for Mozilla in my project is very simple, I need the browser to
just give me the x509 cert as is when I click into a password field,
from there the rest of my project is set up to do various other things
with cert verification fully independent for mozilla. This is the last
piece of project that needs to come together.

If you could please reply it would be greatly appreciated, I am
definitely on the right path to where I need to be now.

-Anderson
Boris Zbarsky
2012-04-19 19:30:24 UTC
Permalink
Post by Anderson Walls
nsCOMPtr<nsISupports> cert;
NodePrincipal()->GetCertificate(getter_AddRefs(cert));
if (cert) {
// Can now QI cert to nsIX509Cert, nsIX509Cert2, nsIX509Cert3,
// extract whatever you want.
}
-Boris
Thanks for the helpful reply Boris.
Would you be able to tell me how to take cert and literally print out
the x509 cert to stderr, PEM, DEM, doesn't matter the format I can
script it pem with openssl.
I can get you DER. Would that be good enough?

Starting with the above code:

nsCOMPtr<nsIX509Cert> c = do_QueryInterface(cert);
PRUint32 length;
PRUint8* data;
c->GetRawDER(&length, &data);
// Do whatever you want with the data; write it to files, whatever
NS_Free(data);

-Boris
Anderson Walls
2012-04-20 01:42:34 UTC
Permalink
Post by Anderson Walls
    nsCOMPtr<nsISupports>  cert;
    NodePrincipal()->GetCertificate(getter_AddRefs(cert));
    if (cert) {
      // Can now QI cert to nsIX509Cert, nsIX509Cert2, nsIX509Cert3,
      // extract whatever you want.
    }
-Boris
Thanks for the helpful reply Boris.
Would you be able to tell me how to take cert and literally print out
the x509 cert to stderr, PEM, DEM, doesn't matter the format I can
script it pem with openssl.
I can get you DER.  Would that be good enough?
   nsCOMPtr<nsIX509Cert> c = do_QueryInterface(cert);
   PRUint32 length;
   PRUint8* data;
   c->GetRawDER(&length, &data);
   // Do whatever you want with the data; write it to files, whatever
   NS_Free(data);
-Boris
Boris once again thank you so much, that is exactly what I needed. DER
will do just fine, converting is simple with openssl. Thank you so
much for your assistance sir.

-Anderson Walls
Boris Zbarsky
2012-04-20 02:53:29 UTC
Permalink
Post by Anderson Walls
Boris once again thank you so much, that is exactly what I needed. DER
will do just fine, converting is simple with openssl. Thank you so
much for your assistance sir.
You're very welcome!

-Boris
Anderson Walls
2012-04-23 14:45:53 UTC
Permalink
Post by Boris Zbarsky
Post by Anderson Walls
Boris once again thank you so much, that is exactly what I needed. DER
will do just fine, converting is simple with openssl. Thank you so
much for your assistance sir.
You're very welcome!
-Boris
Boris you wouldn't happen to be able to direct me to the correct
header files in order to get this all to work properly would you? I
have included the NSIx509Cert.h and the whole thing complies but never
enters the if statement, I'm assuming because I do not have the
correct headers for the nsISupports cert part.

Hope to have this thing running by this afternoon! Just as a reminder
here is what I have inserted into the nsHTMLInputElement.cpp
postHandleEvent method:

if(IsPasswordTextControl()){
std::cerr << "This is a password" << std::endl;
nsCOMPtr<nsISupports> cert;
NodePrincipal()->GetCertificate(getter_AddRefs(cert));
if(cert){
std::cerr << "CERT" << std::endl;
nsCOMPtr<nsIX059Cert> c = do_QueryInterface(cert);
PRUint32 = length;
PRUint8* data;
c->GetRawDER(&length,&data);
std::cerr << data << std::endl;
NS_Free(data);
}
}

if I try to take out the if part and just let it run I segfault when I
go into a password field, which obviously is bad. The site I have been
testing on is Navy Federal's web page so I know they do have a cert. I
have a feeling I am just missing some headers or something pretty
basic. Any ideas?

-Anderson
Boris Zbarsky
2012-04-23 17:08:01 UTC
Permalink
Post by Anderson Walls
Boris you wouldn't happen to be able to direct me to the correct
header files in order to get this all to work properly would you?
Just nsIX509Cert.h should be enough
Post by Anderson Walls
if(IsPasswordTextControl()){
std::cerr<< "This is a password"<< std::endl;
nsCOMPtr<nsISupports> cert;
NodePrincipal()->GetCertificate(getter_AddRefs(cert));
if(cert){
std::cerr<< "CERT"<< std::endl;
nsCOMPtr<nsIX059Cert> c = do_QueryInterface(cert);
nsIX509Cert
Post by Anderson Walls
PRUint32 = length;
PRUint32 length;

Are you sure this compiled?
Post by Anderson Walls
if I try to take out the if part and just let it run I segfault when I
go into a password field, which obviously is bad. The site I have been
testing on is Navy Federal's web page so I know they do have a cert.
Hmm. Maybe NodePrincipal()->GetCertificate() only gets you a cert if
the page itself is signed.... Come to think of it, almost certainly
true. :(

Maybe what would work better is something like this:

if(IsPasswordTextControl()){
nsIChannel* chan = OwnerDoc()->GetChannel();
if (chan) {
nsCOMPtr<nsISupports> securityInfo;
chan->GetSecurityInfo(getter_AddRefs(securityInfo));
nsCOMPtr<nsISSLStatusProvider> provider =
do_QueryInterface(securityInfo);
if (provider) {
nsCOMPtr<nsISSLStatus> status;
provider->GetSSLStatus(getter_AddRefs(status));
if (status) {
nsCOMPtr<nsIX509Cert> cert;
status->GetServerCert(getter_AddRefs(cert));
if (cert) {
PRUint32 length;
PRUint8* data;
cert->GetRawDER(&length,&data);
// Whatever you want
NS_Free(data);
}
}
}
}
}

-Boris
Anderson Walls
2012-04-24 02:11:24 UTC
Permalink
Post by Boris Zbarsky
Post by Anderson Walls
Boris you wouldn't happen to be able to direct me to the correct
header files in order to get this all to work properly would you?
Just nsIX509Cert.h should be enough
Post by Anderson Walls
if(IsPasswordTextControl()){
   std::cerr<<  "This is a password"<<  std::endl;
   nsCOMPtr<nsISupports>  cert;
   NodePrincipal()->GetCertificate(getter_AddRefs(cert));
   if(cert){
     std::cerr<<  "CERT"<<  std::endl;
     nsCOMPtr<nsIX059Cert>  c = do_QueryInterface(cert);
nsIX509Cert
Post by Anderson Walls
     PRUint32 = length;
PRUint32 length;
Are you sure this compiled?
Post by Anderson Walls
if I try to take out the if part and just let it run I segfault when I
go into a password field, which obviously is bad. The site I have been
testing on is Navy Federal's web page so I know they do have a cert.
Hmm.  Maybe NodePrincipal()->GetCertificate() only gets you a cert if
the page itself is signed....  Come to think of it, almost certainly
true.  :(
   if(IsPasswordTextControl()){
     nsIChannel* chan = OwnerDoc()->GetChannel();
     if (chan) {
       nsCOMPtr<nsISupports> securityInfo;
       chan->GetSecurityInfo(getter_AddRefs(securityInfo));
       nsCOMPtr<nsISSLStatusProvider> provider =
do_QueryInterface(securityInfo);
       if (provider) {
         nsCOMPtr<nsISSLStatus> status;
         provider->GetSSLStatus(getter_AddRefs(status));
         if (status) {
           nsCOMPtr<nsIX509Cert> cert;
           status->GetServerCert(getter_AddRefs(cert));
           if (cert) {
             PRUint32 length;
             PRUint8* data;
             cert->GetRawDER(&length,&data);
             // Whatever you want
             NS_Free(data);
           }
         }
       }
     }
   }
-Boris
Well Boris looks like that did it. It was compiling correctly before,
I just typo-ed in a '=', I would pray that g++ would not allow that. I
now have raw DER's going to a file so this last part of my project is
complete! Now just have to do a little gluing together and I should be
just fine.

Thank you for your continued help, I really appreciate it. I would
have spend weeks looking through Mozilla's DOM before I came to a
solution close to this. Have a good one sir, Go Navy.

- Anderson
USNA '13

Loading...