Using X.509 support for SSH on Solaris 11.1

Since Solaris 11.1 the ssh implementation of Solaris supports the usage of X.509 certificates. There is a tutorial of a colleague that explains the setup however when i linked to it a while ago, i got some mails telling me, that it was a little bit on the hard side to understand. So i thought it would be a nice idea to explain the stuff Hai-May Chao wrote in her article on OTN the LKSF way. However there are a few differences: I won’t explain that much about command lines and - more important - i’m using openssl instead of pktool to create keys and certificates.

Why using certificates

The basic idea of using certificates for ssh is quite simple. In order to get rid of passwords, you have to distribute public keys to the .ssh/authorized_keys files on each server. This is easy, when you have one instance of the OS. However imagine you have one hundred of them … or thousands. This issue can be nicely solved by certificate. The system doesn’t check if you are for example user junior. The idea of using X.509 certificates is much simpler. You are showing a certificate stating that you are user x or host y and the system believes you. However in order to prevent that you make up your own certificate stating you are user x, the certificate has to be signed by a certificate authority the communication partner trusts. Furthermore to ensure that you don’t have just the certificate, you have to sign some data with the private key, so when your communication partner can validate the signature with the certificate, it knows that you have the private key. So in essence the mechanisms checks if you have a certificate stating that you are user x, checks if a trusted certificate authority has confirmed this fact and checks that you have the private key matching to the CA signed certificate. If all is true, you are allowed to login as user x, if one is not true, access is denied and you have to use your normal password. I know this is vastly simplified, and the subject matter expert will kill me for this, but i think this is sufficient for a first explanation. At the end it’s not that different from doing SSL.

Preparations

When we want to use certificates, we have to create them. We need a Certificate Authority. When you want to do this for more than just playing around, you have to spend some thoughts about the physical security of the system. May be purchasing a cheap notebook or netbook would be a good idea. A system small enough to put it in a safe. Never attach it to the network. Disable WiFi by hardware so you don’t go into the network accidentally. Perhaps by using a wire cutter. Don’t leave it alone outside the safe. This notebook is the anchor of trust in your network and you have to trust it that it isn’t compromised without a doubt, because with this system you can basically create certificates to be any user in you network. The whole concept is based on concept that this anchor isn’t compromised. Perhaps it’s even a good idea to protect the system by an RBAC configuration that enforces a two-person-rule so a rogue employee can’t make it’s own certificates. Glenn Brunette wrote a nice example back in 2005 how to do this and he is even configuring it for a script we will use later on. Perhaps you should even use auditing of the system to the max. Okay, for this tutorial i won’t go into that part. That’s to a part because i’m lazy, however it’s more about the fear that when i’m missing something in such a part it would be my fault ;) Okay, let’s start with the tutorial.

The certificates

At first we have to create a Certificate Authority and a certificate for a host and a user.

Certificate Authority

At first we have to create our Certificate Authority (CA). This will be our anchor of trust. The configuration described in the rest of the document assumes, that when you are able to use the private key of the CA, you are authorised to give a user access to a system by signing the public key of a user or host.

root@ca:~# CA.pl -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
...............++++++
..++++++
writing new private key to '/etc/openssl/private/cakey.pem'
Enter PEM pass phrase: <b>supersecret1</b>
Verifying - Enter PEM pass phrase: <b>supersecret1</b>
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:<font="green">DE</font>
State or Province Name (full name) []:<font="green">Lower Saxony</font>
Locality Name (eg, city) []:<font="green">Lueneburg</font>
Organization Name (eg, company) []:<font="green">c0t0d0s0.org</font>
Organizational Unit Name (eg, section) []:<font="green">Security Department</font>
Common Name (e.g. server FQDN or YOUR name) []:<font="green">CA</font>
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openssl/openssl.cnf
Enter pass phrase for /etc/openssl/private/cakey.pem: <b>supersecret1</b>
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            b3:54:80:88:66:ad:e8:78
        Validity
            Not Before: Sep 26 10:11:09 2013 GMT
            Not After : Sep 25 10:11:09 2016 GMT
        Subject:
            countryName               = DE
            stateOrProvinceName       = Lower Saxony
            organizationName          = c0t0d0s0.org
            organizationalUnitName    = Security Department
            commonName                = CA
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                5B:1F:2F:71:86:12:30:40:50:15:52:81:8D:52:5A:A5:59:7E:36:44
            X509v3 Authority Key Identifier:
                keyid:5B:1F:2F:71:86:12:30:40:50:15:52:81:8D:52:5A:A5:59:7E:36:44

            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Sep 25 10:11:09 2016 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated
