Slava Leanovich
Archives
« October 2009
SunMonTueWedThuFriSat
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
       
Today
XML
Search

Links
 

Today's Page Hits: 83

All | Personal | Sun
« Unreasonably high... | Main | Inaccurate fonts on... »
20060810 Thursday August 10, 2006
Start playing with Kerberos

I was reading System Administration Guide: Security Services: Kerberos Service book, The Kerberos Network Authentication Service (V5) RFC and several web resources like Kerberos: The Network Authentication Protocol and Wikipedia: Kerberos protocol. Well, general docs are too general, specific ones too detailed, so couple of experiments are actually point out "How it works" and "How to configure it on Solaris OS" things, which may be useful for quick start with Kerberos ...

1. How it works

Conceptually, the scenario is following: The summary is:

2. How to configure it on Solaris OS

  1. First of all, you need a machine which will be a Key Distribution Center (KDC), more precisely a Master KDC.
    KDC basically issues various Kerberos tickets (TGT and Service tickets) and runs the following services:

    • krb5kdc - KDC service - krb5kdc(1M)
    • kadmin - Kerberos administration service - kadmind(1M)
    • ktkt_warn - Kerberos warning messages service - ktkt_warnd(1M)

    So on this machine:

    1. Edit /etc/krb5/krb5.conf, refer to krb5.conf(4)

      Every machine in Kerberos environment must have this config, it tells what is default realm for Kerberos libraries, and for each realm it tells where is KDC (master and its slaves) and administration server (admin server typically is on the same machine as master KDC).
      Also it tells how to map hosts and domains (domain names are precede with a dot ".") to realms.
      For example:
      [libdefaults]
              default_realm = TEST.ORG
      
      [realms]
              TEST.ORG = {
                      kdc = ironus.test.org
                      admin_server = ironus.test.org
              }
      
      [domain_realm]
              .test.org = TEST.ORG
      
      [logging]
              default = FILE:/var/krb5/kdc.log
              kdc = FILE:/var/krb5/kdc.log
              kdc_rotate = {
                      period = 1d
                      versions = 10
              }
      
      [appdefaults]
              kinit = {
                      renewable = true
                      forwardable = true
              }
      
      IMPORTANT:
      Of course, all machines must resolve all hostnames declared,
      but additionally in order to get kadmin and other services working, the very FIRST entry of "hosts" database's record, which corresponds to a hostname from admin_server option, must be the same on all machines (independently from a naming service used, whether it's ldap or nis or dns or just files).
      I.e. kerberized services use canonical representation of hostname provided by a naming service.

      In other words, if you have this on KDC:
      # getent hosts ironus.test.org
      129.157.18.54  ironus.test.org ironus
      
      but that on a client machine:
      # getent hosts ironus.test.org
      129.157.18.54  ironus ironus.test.org
      
      then most likely you'll get SERVER_NOT_FOUND on KDC and the following on a client:
      Required KADM5 principal missing while initializing kadmin interface
      
      It's because principals used by Kerberos admin are kadmin/<admin host>@<REALM> and changepw/<admin host>@<REALM>
      where <admin host> comes from the first entry queried from "hosts" database by the key taken from admin_server option of krb5.conf file (experimentally confirmed).
    2. Edit /etc/krb5/kdc.conf, refer to kdc.conf(4)

      That's KDC configuration (pretty self-explanatory), which defines realms to be served by this KDC, and for each realm defines where the principal's database is.
      Options admin_keytab, acl_file and kadmind_port are related to the administration service, will consider them later (at steps 6 and 7).
      [kdcdefaults]
              kdc_ports = 88,750
      
      [realms]
              TEST.ORG = {
                      profile = /etc/krb5/krb5.conf
                      database_name = /var/krb5/principal
                      admin_keytab = /etc/krb5/kadm5.keytab
                      acl_file = /etc/krb5/kadm5.acl
                      kadmind_port = 749
                      max_life = 8h 0m 0s
                      max_renewable_life = 7d 0h 0m 0s
                      default_principal_flags = +preauth
              }
      
    3. Make principal's database by using kdb5_util(1M):
      # kdb5_util create -s
      Initializing database '/var/krb5/principal' for realm 'TEST.ORG',
      master key name 'K/M@TEST.ORG'
      You will be prompted for the database Master Password.
      It is important that you NOT FORGET this password.
      Enter KDC database master key::
      Re-enter KDC database master key to verify::
      
      Basically kdb5_util above creates several files in /var/krb5/, including a "stash" file with a master key of /var/krb5/principal database (in our example it is /var/krb5/.k5.TEST.ORG). Master key is obviously needed for KDC in order to access the database.

      Also, by default kdb5_util creates several principals:
      # kadmin.local
      Authenticating as principal root/admin@TEST.ORG with password.
      kadmin.local:  listprincs
      K/M@TEST.ORG
      changepw/ironus.test.org@TEST.ORG
      kadmin/admin@TEST.ORG
      kadmin/changepw@TEST.ORG
      kadmin/history@TEST.ORG
      kadmin/ironus.test.org@TEST.ORG
      krbtgt/TEST.ORG@TEST.ORG
      
      kadmin.local(1M) doesn't need KDC service running, it just edit principal's database directly.
      Double-check admin principal's (kadmin and changepw), they should correspond to KDC host name.
      Command "kdb5_util destroy" removes principal's database.

    4. Ok, we're ready to start KDC service.
      # svcadm -v enable -s krb5kdc
      svc:/network/security/krb5kdc:default enabled.
      
      IMPORTANT:
      krb5kdc depends on dns/client, which in turn requires presence of /etc/resolv.conf file,
      well dns/client doesn't spawn any processes, just checks existence of /etc/resolv.conf file:
      # svccfg -s krb5kdc listprop | grep ^dns
      dns                       dependency
      dns/entities              fmri     svc:/network/dns/client
      dns/grouping              astring  require_all
      
      # svccfg -s dns/client listprop | grep ^config_data
      config_data               dependency
      config_data/entities      fmri     file://localhost/etc/resolv.conf
      config_data/grouping      astring  require_all
      
      # svccfg -s dns/client listprop | grep ^start/exec
      start/exec                astring  :true
      
      Anyway, even if you're not using DNS, you still need to sort out this dependence, so if you get your krb5kdc offline because of resolv.conf, you can simply create an empty file:
      # svcadm -v enable -s krb5kdc
      svc:/network/security/krb5kdc:default enabled.
      svcadm: Instance "svc:/network/security/krb5kdc:default"
              has unsatisfied dependencies.
      
      # svcs -x krb5kdc
      svc:/network/security/krb5kdc:default
       State: offline
      Reason: Service svc:/network/dns/client:default is disabled.
      
      # svcadm -v enable -s dns/client
      svc:/network/dns/client:default enabled.
      svcadm: Instance "svc:/network/dns/client:default"
              has unsatisfied dependencies.
      
      # svcs -x dns/client
      svc:/network/dns/client:default (DNS resolver)
       State: offline
      Reason: Dependency file://localhost/etc/resolv.conf is absent.
      
      # touch /etc/resolv.conf
      
      # svcadm -v disable -s dns/client
      # svcadm -v enable -s dns/client
      
      Finally, krb5kdc should be running ...
      # svcs -p krb5kdc
      STATE   STIME    FMRI
      online  11:40:57 svc:/network/security/krb5kdc:default
              11:40:57    10701 krb5kdc
      
      Also, check ktkt_warn service, which is by the way handled by inetd(1M).
      If ktkt_warn is not enabled, kinit may get the following warning:
        RPC: Program not registered
      kinit: no ktkt_warnd warning possible
      
    5. A quick test of KDC ...
      Add "admin" principal to the database and kinit(1), i.e. obtain and cache Kerberos ticket-granting ticket, for this principal:
      # kadmin.local
      kadmin.local:  addprinc admin
      WARNING: no policy specified for admin@TEST.ORG; defaulting to no policy
      Enter password for principal "admin@TEST.ORG": : 
      Re-enter password for principal "admin@TEST.ORG": : 
      Principal "admin@TEST.ORG" created.
      kadmin.local:  q
      
      # kinit admin
      Password for admin@TEST.ORG:
      
      # klist
      Ticket cache: FILE:/tmp/krb5cc_0
      Default principal: admin@TEST.ORG
      
      Valid starting                Expires                Service principal
      08/08/06 12:15:02  08/08/06 20:15:02  krbtgt/TEST.ORG@TEST.ORG
              renew until 08/15/06 12:15:02
      
      Looks good. Note that kdestroy(1) clears ticket cache.
      "WARNING: no policy specified" is ok for now, a "policy" there means just a password policy.

    6. Now you probably want to start the administration server, so you need to create a "keytab" for it.

      Well, kadmind(1M) is like a normal Kerberos service, therefore:

      • it must have one or more service principals,
      • and besides, log-term Service's keys, corresponding to these principals, somehow must be shared with TGS, which is krb5kdc(1M) in our case, refer to How it works section.

      Such long-term key sharing is implemented in the way that on KDC side keys are stored in principal's database, and on Service's side keys are in keytab files. According to man of kadmind(1M) it uses kadmin/<admin host> and changepw/<admin host> principals. Basically kdb5_util generates them, so we can "export" these principals to a admin server's keytab. A keytab name is specified by admin_keytab option in /etc/krb5/kdc.conf file, in our case it is /etc/krb5/kadm5.keytab, so:
      # kadmin.local
      Authenticating as principal root/admin@TEST.ORG with password.
      kadmin.local:  ktadd -k /etc/krb5/kadm5.keytab
                     kadmin/ironus.test.org changepw/ironus.test.org
      
      Note that ktadd not just exports keys, it generates new keys.
      If you do getprinc in kadmin.local before and after ktadd, you'll see that keys have different version numbers (vno).

      You may use klist(1) or ktutil(1) to inspect a keytab:
      # klist -k /etc/krb5/kadm5.keytab
      Keytab name: FILE:/etc/krb5/kadm5.keytab
      KVNO Principal
      ---- ---------------------------------
         3 changepw/ironus.test.org@TEST.ORG
         3 changepw/ironus.test.org@TEST.ORG
         3 changepw/ironus.test.org@TEST.ORG
         3 changepw/ironus.test.org@TEST.ORG
         3 kadmin/ironus.test.org@TEST.ORG
         3 kadmin/ironus.test.org@TEST.ORG
         3 kadmin/ironus.test.org@TEST.ORG
         3 kadmin/ironus.test.org@TEST.ORG
      
      Obviously key version numbers must be the same in KDC's principal database and in Service's keytab.

    7. Set Access Control Level (ACL) for admin server.

      Edit /etc/krb5/kadm5.acl (we specified this name in kdc.conf file, acl_file option),
      for instance give all permissions to "admin" principal (read more about it in kadm5.acl(4) manual):
      admin@TEST.ORG *
      
    8. Start administration service ...
      # svcadm -v enable -s kadmin
      svc:/network/security/kadmin:default enabled.
      
      IMPORTANT:
      The /var/krb5/rcache and /var/krb5/rcache/root directories MUST exist !
      kadmind creates some files e.g. kadmin_0, changepw_0 there ...
      (I guess if KDC stuff will run not under root it may change accordingly)
      # ls -lR /var/krb5/rcache/
      /var/krb5/rcache/:
      total 2
      drwx------   2 root     sys          512 Aug  8 20:25 root
      
      /var/krb5/rcache/root:
      total 4
      -rw-------   1 root     sys           71 Aug  9 16:09 changepw_0
      -rw-------   1 root     sys         1005 Aug  9 15:32 kadmin_0
      
      Without even /var/krb5/rcache/root the kadmind fails with:
      kadmind[11197](Error): Unable to set RPCSEC_GSS service names
      
      and so kadmin service does:
      Restarting too quickly, changing state to maintenance
      
      a client in turn has:
      GSS-API (or Kerberos) error while initializing kadmin interface
      
      just nothing works ...
    9. A quick test of admin ...
      # kadmin -p admin
      Authenticating as principal admin@TEST.ORG with password.
      Password for admin@TEST.ORG: 
      kadmin:  listprincs
      K/M@TEST.ORG
      ...
      
      # kpasswd admin
      kpasswd: Changing password for admin.
      Old password:: 
      New password:: 
      New password (again):: 
      Kerberos password changed.
      
      Here we go, master KDC is up.

      Who likes GUI may run gkadmin application ;-)

  2. Kerberos client machines.

    Before going any further, make sure ALL machines in kerberos environment have:

    • Proper /etc/krb5/krb5.conf file, it should be the same as one on KDC, see krb5.conf description.
    • Valid host names specified in kdc and admin_server options, see important note.
    • Clock is close to KDC's clock (usually difference should not be bigger than 5 minutes).

      Actually you can start time service on KDC:
      [KDC]# svcadm -v enable -s time:stream time:dgram
      svc:/network/time:stream enabled.
      svc:/network/time:dgram enabled.
      
      and then sync other's clock by rdate(1M), e.g.
      [kclient]# rdate ironus.test.org
      
    So, if points above are true, then at least kinit, kadmin, and etc. should work on client.

  3. Some "kerberized" services setup.

    • telnet

      We're on telnet server machine, which is presumably kerberos configured,
      so need to create host/<telnet server hostname> principal on KDC,
      and put its keys to a local keytab (by default it's /etc/krb5/krb5.keytab)
      as far as we want to share long-term Service's key between in.telnetd(1M) and KDC:
      [telnetd]# kadmin -p admin
      Authenticating as principal admin@TEST.ORG with password.
      Password for admin@TEST.ORG:
      kadmin:  addprinc -randkey host/frostina.test.org
      Principal "host/frostina.test.org@TEST.ORG" created.
      kadmin:  ktadd host/frostina.test.org
      kadmin: Bad encryption type while changing host/frostina.test.org's key
      
      Hmmm, looks like we're requesting encryption type which is not supported by KDC.
      Try to explicitly generate just DES and Triple DES keys, basically used by a telnet:
      kadmin:  ktadd -e des3-hmac-sha1:normal,des-cbc-md5:normal
                     host/frostina.test.org
      Entry for principal host/frostina.test.org with kvno 5,
          encryption type Triple DES cbc mode with HMAC/sha1 added to 
          keytab WRFILE:/etc/krb5/krb5.keytab.
      Entry for principal host/frostina.test.org with kvno 5,
          encryption type DES cbc mode with RSA-MD5 added to 
          keytab WRFILE:/etc/krb5/krb5.keytab.
      
      Refer to kadmin(1M) for the ktadd subcommand description,
      and for a list of permitted encryption types see krb5.conf(4): permitted_enctypes section.

      Double-check local keytab, particularly its keys:
      # klist -ke
      Keytab name: FILE:/etc/krb5/krb5.keytab
      KVNO Principal
      ---- --------------------------------------------------------------------
         5 host/frostina.test.org@TEST.ORG (Triple DES cbc mode with HMAC/sha1) 
         5 host/frostina.test.org@TEST.ORG (DES cbc mode with RSA-MD5)
      
      Keys look fine, now start/restart telnet service ...
      # svcadm -v enable -s telnet
      
      Basically, in.telnetd(1M) allocates pseudo-terminal and creates a login(1) process, which in turn uses pam(3PAM) - Pluggable Authentication Module for the authentication, account, session and password management,
      therefore if we want to authenticate by kerberos, we should plug pam_krb5(5) library.
      Normally /etc/pam.conf, see pam.conf(4), has the following definitions:
      ktelnet auth     required   pam_unix_cred.so.1
      ktelnet auth     binding    pam_krb5.so.1
      ktelnet auth     required   pam_unix_auth.so.1
      
      other   account  requisite  pam_roles.so.1
      other   account  required   pam_unix_account.so.1
      
      other   session  required   pam_unix_session.so.1
      
      other   password required   pam_dhkeys.so.1
      other   password requisite  pam_authtok_get.so.1
      other   password requisite  pam_authtok_check.so.1
      other   password required   pam_authtok_store.so.1
      
      It means that authentication for kerberized telnet (ktelnet) service goes through pam_krb5, while account, session and password management are UNIX default.

      Eventually, for our example, assume:

      • user1@TEST.ORG principal exists in our realm

      • user1 is a valid user on the telnet server, otherwise
        Krb5 principal lacks permission to access local account for user1
        
      • user1 is not locked, otherwise
        pam_unix_account: ktelnet attempting to validate locked account
        
        actually /etc/shadow may contain the following:
        user1:NP:::::::
        
      So, let's try to kinit and telnet (forwarding TGT) from some kerberized machine now ...
      $ kinit user1
      Password for user1@TEST.ORG:
      
      $ telnet -a -F -l user1 frostina.test.org
      Connected to frostina.test.org.
      Escape character is '^]'.
      [ Kerberos V5 accepts you as ''user1@TEST.ORG'' ]
      [ Kerberos V5 accepted forwarded credentials ]
      Sun Microsystems Inc.   SunOS 5.11
      [user1@frostina]$
      
      Isn't it's cool.

posted by leanovich Aug 10 2006, 04:20:11 PM CEST Permalink Comments [3]

Trackback URL: http://blogs.sun.com/vl/entry/start_playing_with_kerberos
Comments:

Thanks for this write-up. I found it very useful.

Posted by Jeff on January 25, 2007 at 10:05 PM CET #

dam fine blog, helped me loads - big thanks :)

Posted by rob on August 15, 2008 at 06:17 PM CEST #

Thanks for the tip to create /var/krb5/rcache/root
Where did you find that?

Posted by Douglas on September 16, 2008 at 01:13 PM CEST #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed