DCE 1.1 provides hierarchical cells, or H-Cells. One aspect of H-Cells is transitive trust, allowing the RPC/Security run-time to ``walk the org chart'' greatly reducing the number of keys that must be exchanged (and maintained) among cells that wish to communicate. OSF RFC 7.0 provides a good introduction to this facility.
While every cell pair no longer needs to share a key, all cells must currently know the name/uuid of every cell that may communicate with them. We consider it a bug that DCE doesn't do this automatically. It's a hard bug, however, and will probably not be addressed by DCE 1.2.
This message provides some notes on writing dcecp
scripts that can be used
to partially automate the process. It is also a brief lesson on dcecp
scripting. I will take advantage of a few key points:
dcecp
is easily parsed by dcecp
as input. The TCL catch
command can be used to capture the output of a command, and
indicate whether or not an error occured. For example:
set n krbtgt/foo catch { principal show $n } prindata
This executes principal show krbtgt/foo
command, and stores any output
into the variable prindata
. It then returns zero if it succeeded or one on
error. This lets us write:
if [ catch { principal show $n } prindata ] { # The principal named $n does not exist; must create it. }
Now let's fill in the ``must create'' part. Remember we need the name and the uuid. We
already have the name in $n
. For the UUID I'll use the attrlist
command to parse the output of the principal show
command:
set celluuid [ attrlist getvalues $prindata -type uuid ] if { $celluuid == "" } { # This is a "can't happen" error. }
(The careful reader will see that the two fragments above won't work when put together.
If the catch
succeeded, the command failed, so prindata
will be
empty.)
Note that attrlist getvalues
returns an empty string if the type isn't
found. All DCE principals have a uuid, so I'm on the verge of paranoia by doing the
error-checking. We can then put the two fields together and create the cell principal:
principal create $n -uuid $celluuid
The only remaining part is how to get the ``definitive'' list of all cells. This will depend on how you set up DCE in your enterprise. I'll show some alternatives below.
You might want to create a cron
job that runs the script. (This will mean
embedding the DCE password somewhere, which is not good, but there are no alternatives to
this now.)
Now we can build up the pieces. Let's assume that other_cell
is the name
of a parent (or sibling) cell using the global ``/.../foo'' notation. We want to know
about all cells that that cell knows about. The following loop gives us the names
of all cell principals known by that other cell:
foreach p [ principal catalog $other_cell -simplename ] { ## Is this a cell principal that we don't know about? if { [ string match krbtgt/* $p ] && [ catch { principal show $p } ] } { # Yes. Find the cell's uuid and create the principal here. set output [ principal show $other_cell/$p ] set celluid [ attrlist getvalues $output -type uuid ] principal create $p -uuid $celluuid } }
Now let's make this into a function:
proc get_prins_from_cell { other_cell } { foreach p [ principal catalog $other_cell -simplename ] { # Is this a cell principal that we don't know about? if { [string match krbtgt/* $p] && [catch {principal show $p}] } { # Yes. Find the cell's uuid and create locally. set output [ principal show $other_cell/$p ] set celluid [ attrlist getvalues $output -type uuid ] principal create $p -uuid $celluuid } } }
The last question to answer is how to set other_cell
. Here are a couple of
ideas. They all follow the same format: a loop around the function above.
One simple method is to ask all the cells you already know about for the cells that
they know about. The key here is using the TCL regexp
command. This does a
regular-expression match and returns one if the string matched, or zero if it didn't. As a
side-effect it can also set a variable to part of the string that was matched. In our
case, we want to see if the principal name looks like ``krbtgt/foo'' and, if so, set a
variable to hold the foo part:
foreach p [ principal catalog -simplename ] { if [ regexp "krbtgt/(.*)" $p other_cell ] { get_prins_from_cell /.../$other_cell } }
This method is not very efficient. A better method might be for a cell to know only its parent. A script can find the name of its cell from a well-known hostdata object:
set mycellname [ attrlist getvalues [ hostdata show cell_name ] -type hostdata/data ]
It can then use regexp
command to strip off the last component. Note that
I used {}
to quote the pattern, not ""
marks since the
pattern has []
characters in it:
if [ regexp {(/.../.*)/([^/]*)} $mycellname temp parent ] { # The name of the parent cell is now in $parent get_prins_from_cell $parent }
You could also hardwire a set of cell names and try that:
foreach cell { /.../foo /.../foo/bar /.../foo/mis } { get_prins_from_cell $cell }
Even simpler, you can assume/ensure that there is one cell in your enterprise that knows about every other cell. For example, you can create your own cell-creation script that exchanges keys with this enterprise keymaster cell. (It might be a good idea to make this cell be your root cell.)
get_prins_from_cell /.../enterprise_cell
Hope you find this useful. Note that since I only used dcecp
, the script
fragments here are portable to any DCE platform that provides dcecp
.