#

Please keep the password you have just set in mind. You will need it every time when you sign a certificate request in order to create a certificate.

Server Certificates

Now we create the server certificate. This certificate will be used by the host to identify towards a client as being really the host the client wants to connect to. For the configuration i will show in this blog entry only one parameter is really important: The common name has to be equal to the hostname. It’s the red part in the following output.

root@ca:~# mkdir server
root@ca:~# cd server
root@ca:~/server# CA.pl -newreq
Generating a 1024 bit RSA private key
.....++++++
..................++++++
writing new private key to 'newkey.pem'
Enter PEM pass phrase: <strong>supersecret2</strong>
Verifying - Enter PEM pass phrase: <strong>supersecret2</strong>
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:<font color=green>DE</font>
State or Province Name (full name) []:<font color=green>Lower Saxony</font>
Locality Name (eg, city) []:<font color=green>Lueneburg</font>
Organization Name (eg, company) []:<font color=green>c0t0d0s0.org</font>
Organizational Unit Name (eg, section) []:<font color=green>Server Certificates</font>
Common Name (e.g. server FQDN or YOUR name) []:<font color=red>server</font>
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request is in newreq.pem, private key is in newkey.pem

Now we sign the certificate request. You will need the password for the private key of the CA here.

root@ca:~/server# CA.pl -signreq
Using configuration from /etc/openssl/openssl.cnf
Enter pass phrase for /etc/openssl/private/cakey.pem: <strong>supersecret1</strong>
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            b3:54:80:88:66:ad:e8:79
        Validity
            Not Before: Sep 26 10:29:12 2013 GMT
            Not After : Sep 26 10:29:12 2014 GMT
        Subject:
            countryName               = DE
            stateOrProvinceName       = Lower Saxony
            localityName              = Lueneburg
            organizationName          = c0t0d0s0.org
            organizationalUnitName    = Server Certificates
            commonName                = server
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                A7:DC:03:DE:B3:D5:FB:F9:C0:06:F1:1A:55:A9:AD:04:C4:9C:10:FA
            X509v3 Authority Key Identifier:
                keyid:5B:1F:2F:71:86:12:30:40:50:15:52:81:8D:52:5A:A5:59:7E:36:44

Certificate is to be certified until Sep 26 10:29:12 2014 GMT (365 days)
Sign the certificate? [y/n]:<font color="green">y</font>


1 out of 1 certificate requests certified, commit? [y/n]<font color="green">y</font>
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
root@ca:~/server# ls -l
total 15
-rw-r--r--   1 root     root        3196 Sep 26 12:29 newcert.pem
-rw-r--r--   1 root     root        1041 Sep 26 12:28 newkey.pem
-rw-r--r--   1 root     root         680 Sep 26 12:28 newreq.pem

Now we have signed certificate for the host.

User Certificate

We have to do pretty much the same for our users. Important for this kind of certificate: The common name in the certificate has to be equal to the username of the user. Again it’s the red part in the following output.

root@ca:~/junior# CA.pl -newreq
Generating a 1024 bit RSA private key
..........++++++
......++++++
writing new private key to 'newkey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Verify failure
Enter PEM pass phrase: <b>supersecret3</b>
Verifying - Enter PEM pass phrase: <b>supersecret3</b>
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:<font color=green>DE</font>
State or Province Name (full name) []:<font color=green>Lower Saxony</font>
Locality Name (eg, city) []:<font color=green>Lueneburg</font>
Organization Name (eg, company) []:<font color=green>c0t0d0s0.org</font>
Organizational Unit Name (eg, section) []:<font color=green>User certificates</font>
Common Name (e.g. server FQDN or YOUR name) []:<font color=red>junior</font>
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Request is in newreq.pem, private key is in newkey.pem

We have to sign this certificate request as well. You will need the password for the private key of the CA here, again.

root@ca:~/junior# CA.pl -signreq
Using configuration from /etc/openssl/openssl.cnf
Enter pass phrase for /etc/openssl/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            b3:54:80:88:66:ad:e8:7a
        Validity
            Not Before: Sep 26 11:09:29 2013 GMT
            Not After : Sep 26 11:09:29 2014 GMT
        Subject:
            countryName               = DE
            stateOrProvinceName       = Lower Saxony
            localityName              = Lueneburg
            organizationName          = c0t0d0s0.org
            organizationalUnitName    = User certificates
            commonName                = junior
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                A1:F2:FC:9D:8A:E2:AD:9A:F5:29:03:F5:B7:14:93:3C:64:62:8E:9C
            X509v3 Authority Key Identifier:
                keyid:5B:1F:2F:71:86:12:30:40:50:15:52:81:8D:52:5A:A5:59:7E:36:44

Certificate is to be certified until Sep 26 11:09:29 2014 GMT (365 days)
Sign the certificate? [y/n]:<font color=green>y</font>


1 out of 1 certificate requests certified, commit? [y/n]<font color=green>y</font>
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
#

Okay, we have now the certificates we need. Of course other users need their own certificates as well as other hosts need their own certificate. But that should be obvious.

Assumption

I assume in the tutorial that a user junior exists on the client and the server. The user on the client could be named differently. However the username on the server has to be exactly the one as stated in the common name of the user certificate. In case there aren’t such users on your system, please create the necessary user accounts: At first on server:

root@server:~# useradd -m junior
80 blocks
root@server:~# passwd junior
New Password:
Re-enter new Password:
passwd: password successfully changed for junior
root@server:~#

We repeat the same on the client.

root@client:~# useradd -m junior
80 blocks
root@client:~# passwd junior
New Password:
Re-enter new Password:
passwd: password successfully changed for junior

Futhermore you have to ensureproper resolution of the host names. In this example i will just use /etc/hosts. So execute this on the server.

root@server:~# echo "192.168.10.51 server" >> /etc/hosts
root@server:~# echo "192.168.10.52 client" >> /etc/hosts

Now repeat the same on the client system

root@client:~# echo "192.168.10.51 server" >> /etc/hosts
root@client:~# echo "192.168.10.52 client" >> /etc/hosts

Distributing the keys and certificates

The keys and certificate we created are without use when we do not distribute them. I will to this with scp and use another already existing account on the system. On the server we need the key file and the certificate for the common name server and the certificate for the CA.

root@ca:~/server# scp /etc/openssl/cacert.pem  jmoekamp@192.168.1.109:/export/home/jmoekamp
Password:
cacert.pem           100% |****************************************|  3011       00:00
root@ca:~/server# scp newcert.pem jmoekamp@192.168.1.109:/export/home/jmoekamp
Password:
newcert.pem          100% |****************************************|  3196       00:00
root@ca:~/server# scp newkey.pem jmoekamp@192.168.1.109:/export/home/jmoekamp
Password:
newkey.pem           100% |****************************************|  1041       00:00

On the client we need the key and the certificate for the common name junior

root@ca:~/junior# scp newkey.pem junior@client:/export/home/junior
Password:
newkey.pem           100% |****************************************|  1041       00:00
root@ca:~/junior# scp newcert.pem junior@client:/export/home/junior
Password:
newcert.pem          100% |****************************************|  3190       00:00
root@ca:~/junior# scp /etc/openssl/cacert.pem  junior@192.168.1.104:/export/home/junior
Password:
cacert.pem           100% |****************************************|  3011       00:00

Configuring SSH

Now we have the certificates we need. Next step is the configuration of the ssh and sshd.

On the server

After the transfer of the keys and certificates by scp your home directory should look like this:

root@server:~# ls
cacert.pem   newcert.pem  newkey.pem

The next step is changing the PIN of the keystone of the root user.:

root@server:~# pktool setpin
Enter token passphrase: <b>changeme</b>
Create new passphrase: <b>superserversecret</b>
Re-enter new passphrase: <b>superserversecret</b>
Passphrase changed.
root@server:~#

This password is needed whenever you want to access keys in the Solaris keystone. However: As the sshd must be able to access the keystore automatically without user intervention, we put the pin in a file.

root@server:~# printf "superserversecret" > /etc/ssh/pinfile

The access to keys and certificates is handled by the Solaris Key Management Framework. We need a policy file for ssh.

root@server:~# kmfcfg create dbfile=/etc/ssh/policy.xml policy=ssh ta-name=search mapper-name=cn

This command leads to a policy file:

root@server:~# cat /etc/ssh/policy.xml
&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE kmf-policy-db SYSTEM "/usr/share/lib/xml/dtd/kmfpolicy.dtd"&gt;
&lt;kmf-policy-db&gt;
  &lt;kmf-policy name="ssh" ta-name="search"&gt;
        &lt;validation-methods&gt;
        &lt;/validation-methods&gt;

        &lt;cert-to-name-mapping mapper-name="cn"&gt;
        &lt;/cert-to-name-mapping&gt;
&lt;/kmf-policy&gt;
&lt;/kmf-policy-db&gt;

Okay, essentially this file is telling you “Don’t do a validation of the certificate by using CRL (certificate revocation lists) or OCSP (Online certificate Status Protocol). Search for a matching issuer certificate (the certificate of the CA) in the key store for such certificates (which is a directory) and the mapping from cert to name is done with /lib/crypto/kmf_mapper_cn.so” kmf_mapper_cn.so is a simple mapper which maps a certificate to it’s value of the Common Name certificate. Now we add a few lines of configuration to /etc/ssh/sshd_config. We can just append them by echo because they aren’t in the default sshd_config:

root@server:~# echo "TrustedAnchorKeystore /etc/ssh/cert" >> /etc/ssh/sshd_config
root@server:~# echo "KMFPolicyDatabase /etc/ssh/policy.xml" >> /etc/ssh/sshd_config
root@server:~# echo "KMFPolicyName ssh" >> /etc/ssh/sshd_config
root@server:~# echo "HostKey       pkcs11:object=host;token=Sun Metaslot;pinfile=/etc/ssh/pinfile" >> /etc/ssh/sshd_config

Okay, the meaning of this statements is quite straight forward: The store of the certificates of the trusted CA is in /etc/ssh/cert. It will trust any CA if they are placed here. The Key Management Policy Database is the file we just created and we will use the ssh policy in that file. The Hostkey should be taking out of the pkcs11 keystone. It’s the key with the label host and as i already wrote, as you need a password to access the keystore, the password is store in /etc/ssh/pinfile. But how do we get the private key into the pkcs#11 keystone? That’s quite easy. You use the pktool to import the keys and the certificates.

root@server:~# pktool import keystore=pkcs11 infile=newkey.pem objtype=key label=host
Enter PIN for Sun Software PKCS#11 softtoken: <b>superserversecret</b> 
Enter PEM pass phrase: <b>supersecret2</b>
Importing 1 keys

Why do you need to enter two passwords? The first one is the password to access the key store. The second one is the password protecting the key. The second is stripped off while importing it. Just one tip: The CA.pl puts the metadata of the certificate in front of the certificate. You can’t import it with this header. When you see something like that, you forgot to remove this header:

junior@client:~$ pktool import keystore=pkcs11 infile=newcert.pem objtype=cert label=user
Error importing objects:
<b>libkmf error: KMF_ERR_ENCODING</b>

I just removed the stuff by using egrep:

root@server:~# egrep -v "^ |^$|^Cert" newcert.pem > newcert.cooked.pem

Now you should be able to import the certificate:

root@server:~# pktool import keystore=pkcs11 infile=newcert.cooked.pem objtype=cert label=host
root@server:~#

That’s all for the moment on the server.

On the client

Your home directory should look like this when using the junior

junior@client:~$ ls *.pem
cacert.pem          newcert.pem         newkey.pem

We will do some steps as root first. Again we create a policy file for the Key Management Framework of Solaris and put the certificate of the certificate authority in a central directory.

root@client:~# kmfcfg create dbfile=/etc/ssh/policy.xml policy=ssh ta-name=search mapper-name=cn
root@client:~# egrep -v "^ |^$|^Cert" /export/home/junior/cacert.pem > /etc/ssh/cert/cacert.cooked.pem

Get back to the normal user privileges by leaving your root shell and change the password of the keystone for user junior:

junior@client:~$ pktool setpin
Enter token passphrase: <b>changeme</b>
Create new passphrase: <b>superusersecret</b>
Re-enter new passphrase: <b>superusersecret</b>
Passphrase changed.

Now we have to import the key and the certificate for the common name junior

junior@client:~$ pktool import keystore=pkcs11 infile=newkey.pem objtype=key label=user
Enter PIN for Sun Software PKCS#11 softtoken: <b>superusersecret</b>
Enter PEM pass phrase: <b>supersecret3</b>
Importing 1 keys
junior@client:~$ egrep -v "^ |^$|^Cert" newcert.pem > newcert.cooked.pem
junior@client:~$ pktool import keystore=pkcs11 infile=newcert.cooked.pem objtype=cert label=user

Okay, that’s all on client.

Please note...

Please note that i din’t imported the host keys and certificates to the client machine or the user certificates and keys to the server machine. Just the certificate of the CA is on both server and it’s the piece of information that creates trust between both parties. There could be hundreds or thousands of servers. As long as you have a certificate with a username in it and there is a user account with that name on the system (locally or by LDAP for example), you can log in to the system with your certificate on your client without a question for a password. This has an important implication. The user junior on server A and the user junior on server B has to be same person when both trust the same certificate authority. Otherwise the person junior on server B could access the account junior on server A and vice versa with just the certificate. But that is pretty obvious. You can solve this by separate CA for each server or just giving separate account names.

Testing

I’m not a fan of testing an ssh configuration just by kicking the ssh-service of SMF. So i will start the sshd with a different port number and a vastly increased debug level:

root@server:/# /usr/lib/ssh/sshd -p 2222 -ddd

Important to know … sshd terminates after one successful or unsuccessful attempt to log in. You have to restart it afterwards by executing the command again. Right after startup you should see something like that:

debug1: key_load_private: loading pkcs11:object=host;token=Sun Metaslot;pinfile=/etc/ssh/pinfile
debug1: ssh_kmf_check_uri: pkcs11:object=host;token=Sun Metaslot;pinfile=/etc/ssh/pinfile
debug1: Configuring the PKCS#11 keystore.
debug1: pkcs11_configure_keystore: token label 'Sun Metaslot'
debug1: kmf_find_key: key algorithm type 1.
debug1: pkcs11_load_certificate: kmf_find_cert returned 0
debug1: ssh_kmf_get_cert_pubkey_alg: alg string from cert is rsaEncryption
debug1: ssh_kmf_load_certificate returns success.
debug1: Private host key #2 of type 3 (X509_RSA).
debug1: Creating a global KMF session.

As soon you see Server listening on :: port 2222. you are ready to test. Now try to log into my server with the X.509:

junior@client:~$ ssh -o TrustedAnchorKeystore=/etc/ssh/cert \
 -o KMFPolicyDatabase=/etc/ssh/policy.xml \
 -o KMFPolicyName=ssh \
 -o IdentityFile="pkcs11:object=user;token=Sun Software PKCS#11 softtoken" \ 
 -p 2222 -vvvv junior@server

It’s a rather complex and long command line. However it tells ssh a lot of import information. You know most of the statements. We just added the satement IdentityFile By using this, you really enable the x.509 certificate based authentication (when you forget it, you will use password authentication in this session).

debug1: Trying private key: pkcs11:object=user;token=Sun Software PKCS#11 softtoken
debug1: ssh_kmf_check_uri: pkcs11:object=user;token=Sun Software PKCS#11 softtoken
debug1: Configuring the PKCS#11 keystore.
debug1: pkcs11_configure_keystore: token label 'Sun Software PKCS#11 softtoken'
debug1: No 'pinfile' attribute in URI.
Enter PIN for 'Sun Software PKCS#11 softtoken':

You should see in the client’s debug output the check for the host certificate.

debug1: ssh_kmf_key_from_blob: blob length is 737.
debug1: ssh_kmf_get_cert_pubkey_alg: alg string from cert is rsaEncryption
debug1: Certificate subject from blob is 'C=DE, ST=Lower Saxony, L=Lueneburg, O=c0t0d0s0.org, OU=Server Certificates, CN=server'.
debug1: ssh_kmf_is_cert_self_signed: 'C=DE, ST=Lower Saxony,
 L=Lueneburg, O=c0t0d0s0.org, OU=Server Certificates, CN=server' vs. 'C=DE, 
 ST=Lower Saxony, O=c0t0d0s0.org, OU=Security Department, CN=CA'
debug1: ssh_kmf_validate_cert: validating a certificate.
debug1: kmf_openssl_set_validate_attrs: kmf_ta_keystore is '/etc/ssh/cert'.
debug3: Host certificate validated.

Back on the server you should see something like that in the debugging output of the sshd:

debug1: userauth-request for user junior service ssh-connection method publickey
debug1: attempt 1 initial attempt 0 failures 0 initial failures 0
debug2: input_userauth_request: try method publickey
debug1: ssh_kmf_key_from_blob: blob length is 735.
debug1: ssh_kmf_get_cert_pubkey_alg: alg string from cert is rsaEncryption
debug1: Certificate subject from blob is 'C=DE, ST=Lower Saxony, L=Lueneburg, O=c0t0d0s0.org, OU=User certificates, CN=junior'.
debug1: We received a signature in the user auth packet.
debug3: Checking validity of the client certificate.
debug1: ssh_kmf_is_cert_self_signed: 'C=DE, ST=Lower Saxony, L=Lueneburg,
  O=c0t0d0s0.org, OU=User certificates, CN=junior' vs.
  'C=DE, ST=Lower Saxony, O=c0t0d0s0.org, OU=Security Department, CN=CA'
debug1: ssh_kmf_validate_cert: validating a certificate.
debug1: kmf_openssl_set_validate_attrs: kmf_ta_keystore is '/etc/ssh/cert'.
debug3: User certificate validated.
debug1: Extracted signature is 128 bytes long.
debug1: Data to be verified is 837 bytes long.
debug1: kmf_verify_data: data verification passed..
debug2: Starting PAM service sshd-pubkey for method publickey
debug2: userauth_pubkey: authenticated 1 pkalg x509v3-sign-rsa

At the end of it all you should see a nice shell on your system.

debug3: channel_close_fds: channel 0: r -1 w -1 e -1
Oracle Corporation      SunOS 5.11      11.1    September 2013
junior@server:~$

Neat works as designed.

Cleaning up

root@server:~# svcadm disable ssh
root@server:~# svcadm enable ssh
junior@client:~$ ssh -o TrustedAnchorKeystore=/etc/ssh/cert \
 -o KMFPolicyDatabase=/etc/ssh/policy.xml \
 -o KMFPolicyName=ssh \
 -o IdentityFile="pkcs11:object=user;token=Sun Software PKCS#11 softtoken" \
 junior@server
Enter PIN for 'Sun Software PKCS#11 softtoken':
Last login: Thu Sep 26 19:51:03 2013 from client
Oracle Corporation      SunOS 5.11      11.1    September 2013
junior@server:~$

Of course it’s a little bit cumbersome to type in all this stuff for each login into the system. If you prefer to type in your key store password every time you log in (as i do), just leave out the ;pinfile=/export/home/junior/.ssh/pinfile part and of course don’t put the PIN into the file:

junior@client:~$ cd .ssh
junior@client:~/.ssh$ printf "superusersecret" >> pinfile
junior@client:~/.ssh$ cat config
Host server-x509
  Hostname server
  TrustedAnchorKeystore /etc/ssh/cert
  KMFPolicyDatabase /etc/ssh/policy.xml
  KMFPolicyName ssh
  IdentityFile pkcs11:object=user;token=Sun Software PKCS#11 softtoken;pinfile=/export/home/junior/.ssh/pinfile

Afterwards you can log into the other server with public key authentication.

junior@client:~/.ssh$ ssh junior@server-x509
Last login: Thu Sep 26 20:07:14 2013 from client
Oracle Corporation      SunOS 5.11      11.1    September 2013
junior@server:~$

Do you want to learn more

OTN: How to Set Up X.509 Support for SunSSH on Oracle Solaris 11
(by Hai-May Chao)