dce stuff, by way of From Ake Sandgren <ake@cs.umu.se>
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8506 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
22
appl/dceutils/Makefile.am
Normal file
22
appl/dceutils/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
# $Id$
|
||||
|
||||
include $(top_srcdir)/Makefile.am.common
|
||||
|
||||
|
||||
DFSPROGS = k5dcecon
|
||||
if AIX
|
||||
AIX_DFSPROGS = dpagaix
|
||||
dpagaix_LDFLAGS = -Wl,-edpagaix -Wl,dfspag.exp
|
||||
dpagaix_LDADD =
|
||||
CC = xlc_r4
|
||||
endif
|
||||
|
||||
libexec_PROGRAMS = $(DFSPROGS) $(AIX_DFSPROGS)
|
||||
|
||||
LIB_dce = -ldce
|
||||
|
||||
k5dcecon_SOURCES = k5dcecon.c k5dce.h
|
||||
|
||||
dpagaix_SOURCES = dpagaix.c
|
||||
|
||||
LDADD = $(LIB_roken) $(LIB_dce)
|
335
appl/dceutils/README.original
Normal file
335
appl/dceutils/README.original
Normal file
@@ -0,0 +1,335 @@
|
||||
KERBEROS and DCE INTEROPERABILITY ROUTINES
|
||||
|
||||
WHAT'S NEW
|
||||
|
||||
When k5dcecon was examining the ticket caches looking to
|
||||
update one with a newer TGT, it might update the wrong
|
||||
one for the correct user. This problem was reported by PNNL,
|
||||
and is now fixed.
|
||||
|
||||
Any Kerberized application can now use a forwarded TGT to establish a
|
||||
DCE context, or can use a previously established DCE context. This is
|
||||
both a functional improvement and a performance improvement.
|
||||
|
||||
BACKGROUND
|
||||
|
||||
The MIT Kerberos 5 Release 1.x and DCE 1.1 can interoperate in a
|
||||
number of ways. This is possible because:
|
||||
|
||||
o DCE used Kerberos 5 internally. Based on the MIT code as of beta 4
|
||||
or so, with additional changes.
|
||||
|
||||
o The DCE security server can act as a K5 KDC, as defined in RFC 1510
|
||||
and responds on port 88.
|
||||
|
||||
o On the clients, DCE and Kerberos use the same format for the ticket
|
||||
cache, and then can share it. The KRB5CCNAME environment variable points
|
||||
at the cache.
|
||||
|
||||
o On the clients, DCE and Kerberos use the same format for the srvtab
|
||||
file. DCE refers to is a /krb5/v5srvtab and Kerberos as
|
||||
/etc/krb5.keytab. They can be symlinked.
|
||||
|
||||
o MIT has added many options to the krb5.conf configuration file
|
||||
which allows newer features of Release 1.0 to be turned off to match
|
||||
the earlier version of Kerberos upon which DCE is based.
|
||||
|
||||
o DCE will accept a externally obtained Kerberos TGT in place of a
|
||||
password when establishing a DCE context.
|
||||
|
||||
There are some areas where they differ, including the following:
|
||||
|
||||
o Administration of the database and the keytab files is done by the
|
||||
DCE routines, rather the the Kerberos kadmin.
|
||||
|
||||
o User password changes must be done using the DCE commands. Kpasswd
|
||||
does not work. (But there are mods to Kerberos to use the v5passwd
|
||||
with DCE.
|
||||
|
||||
o DCE goes beyond authentication only, and provides authorization via
|
||||
the PAC, and the dce-ptgt tickets stored in the cache. Thus a
|
||||
Kerberos KDC can not act as a DCE security server.
|
||||
|
||||
o A DCE cell and Kerberos realm can cross-realm authenticate, but
|
||||
there can be no intermediate realms. (There are other problems
|
||||
in this area as well. But directly connected realms/cells do work.)
|
||||
|
||||
o You can't link a module with the DCE library and the Kerberos
|
||||
library. They have conflicting routines, static data and structures.
|
||||
|
||||
One of the main features of DCE is the Distributed File System
|
||||
DFS. Access to DFS requires authentication and authorization, and when
|
||||
one uses a Kerberized network utility such as telnet, a forwarded
|
||||
Kerberos ticket can be used to establish the DCE context to allow
|
||||
access to DFS.
|
||||
|
||||
|
||||
NEW TO THIS RELEASE
|
||||
|
||||
This release introduces sharing of a DCE context, and PAG, and allows
|
||||
any Kerberized application to establish or share the context. This is
|
||||
made possible by using an undocumented feature of DCE which is on at
|
||||
least the Transarc and IBM releases of DCE 1.1.
|
||||
|
||||
I am in the process of trying to get this contributed to the general
|
||||
DCE 1.2.2 release as a patch, so it could be included in other vendors
|
||||
products. HP has expressed interest in doing this, as well as the
|
||||
OpenGroup if the modification is contributed. You can help by
|
||||
requesting Transarc and/or IBM to submit this modification to the
|
||||
OpenGroup and ask your vendor to adopt this modification.
|
||||
|
||||
The feature is a modification to the setpag() system call which will
|
||||
allow an authorized process to set the PAG to a specific value, and
|
||||
thus allow unrelated processes to share the same PAG.
|
||||
|
||||
This then allows the Kerberized daemons such as kshd, to exec a DCE
|
||||
module which established the DCE context. Kshd then sets the
|
||||
KRB5CCNAME environment variable and then issues the setpag() to use
|
||||
this context. This solves the linking problem. This is done via the
|
||||
k5dfspag.c routine.
|
||||
|
||||
The k5dfspag.c code is compiled with the lib/krb5/os routines and
|
||||
included in the libkrb5. A daemon calls krb5_dfs_pag after the
|
||||
krb5_kuserok has determined that the Kerberos principal and local
|
||||
userid pair are acceptable. This should be done early so as to give
|
||||
the daemon access to the home directory which may be located on DFS.
|
||||
If the .k5login file is used by krb5_kuserok it will need to be
|
||||
accessed by the daemon and will need special ACL handling.
|
||||
|
||||
The krb5_dfs_pag routine will exec the k5dcecon module to do all the
|
||||
real work. Upon return, if a PAG is obtained, krb5_dfs_pag with set
|
||||
the PAG for the current process to the returned PAG value. It will
|
||||
also set the KRB5CCNAME environment as well. Under DCE the PAG value
|
||||
is the nnnnnnn part of the name of the cache:
|
||||
FILE:/opt/dcelocal/var/security/creds/dcecred_nnnnnnnn.
|
||||
|
||||
The k5dcecon routine will attempt to use TGT which may have been
|
||||
forwarded, to convert it to a DCE context. If there is no TGT, an
|
||||
attempt will be made to join an existing PAG for the local userid, and
|
||||
Kerberos principal. If there are existing PAGs, and a forwarded TGT,
|
||||
k5dcecon will check the lifetime of the forwarded TGT, and if it is
|
||||
less then the lifetime of the PAG, it will just join the PAG. If it
|
||||
is greater, it will refresh the PAG using the forwarded TGT.
|
||||
This approach has the advantage of not requiring many new tickets from
|
||||
having to be obtained, and allows one to refresh a DCE context, or use
|
||||
an already established context.
|
||||
|
||||
If the system also has AFS, the AFS krb5_afs_pag should be called
|
||||
after the krb5_dfs_pag, since cache pointed at via the KRB5CCNAME may
|
||||
have changed, such as if a DFS PAG has been joined. The AFS code does
|
||||
not have the capability to join an existing AFS PAG, but can use the
|
||||
same cache which might already had a
|
||||
afsx/<afs.cell.name>@<k5.realm.name> service ticket.
|
||||
|
||||
|
||||
WHAT'S IN THIS RELEASE
|
||||
|
||||
The k5prelogin, k5dcelogin, k5afslogin (with ak5log) were designed to
|
||||
be slipped in between telnetd or klogind and login.krb5. They would
|
||||
use a forwarded Kerberos ticket to establish a DCE context. They are
|
||||
the older programs which are included here. They work on all DCE
|
||||
platforms, and don't take advantage of the undocumented setpag
|
||||
feature. (A version of k5dcelogin is being included with DCE 1.2.2)
|
||||
|
||||
K5dcecon is the new program which can be used to create, update or
|
||||
join a DCE context. k5dcecon returns KRB5CCNAME string which contains
|
||||
the PAG.
|
||||
|
||||
k5dfspag.c is to be built in the MIT Kerberos 5 release 1.0 patchlevel
|
||||
1 and added to the libkrb5. It will exec k5dcecon and upon return set
|
||||
the KRB5CCNAME and PAG. Mods to Kerberized klogind, rshd, telnetd,
|
||||
ftpd are available to use the k5dfspag.
|
||||
|
||||
Testpag.c is a test programs to see if the PAG can be set.
|
||||
|
||||
The cpwkey.c routine can be used to change a key in the DCE registry,
|
||||
by adding the key directly, or by setting the salt/pepper and password
|
||||
or by providing the key and the pepper. This could be useful when
|
||||
coping keys from a K4 or AFS database to DCE. It can also be used when
|
||||
setting a DCE to K5 cross-cell key. This program is a test program
|
||||
For mass inserts, it should be rewritten to read from stdin.
|
||||
|
||||
K5dcelogin can also be called directly, much like dce_login.
|
||||
I use the following commands in effect do the same thing as dce_login
|
||||
and get a forwardable ticket, DCE context and an AFS token:
|
||||
|
||||
#!/bin/csh
|
||||
# simulate a dce_login using krb5 kinit and k5dcelogin
|
||||
#
|
||||
setenv KRB5CCNAME FILE:/tmp/krb5cc_p$$
|
||||
/krb5/bin/kinit -f
|
||||
exec /krb5/sbin/k5dcelogin /krb5/sbin/k5afslogin /bin/csh
|
||||
#exec /krb5/sbin/k5dcelogin /bin/csh
|
||||
|
||||
This could be useful in a mixed cell where "AS_REQ" messages are
|
||||
handled by a K5 KDC, but DCE RPCs are handled by the DCE security
|
||||
server.
|
||||
|
||||
TESTING THE SETPAG
|
||||
|
||||
The krb5_dfs_pag routine relies on an undocumented feature which is
|
||||
in the AIX and Transarc Solaris ports of DCE and has been recently
|
||||
added to the SGI version. To test if this feature is present
|
||||
on some other DFS implementation use the testpag routine.
|
||||
|
||||
The testpag routine attempts to set a PAG value to one you supply. It
|
||||
uses the afs_syscall with the afs_setpag, and passes the supplied
|
||||
PAG value as the next parameter. On an unmodifed system, this
|
||||
will be ignored, and a new will be set. You should also check that
|
||||
if run as a user, you cannot join a PAG owned by another user.
|
||||
When run as root, any PAG should be usable.
|
||||
|
||||
On a machine with DFS running, do a dce_login to get a DCE context and
|
||||
PAG. ECHO the KRB5CCNAME and look at the nnnnnnnn at the end. It
|
||||
should look like an 8 char hex value, which may be 41ffxxxx on some
|
||||
systems.
|
||||
|
||||
Su to root and unsetenv KRB5CCNAME. Do a testpag -n nnnnnnnn where
|
||||
nnnnnnnn is the PAG obtained for the above name.
|
||||
|
||||
It should look like this example on an AIX 4.1.4 system:
|
||||
|
||||
pembroke# ./testpag -n 63dc9997
|
||||
calling k5dcepag newpag=63dc9997
|
||||
PAG returned = 63dc9997
|
||||
|
||||
You will be running under a new shell with the PAG and KRB5CCNAME set.
|
||||
If the PAG returned is the same as the newpag, then it worked. You can
|
||||
further verify this by doing a DCE klist, cd to DFS and a DCE klist
|
||||
again. The klist should show some tickets for DFS servers.
|
||||
|
||||
If the PAG returned is not the same, and repeated attempts show a
|
||||
returned PAG decremented by 1 from the previous returned PAG, then
|
||||
this system does not have the modification For example:
|
||||
|
||||
# ./testpag -n 41fffff9
|
||||
calling k5dcepag newpag=41fffff9
|
||||
PAG returned = 41fffff8
|
||||
# ./testpag -n 41fffff9
|
||||
calling k5dcepag newpag=41fffff9
|
||||
PAG returned = 41fffff7
|
||||
|
||||
In this case the syscall is ignoring the newpag parameter.
|
||||
|
||||
Running it with -n 0 should get the next PAG value with or without
|
||||
this modification.
|
||||
|
||||
If the DFS kernel extensions are not installed, you would get
|
||||
something like this:
|
||||
|
||||
caliban.ctd.anl.gov% ./testpag -n 012345678
|
||||
calling k5dcepag newpag=012345678
|
||||
Setpag failed with a system error
|
||||
PAG returned = ffffffff
|
||||
Not a good pag value
|
||||
|
||||
If you DFS implementation does not have this modification, you could
|
||||
attempt to install it yourself. But this requires source and requires
|
||||
modifications to the kernel extensions. At the end of this note is an
|
||||
untested sample using the DCE 1.2.2 source code. You can also contact
|
||||
your system vendor and ask for this modification.
|
||||
|
||||
UNICOS has a similar function setppag(newpag) which can be used to set
|
||||
the PAG of the parent. Contact me if you are interested.
|
||||
|
||||
HOW TO INSTALL
|
||||
|
||||
Examine the k5dfspag.c file to make sure the DFS syscalls are correct
|
||||
for your platform. See the /opt/dcelocal/share/include/dcedfs/syscall.h
|
||||
on Solaris for example.
|
||||
|
||||
You should build the testpag routine and make sure it works before
|
||||
adding all the other mods. If it fails you can still use the klogind
|
||||
and telnetd with the k5prelogin and k5dcelogin code.
|
||||
|
||||
If you intend to install with a prefix other then /krb5, change:
|
||||
DPAGAIX and K5DCECON in k5dfspag.c; the three references in
|
||||
k5prelogin.c; and the DESTDIR in the Makefile.
|
||||
|
||||
Get k5101.cdiff.xxxxxx.tar file and install the mods for ANL_DFS_PAG
|
||||
and ANL_DCE to the MIT Kerberos 5 source. These mods turn on some DCE
|
||||
related changes and the calls to krb5_dfs_pag.
|
||||
|
||||
Symlink or copy the k5dfspag.c to the src/lib/krb5/os directory.
|
||||
|
||||
Add the -DANL_DFS_PAG and -DANL_DCE flags to the configuration.
|
||||
|
||||
Configure and Build the Kerberos v5.
|
||||
|
||||
Modify the k5dce Makefile for your system.
|
||||
|
||||
Build the k5dcecon and related programs.
|
||||
|
||||
Install both the MIT Kerberos v5 and the k5dcecon and dpagaix if AIX.
|
||||
|
||||
The makefile can also build k5dcelogin and k5prelogin. The install
|
||||
can install k5dcelogin, k5prelogin and update the links for login.krb5
|
||||
-> k5prelogin and moving login.krb5 to login.k5. If you will be using
|
||||
the k5dcecon/k5dfspag with the Kerberos mods, you don't need
|
||||
k5prelogin, or the links changed, and may not need k5dcelogin.
|
||||
|
||||
Note that Transarc has obfuscated the entries to the lib, and
|
||||
the 1.0.3a is different from the 1.1. You may need to build two
|
||||
versions of the k5dcelogin and/or k5dcecon one for each.
|
||||
|
||||
AIX ONLY
|
||||
|
||||
The dpagaix routine is needed for AIX because of the way they do the
|
||||
syscalls.
|
||||
|
||||
The following fix.aix.libdce.mk is not needed if dce 2.1.0.21
|
||||
has been installed. This PTF exposed the needed entrypoints.
|
||||
|
||||
The fix.aix.libdce.mk is a Makefile for AIX 4.x to add the required
|
||||
external entry points to the libdce.a. These are needed by k5dcecon
|
||||
and k5dcelogin. A bug report was submitted to IBM on this, and it was
|
||||
rejected. But since DCE 1.2.2 will have a k5dcelogin, this should not
|
||||
be needed with 1.2.2
|
||||
|
||||
Copy /usr/lib/libdce.a to /usr/libdce.a.orig before starting. Copy the
|
||||
makefile to its own directory. It will create a new libdce.a which you
|
||||
need to copy back to /usr/lib/libdce.a You will need to reboot the
|
||||
machine. See the /usr/lpp/dce/examples/inst/README.AIX for a similar
|
||||
procedure. IBM was not responsive in a request to have these added.
|
||||
|
||||
UNTESTED KERNEL EXTENSION FOR SETPAG
|
||||
|
||||
*** src/file/osi/,osi_pag.c Wed Oct 2 13:03:05 1996
|
||||
--- src/file/osi/osi_pag.c Mon Jul 28 13:53:13 1997
|
||||
***************
|
||||
*** 293,298 ****
|
||||
--- 293,302 ----
|
||||
int code;
|
||||
|
||||
osi_MakePreemptionRight();
|
||||
+ /* allow sharing of a PAG by non child processes DEE- 6/6/97 */
|
||||
+ if (unused && osi_GetUID(osi_getucred()) == 0) {
|
||||
+ newpag = unused;
|
||||
+ } else {
|
||||
osi_mutex_enter(&osi_pagLock);
|
||||
now = osi_Time();
|
||||
soonest = osi_firstPagTime +
|
||||
***************
|
||||
*** 309,314 ****
|
||||
--- 313,319 ----
|
||||
}
|
||||
osi_mutex_exit(&osi_pagLock);
|
||||
newpag = osi_genpag();
|
||||
+ }
|
||||
osi_pcred_lock(p);
|
||||
credp = crcopy(osi_getucred());
|
||||
code = osi_SetPagInCred(credp, newpag);
|
||||
|
||||
Created 07/08/96
|
||||
Modified 09/30/96
|
||||
Modified 11/19/96
|
||||
Modified 12/19/96
|
||||
Modified 06/20/97
|
||||
Modified 07/28/97
|
||||
Modified 02/18/98
|
||||
|
||||
Douglas E. Engert <DEEngert@anl.gov>
|
||||
Argonne National Laboratory
|
||||
9700 South Cass Avenue
|
||||
Argonne, Illinois 60439
|
||||
(630) 252-5444
|
3
appl/dceutils/dfspag.exp
Normal file
3
appl/dceutils/dfspag.exp
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/unix
|
||||
* kernel extentions used to get the pag
|
||||
kafs_syscall syscall
|
23
appl/dceutils/dpagaix.c
Normal file
23
appl/dceutils/dpagaix.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* dpagaix.c
|
||||
* On AIX we need to get the kernel extentions
|
||||
* with the DFS kafs_syscall in it.
|
||||
* We might be running on a system
|
||||
* where DFS is not active.
|
||||
* So we use this dummy routine which
|
||||
* might not load to do the dirty work
|
||||
*
|
||||
* DCE does this with the /usr/lib/drivers/dfsloadobj
|
||||
*
|
||||
*/
|
||||
|
||||
int dpagaix(parm1, parm2, parm3, parm4, parm5, parm6)
|
||||
int parm1;
|
||||
int parm2;
|
||||
int parm3;
|
||||
int parm4;
|
||||
int parm5;
|
||||
int parm6;
|
||||
{
|
||||
return(kafs_syscall(parm1, parm2, parm3, parm4, parm5, parm6));
|
||||
}
|
165
appl/dceutils/k5dce.h
Normal file
165
appl/dceutils/k5dce.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/* dummy K5 routines which are needed to get this to
|
||||
* compile without having access ti the DCE versions
|
||||
* of the header files.
|
||||
* Thiis is very crude, and OSF needs to expose the K5
|
||||
* API.
|
||||
*/
|
||||
|
||||
#ifdef sun
|
||||
/* Transarc obfascates these routines */
|
||||
#ifdef DCE_1_1
|
||||
|
||||
#define krb5_init_ets _dce_PkjKqOaklP
|
||||
#define krb5_copy_creds _dce_LuFxPiITzD
|
||||
#define krb5_unparse_name _dce_LWHtAuNgRV
|
||||
#define krb5_get_default_realm _dce_vDruhprWGh
|
||||
#define krb5_build_principal _dce_qwAalSzTtF
|
||||
#define krb5_build_principal_ext _dce_vhafIQlejW
|
||||
#define krb5_build_principal_va _dce_alsqToMmuJ
|
||||
#define krb5_cc_default _dce_KZRshhTXhE
|
||||
#define krb5_cc_default_name _dce_bzJVAjHXVQ
|
||||
#define sec_login_krb5_add_cred _dce_ePDtOJTZvU
|
||||
|
||||
#else /* DCE 1.0.3a */
|
||||
|
||||
#define krb5_init_ets _dce_BmLRpOVsBo
|
||||
#define krb5_copy_creds _dce_VGwSEBNwaf
|
||||
#define krb5_unparse_name _dce_PgAOkJoMXA
|
||||
#define krb5_get_default_realm _dce_plVOzStKyK
|
||||
#define krb5_build_principal _dce_uAKSsluIFy
|
||||
#define krb5_build_principal_ext _dce_tRMpPiRada
|
||||
#define krb5_build_principal_va _dce_SxnLejZemH
|
||||
#define krb5_cc_default _dce_SeKosWFnsv
|
||||
#define krb5_cc_default_name _dce_qJeaphJWVc
|
||||
#define sec_login_krb5_add_cred _dce_uHwRasumsN
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define the bare minimum k5 structures which are needed
|
||||
* by this program. Since the krb5 includes are not supplied
|
||||
* with DCE, these were based on the MIT Kerberos 5 beta 3
|
||||
* which should match the DCE as of 1.0.3 at least.
|
||||
* The tricky one is the krb5_creds, since one is allocated
|
||||
* by this program, and it needs access to the client principal
|
||||
* in it.
|
||||
* Note that there are no function prototypes, so there is no
|
||||
* compile time checking.
|
||||
* DEE 07/11/95
|
||||
*/
|
||||
#define NPROTOTYPE(x) ()
|
||||
typedef int krb5_int32; /* assuming all DCE systems are 32 bit */
|
||||
typedef short krb5short; /* assuming short is 16 bit */
|
||||
typedef krb5_int32 krb5_error_code;
|
||||
typedef unsigned char krb5_octet;
|
||||
typedef krb5_octet krb5_boolean;
|
||||
typedef krb5short krb5_keytype; /* in k5.2 it's a short */
|
||||
typedef krb5_int32 krb5_flags;
|
||||
typedef krb5_int32 krb5_timestamp;
|
||||
|
||||
typedef char * krb5_pointer; /* pointer to unexposed data */
|
||||
|
||||
typedef struct _krb5_ccache {
|
||||
struct _krb5_cc_ops *ops;
|
||||
krb5_pointer data;
|
||||
} *krb5_ccache;
|
||||
|
||||
typedef struct _krb5_cc_ops {
|
||||
char *prefix;
|
||||
char *(*get_name) NPROTOTYPE((krb5_ccache));
|
||||
krb5_error_code (*resolve) NPROTOTYPE((krb5_ccache *, char *));
|
||||
krb5_error_code (*gen_new) NPROTOTYPE((krb5_ccache *));
|
||||
krb5_error_code (*init) NPROTOTYPE((krb5_ccache, krb5_principal));
|
||||
krb5_error_code (*destroy) NPROTOTYPE((krb5_ccache));
|
||||
krb5_error_code (*close) NPROTOTYPE((krb5_ccache));
|
||||
krb5_error_code (*store) NPROTOTYPE((krb5_ccache, krb5_creds *));
|
||||
krb5_error_code (*retrieve) NPROTOTYPE((krb5_ccache, krb5_flags,
|
||||
krb5_creds *, krb5_creds *));
|
||||
krb5_error_code (*get_princ) NPROTOTYPE((krb5_ccache,
|
||||
krb5_principal *));
|
||||
krb5_error_code (*get_first) NPROTOTYPE((krb5_ccache,
|
||||
krb5_cc_cursor *));
|
||||
krb5_error_code (*get_next) NPROTOTYPE((krb5_ccache, krb5_cc_cursor *,
|
||||
krb5_creds *));
|
||||
krb5_error_code (*end_get) NPROTOTYPE((krb5_ccache, krb5_cc_cursor *));
|
||||
krb5_error_code (*remove_cred) NPROTOTYPE((krb5_ccache, krb5_flags,
|
||||
krb5_creds *));
|
||||
krb5_error_code (*set_flags) NPROTOTYPE((krb5_ccache, krb5_flags));
|
||||
} krb5_cc_ops;
|
||||
|
||||
typedef struct _krb5_keyblock {
|
||||
krb5_keytype keytype;
|
||||
int length;
|
||||
krb5_octet *contents;
|
||||
} krb5_keyblock;
|
||||
|
||||
typedef struct _krb5_ticket_times {
|
||||
krb5_timestamp authtime;
|
||||
krb5_timestamp starttime;
|
||||
krb5_timestamp endtime;
|
||||
krb5_timestamp renew_till;
|
||||
} krb5_ticket_times;
|
||||
|
||||
typedef krb5_pointer krb5_cc_cursor;
|
||||
|
||||
typedef struct _krb5_data {
|
||||
int length;
|
||||
char *data;
|
||||
} krb5_data;
|
||||
|
||||
typedef struct _krb5_authdata {
|
||||
int ad_type;
|
||||
int length;
|
||||
krb5_octet *contents;
|
||||
} krb5_authdata;
|
||||
|
||||
typedef struct _krb5_creds {
|
||||
krb5_pointer client;
|
||||
krb5_pointer server;
|
||||
krb5_keyblock keyblock;
|
||||
krb5_ticket_times times;
|
||||
krb5_boolean is_skey;
|
||||
krb5_flags ticket_flags;
|
||||
krb5_pointer **addresses;
|
||||
krb5_data ticket;
|
||||
krb5_data second_ticket;
|
||||
krb5_pointer **authdata;
|
||||
} krb5_creds;
|
||||
|
||||
typedef krb5_pointer krb5_principal;
|
||||
|
||||
#define KRB5_CC_END 336760974
|
||||
#define KRB5_TC_OPENCLOSE 0x00000001
|
||||
|
||||
/* Ticket flags */
|
||||
/* flags are 32 bits; each host is responsible to put the 4 bytes
|
||||
representing these bits into net order before transmission */
|
||||
/* #define TKT_FLG_RESERVED 0x80000000 */
|
||||
#define TKT_FLG_FORWARDABLE 0x40000000
|
||||
#define TKT_FLG_FORWARDED 0x20000000
|
||||
#define TKT_FLG_PROXIABLE 0x10000000
|
||||
#define TKT_FLG_PROXY 0x08000000
|
||||
#define TKT_FLG_MAY_POSTDATE 0x04000000
|
||||
#define TKT_FLG_POSTDATED 0x02000000
|
||||
#define TKT_FLG_INVALID 0x01000000
|
||||
#define TKT_FLG_RENEWABLE 0x00800000
|
||||
#define TKT_FLG_INITIAL 0x00400000
|
||||
#define TKT_FLG_PRE_AUTH 0x00200000
|
||||
#define TKT_FLG_HW_AUTH 0x00100000
|
||||
#ifdef PK_INIT
|
||||
#define TKT_FLG_PUBKEY_PREAUTH 0x00080000
|
||||
#define TKT_FLG_DIGSIGN_PREAUTH 0x00040000
|
||||
#define TKT_FLG_PRIVKEY_PREAUTH 0x00020000
|
||||
#endif
|
||||
|
||||
|
||||
#define krb5_cc_get_principal(cache, principal) (*(cache)->ops->get_princ)(cache, principal)
|
||||
#define krb5_cc_set_flags(cache, flags) (*(cache)->ops->set_flags)(cache, flags)
|
||||
#define krb5_cc_get_name(cache) (*(cache)->ops->get_name)(cache)
|
||||
#define krb5_cc_start_seq_get(cache, cursor) (*(cache)->ops->get_first)(cache, cursor)
|
||||
#define krb5_cc_next_cred(cache, cursor, creds) (*(cache)->ops->get_next)(cache, cursor, creds)
|
||||
#define krb5_cc_destroy(cache) (*(cache)->ops->destroy)(cache)
|
||||
#define krb5_cc_end_seq_get(cache, cursor) (*(cache)->ops->end_get)(cache, cursor)
|
||||
|
||||
/* end of k5 dummy typedefs */
|
||||
|
791
appl/dceutils/k5dcecon.c
Normal file
791
appl/dceutils/k5dcecon.c
Normal file
@@ -0,0 +1,791 @@
|
||||
/*
|
||||
* (c) Copyright 1995 HEWLETT-PACKARD COMPANY
|
||||
*
|
||||
* To anyone who acknowledges that this file is provided
|
||||
* "AS IS" without any express or implied warranty:
|
||||
* permission to use, copy, modify, and distribute this
|
||||
* file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice and this
|
||||
* notice appears in all copies, and that the name of
|
||||
* Hewlett-Packard Company not be used in advertising or
|
||||
* publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. Hewlett-
|
||||
* Packard Company makes no representations about the
|
||||
* suitability of this software for any purpose.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* k5dcecon - Program to convert a K5 TGT to a DCE context,
|
||||
* for use with DFS and its PAG.
|
||||
*
|
||||
* The program is designed to be called as a sub process,
|
||||
* and return via stdout the name of the cache which implies
|
||||
* the PAG which should be used. This program itself does not
|
||||
* use the cache or PAG itself, so the PAG in the kernel for
|
||||
* this program may not be set.
|
||||
*
|
||||
* The calling program can then use the name of the cache
|
||||
* to set the KRB5CCNAME and PAG for its self and its children.
|
||||
*
|
||||
* If no ticket was passed, an attemplt to join an existing
|
||||
* PAG will be made.
|
||||
*
|
||||
* If a forwarded K5 TGT is passed in, either a new DCE
|
||||
* context will be created, or an existing one will be updated.
|
||||
* If the same ticket was already used to create an existing
|
||||
* context, it will be joined instead.
|
||||
*
|
||||
* Parts of this program are based on k5dceauth,c which was
|
||||
* given to me by HP and by the k5dcelogin.c which I developed.
|
||||
* A slightly different version of k5dcelogin.c, was added to
|
||||
* DCE 1.2.2
|
||||
*
|
||||
* D. E. Engert 6/17/97 ANL
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include "k5dce.h"
|
||||
|
||||
#include <dce/sec_login.h>
|
||||
#include <dce/dce_error.h>
|
||||
#include <dce/passwd.h>
|
||||
|
||||
/* #define DEBUG */
|
||||
#if defined(DEBUG)
|
||||
#define DEEDEBUG(A) fprintf(stderr,A); fflush(stderr)
|
||||
#define DEEDEBUG2(A,B) fprintf(stderr,A,B); fflush(stderr)
|
||||
#else
|
||||
#define DEEDEBUG(A)
|
||||
#define DEEDEBUG2(A,B)
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
#define seteuid(A) setresuid(-1,A,-1);
|
||||
#endif
|
||||
|
||||
|
||||
int k5dcecreate (uid_t, char *, char*, krb5_creds **);
|
||||
int k5dcecon (uid_t, char *, char *);
|
||||
int k5dcegettgt (krb5_ccache *, char *, char *, krb5_creds **);
|
||||
int k5dcematch (uid_t, char *, char *, off_t *, krb5_creds **);
|
||||
int k5dcesession (uid_t, char *, krb5_creds **, int *,krb5_flags);
|
||||
|
||||
|
||||
char *progname = "k5dcecon";
|
||||
static time_t now;
|
||||
|
||||
#ifdef notdef
|
||||
#ifdef _AIX
|
||||
/*---------------------------------------------*/
|
||||
/* AIX with DCE 1.1 does not have the com_err in the libdce.a
|
||||
* do a half hearted job of substituting for it.
|
||||
*/
|
||||
void com_err(char *p1, int code, ...)
|
||||
{
|
||||
int lst;
|
||||
dce_error_string_t err_string;
|
||||
dce_error_inq_text(code, err_string, &lst);
|
||||
fprintf(stderr,"Error %d in %s: %s\n", code, p1, err_string );
|
||||
}
|
||||
|
||||
/*---------------------------------------------*/
|
||||
void krb5_init_ets()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*------------------------------------------------*/
|
||||
/* find a cache to use for our new pag */
|
||||
/* Since there is no simple way to determine which
|
||||
* caches are associated with a pag, we will have
|
||||
* do look around and see what makes most sense on
|
||||
* different systems.
|
||||
* on a Solaris system, and in the DCE source,
|
||||
* the pags always start with a 41.
|
||||
* this is not true on the IBM, where there does not
|
||||
* appear to be any pattern.
|
||||
*
|
||||
* But since we are always certifing our creds when
|
||||
* they are received, we can us that fact, and look
|
||||
* at the first word of the associated data file
|
||||
* to see that it has a "5". If not don't use.
|
||||
*/
|
||||
|
||||
int k5dcesession(luid, pname, tgt, ppag, tflags)
|
||||
uid_t luid;
|
||||
char *pname;
|
||||
krb5_creds **tgt;
|
||||
int *ppag;
|
||||
krb5_flags tflags;
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *direntp;
|
||||
off_t size;
|
||||
krb5_timestamp endtime;
|
||||
int better = 0;
|
||||
krb5_creds *xtgt;
|
||||
|
||||
char prev_name[17] = "";
|
||||
krb5_timestamp prev_endtime;
|
||||
off_t prev_size;
|
||||
u_long prev_pag = 0;
|
||||
|
||||
char ccname[64] = "FILE:/opt/dcelocal/var/security/creds/";
|
||||
|
||||
error_status_t st;
|
||||
sec_login_handle_t lcontext = 0;
|
||||
dce_error_string_t err_string;
|
||||
int lst;
|
||||
|
||||
DEEDEBUG2("k5dcesession looking for flags %8.8x\n",tflags);
|
||||
|
||||
dirp = opendir("/opt/dcelocal/var/security/creds/");
|
||||
if (dirp == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ( (direntp = readdir( dirp )) != NULL ) {
|
||||
|
||||
/*
|
||||
* (but root has the ffffffff which we are not interested in)
|
||||
*/
|
||||
if (!strncmp(direntp->d_name,"dcecred_",8)
|
||||
&& (strlen(direntp->d_name) == 16)) {
|
||||
|
||||
/* looks like a cache name, lets do the stat, etc */
|
||||
|
||||
strcpy(ccname+38,direntp->d_name);
|
||||
if (!k5dcematch(luid, pname, ccname, &size, &xtgt)) {
|
||||
|
||||
/* its one of our caches, see if it is better
|
||||
* i.e. the endtime is farther, and if the endtimes
|
||||
* are the same, take the larger, as he who has the
|
||||
* most tickets wins.
|
||||
* it must also had the same set of flags at least
|
||||
* i.e. if the forwarded TGT is forwardable, this one must
|
||||
* be as well.
|
||||
*/
|
||||
|
||||
DEEDEBUG2("Cache:%s",direntp->d_name);
|
||||
DEEDEBUG2(" size:%d",size);
|
||||
DEEDEBUG2(" flags:%8.8x",xtgt->ticket_flags);
|
||||
DEEDEBUG2(" %s",ctime((time_t *)&xtgt->times.endtime));
|
||||
|
||||
if ((xtgt->ticket_flags & tflags) == tflags ) {
|
||||
if (prev_name[0]) {
|
||||
if (xtgt->times.endtime > prev_endtime) {
|
||||
better = 1;
|
||||
} else if ((xtgt->times.endtime = prev_endtime)
|
||||
&& (size > prev_size)){
|
||||
better = 1;
|
||||
}
|
||||
} else { /* the first */
|
||||
if (xtgt->times.endtime >= now) {
|
||||
better = 1;
|
||||
}
|
||||
}
|
||||
if (better) {
|
||||
strcpy(prev_name, direntp->d_name);
|
||||
prev_endtime = xtgt->times.endtime;
|
||||
prev_size = size;
|
||||
sscanf(prev_name+8,"%8X",&prev_pag);
|
||||
*tgt = xtgt;
|
||||
better = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)closedir( dirp );
|
||||
|
||||
if (!prev_name[0])
|
||||
return 1; /* failed to find one */
|
||||
|
||||
DEEDEBUG2("Best: %s\n",prev_name);
|
||||
|
||||
if (ppag)
|
||||
*ppag = prev_pag;
|
||||
|
||||
strcpy(ccname+38,prev_name);
|
||||
setenv("KRB5CCNAME",ccname,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------*/
|
||||
/* see if this cache is for this this principal */
|
||||
|
||||
int k5dcematch(luid, pname, ccname, sizep, tgt)
|
||||
uid_t luid;
|
||||
char *pname;
|
||||
char *ccname;
|
||||
off_t *sizep; /* size of the file */
|
||||
krb5_creds **tgt;
|
||||
{
|
||||
|
||||
krb5_ccache cache;
|
||||
struct stat stbuf;
|
||||
char ccdata[256];
|
||||
int fd;
|
||||
int status;
|
||||
|
||||
/* DEEDEBUG2("k5dcematch called: cache=%s\n",ccname+38); */
|
||||
|
||||
if (!strncmp(ccname,"FILE:",5)) {
|
||||
|
||||
strcpy(ccdata,ccname+5);
|
||||
strcat(ccdata,".data");
|
||||
|
||||
/* DEEDEBUG2("Checking the .data file for %s\n",ccdata); */
|
||||
|
||||
if (stat(ccdata, &stbuf))
|
||||
return(1);
|
||||
|
||||
if (stbuf.st_uid != luid)
|
||||
return(1);
|
||||
|
||||
if ((fd = open(ccdata,O_RDONLY)) == -1)
|
||||
return(1);
|
||||
|
||||
if ((read(fd,&status,4)) != 4) {
|
||||
close(fd);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* DEEDEBUG2(".data file status = %d\n", status); */
|
||||
|
||||
if (status != 5)
|
||||
return(1);
|
||||
|
||||
if (stat(ccname+5, &stbuf))
|
||||
return(1);
|
||||
|
||||
if (stbuf.st_uid != luid)
|
||||
return(1);
|
||||
|
||||
*sizep = stbuf.st_size;
|
||||
}
|
||||
|
||||
return(k5dcegettgt(&cache, ccname, pname, tgt));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------*/
|
||||
/* k5dcegettgt - get the tgt from a cache */
|
||||
|
||||
int k5dcegettgt(pcache, ccname, pname, tgt)
|
||||
krb5_ccache *pcache;
|
||||
char *ccname;
|
||||
char *pname;
|
||||
krb5_creds **tgt;
|
||||
|
||||
{
|
||||
krb5_ccache cache;
|
||||
krb5_cc_cursor cur;
|
||||
krb5_creds creds;
|
||||
int code;
|
||||
int found = 1;
|
||||
krb5_principal princ;
|
||||
char *kusername;
|
||||
krb5_flags flags;
|
||||
char *sname, *realm, *tgtname = NULL;
|
||||
|
||||
/* Since DCE does not expose much of the Kerberos interface,
|
||||
* we will have to use what we can. This means setting the
|
||||
* KRB5CCNAME for each file we want to test
|
||||
* We will also not worry about freeing extra cache structures
|
||||
* as this this routine is also not exposed, and this should not
|
||||
* effect this module.
|
||||
* We should also free the creds contents, but that is not exposed
|
||||
* either.
|
||||
*/
|
||||
|
||||
setenv("KRB5CCNAME",ccname,1);
|
||||
cache = NULL;
|
||||
*tgt = NULL;
|
||||
|
||||
if (code = krb5_cc_default(pcache)) {
|
||||
com_err(progname, code, "while getting ccache");
|
||||
goto return2;
|
||||
}
|
||||
|
||||
DEEDEBUG("Got cache\n");
|
||||
flags = 0;
|
||||
if (code = krb5_cc_set_flags(*pcache, flags)) {
|
||||
com_err(progname, code,"While setting flags");
|
||||
goto return2;
|
||||
}
|
||||
DEEDEBUG("Set flags\n");
|
||||
if (code = krb5_cc_get_principal(*pcache, &princ)) {
|
||||
com_err(progname, code, "While getting princ");
|
||||
goto return1;
|
||||
}
|
||||
DEEDEBUG("Got principal\n");
|
||||
if (code = krb5_unparse_name(princ, &kusername)) {
|
||||
com_err(progname, code, "While unparsing principal");
|
||||
goto return1;
|
||||
}
|
||||
|
||||
DEEDEBUG2("Unparsed to \"%s\"\n", kusername);
|
||||
DEEDEBUG2("pname is \"%s\"\n", pname);
|
||||
if (strcmp(kusername, pname)) {
|
||||
DEEDEBUG("Principals not equal\n");
|
||||
goto return1;
|
||||
}
|
||||
DEEDEBUG("Principals equal\n");
|
||||
|
||||
realm = strchr(pname,'@');
|
||||
realm++;
|
||||
|
||||
if ((tgtname = malloc(9 + 2 * strlen(realm))) == 0) {
|
||||
fprintf(stderr,"Malloc failed for tgtname\n");
|
||||
goto return1;
|
||||
}
|
||||
|
||||
strcpy(tgtname,"krbtgt/");
|
||||
strcat(tgtname,realm);
|
||||
strcat(tgtname,"@");
|
||||
strcat(tgtname,realm);
|
||||
|
||||
DEEDEBUG2("Getting tgt %s\n", tgtname);
|
||||
if (code = krb5_cc_start_seq_get(*pcache, &cur)) {
|
||||
com_err(progname, code, "while starting to retrieve tickets");
|
||||
goto return1;
|
||||
}
|
||||
|
||||
while (!(code = krb5_cc_next_cred(*pcache, &cur, &creds))) {
|
||||
krb5_creds *cred = &creds;
|
||||
|
||||
if (code = krb5_unparse_name(cred->server, &sname)) {
|
||||
com_err(progname, code, "while unparsing server name");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(sname, tgtname, strlen(tgtname)) == 0) {
|
||||
DEEDEBUG("FOUND\n");
|
||||
if (code = krb5_copy_creds(&creds, tgt)) {
|
||||
com_err(progname, code, "while copying TGT");
|
||||
goto return1;
|
||||
}
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
/* we should do a krb5_free_cred_contents(creds); */
|
||||
}
|
||||
|
||||
if (code = krb5_cc_end_seq_get(*pcache, &cur)) {
|
||||
com_err(progname, code, "while finishing retrieval");
|
||||
goto return2;
|
||||
}
|
||||
|
||||
return1:
|
||||
flags = KRB5_TC_OPENCLOSE;
|
||||
krb5_cc_set_flags(*pcache, flags); /* force a close */
|
||||
|
||||
return2:
|
||||
if (tgtname)
|
||||
free(tgtname);
|
||||
|
||||
return(found);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------*/
|
||||
/* Convert a forwarded TGT to a DCE context */
|
||||
int k5dcecon(luid, luser, pname)
|
||||
uid_t luid;
|
||||
char *luser;
|
||||
char *pname;
|
||||
{
|
||||
|
||||
krb5_creds *ftgt = NULL;
|
||||
krb5_creds *tgt = NULL;
|
||||
unsigned32 dfspag;
|
||||
boolean32 reset_passwd = 0;
|
||||
int lst;
|
||||
dce_error_string_t err_string;
|
||||
char *shell_prog;
|
||||
krb5_ccache fcache;
|
||||
char *ccname;
|
||||
char *kusername;
|
||||
char *urealm;
|
||||
char *cp;
|
||||
int pag;
|
||||
int code;
|
||||
krb5_timestamp endtime;
|
||||
|
||||
|
||||
/* If there is no cache to be converted, we should not be here */
|
||||
|
||||
if ((ccname = getenv("KRB5CCNAME")) == NULL) {
|
||||
DEEDEBUG("No KRB5CCNAME\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (k5dcegettgt(&fcache, ccname, pname, &ftgt)) {
|
||||
fprintf(stderr, "%s: Did not find TGT\n", progname);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
DEEDEBUG2("flags=%x\n",ftgt->ticket_flags);
|
||||
if (!(ftgt->ticket_flags & TKT_FLG_FORWARDABLE)){
|
||||
fprintf(stderr,"Ticket not forwardable\n");
|
||||
return(0); /* but OK to continue */
|
||||
}
|
||||
|
||||
setenv("KRB5CCNAME","",1);
|
||||
|
||||
#define TKT_ACCEPTABLE (TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE \
|
||||
| TKT_FLG_MAY_POSTDATE | TKT_FLG_RENEWABLE | TKT_FLG_HW_AUTH \
|
||||
| TKT_FLG_PRE_AUTH)
|
||||
|
||||
if (!k5dcesession(luid, pname, &tgt, &pag,
|
||||
(ftgt->ticket_flags & TKT_ACCEPTABLE))) {
|
||||
if (ftgt->times.endtime > tgt->times.endtime) {
|
||||
DEEDEBUG("Updating existing cache\n");
|
||||
return(k5dceupdate(&ftgt, pag));
|
||||
} else {
|
||||
DEEDEBUG("Using existing cache\n");
|
||||
return(0); /* use the original one */
|
||||
}
|
||||
}
|
||||
/* see if the tgts match up */
|
||||
|
||||
if ((code = k5dcecreate(luid, luser, pname, &ftgt))) {
|
||||
return (code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the Kerberos5 cred cache file.
|
||||
* but dont care aout the return code.
|
||||
*/
|
||||
|
||||
DEEDEBUG("Destroying the old cache\n");
|
||||
if ((code = krb5_cc_destroy(fcache))) {
|
||||
com_err(progname, code, "while destroying Kerberos5 ccache");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
/* k5dceupdate - update the cache with a new TGT */
|
||||
/* Assumed that the KRB5CCNAME has been set */
|
||||
|
||||
int k5dceupdate(krbtgt, pag)
|
||||
krb5_creds **krbtgt;
|
||||
int pag;
|
||||
{
|
||||
|
||||
krb5_ccache ccache;
|
||||
int code;
|
||||
|
||||
if (code = krb5_cc_default(&ccache)) {
|
||||
com_err(progname, code, "while opening cache for update");
|
||||
return(2);
|
||||
}
|
||||
|
||||
if (code = ccache->ops->init(ccache,(*krbtgt)->client)) {
|
||||
com_err(progname, code, "while reinitilizing cache");
|
||||
return(3);
|
||||
}
|
||||
|
||||
/* krb5_cc_store_cred */
|
||||
if (code = ccache->ops->store(ccache, *krbtgt)) {
|
||||
com_err(progname, code, "while updating cache");
|
||||
return(2);
|
||||
}
|
||||
|
||||
sec_login_pag_new_tgt(pag, (*krbtgt)->times.endtime);
|
||||
return(0);
|
||||
}
|
||||
/*--------------------------------------------------*/
|
||||
/* k5dcecreate - create a new DCE context */
|
||||
|
||||
int k5dcecreate(luid, luser, pname, krbtgt)
|
||||
uid_t luid;
|
||||
char *luser;
|
||||
char *pname;
|
||||
krb5_creds **krbtgt;
|
||||
{
|
||||
|
||||
char *cp;
|
||||
char *urealm;
|
||||
char *username;
|
||||
char *defrealm;
|
||||
uid_t uid;
|
||||
|
||||
error_status_t st;
|
||||
sec_login_handle_t lcontext = 0;
|
||||
sec_login_auth_src_t auth_src = 0;
|
||||
boolean32 reset_passwd = 0;
|
||||
int lst;
|
||||
dce_error_string_t err_string;
|
||||
|
||||
setenv("KRB5CCNAME","",1); /* make sure it not misused */
|
||||
|
||||
uid = getuid();
|
||||
DEEDEBUG2("uid=%d\n",uid);
|
||||
|
||||
/* if run as root, change to user, so as to have the
|
||||
* cache created for the local user even if cross-cell
|
||||
* If run as a user, let standard file protection work.
|
||||
*/
|
||||
|
||||
if (uid == 0) {
|
||||
seteuid(luid);
|
||||
}
|
||||
|
||||
cp = strchr(pname,'@');
|
||||
*cp = '\0';
|
||||
urealm = ++cp;
|
||||
|
||||
DEEDEBUG2("basename=%s\n",cp);
|
||||
DEEDEBUG2("realm=%s\n",urealm);
|
||||
|
||||
/* now build the username as a single string or a /.../cell/user
|
||||
* if this is a cross cell
|
||||
*/
|
||||
|
||||
if ((username = malloc(7+strlen(pname)+strlen(urealm))) == 0) {
|
||||
fprintf(stderr,"Malloc failed for username\n");
|
||||
goto abort;
|
||||
}
|
||||
if (krb5_get_default_realm(&defrealm)) {
|
||||
DEEDEBUG("krb5_get_default_realm failed\n");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(urealm,defrealm)) {
|
||||
strcpy(username,pname);
|
||||
} else {
|
||||
strcpy(username,"/.../");
|
||||
strcat(username,urealm);
|
||||
strcat(username,"/");
|
||||
strcat(username,pname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a DCE login context
|
||||
*/
|
||||
|
||||
if (sec_login_setup_identity((unsigned_char_p_t)username,
|
||||
(sec_login_external_tgt|sec_login_proxy_cred),
|
||||
&lcontext, &st)) {
|
||||
/*
|
||||
* Add our TGT.
|
||||
*/
|
||||
DEEDEBUG("Adding our new TGT\n");
|
||||
sec_login_krb5_add_cred(lcontext, *krbtgt, &st);
|
||||
if (st) {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Error while adding credentials for %s because %s\n",
|
||||
username, err_string);
|
||||
goto abort;
|
||||
}
|
||||
DEEDEBUG("validating and certifying\n");
|
||||
/*
|
||||
* Now "validate" and certify the identity,
|
||||
* usually we would pass a password here, but...
|
||||
* sec_login_valid_and_cert_ident
|
||||
* sec_login_validate_identity
|
||||
*/
|
||||
|
||||
if (sec_login_validate_identity(lcontext, 0, &reset_passwd,
|
||||
&auth_src, &st)) {
|
||||
DEEDEBUG2("validate_identity st=%d\n",st);
|
||||
if (st) {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr, "Validation error for %s because %s\n",
|
||||
username, err_string);
|
||||
goto abort;
|
||||
}
|
||||
if (!sec_login_certify_identity(lcontext,&st)) {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Credentials not certified because %s\n",err_string);
|
||||
}
|
||||
if (reset_passwd) {
|
||||
fprintf(stderr,
|
||||
"Password must be changed for %s\n", username);
|
||||
}
|
||||
if (auth_src == sec_login_auth_src_local) {
|
||||
fprintf(stderr,
|
||||
"Credentials obtained from local registry for %s\n",
|
||||
username);
|
||||
}
|
||||
if (auth_src == sec_login_auth_src_overridden) {
|
||||
fprintf(stderr, "Validated %s from local override entry, no network credentials obtained\n", username);
|
||||
goto abort;
|
||||
|
||||
}
|
||||
/*
|
||||
* Actually create the cred files.
|
||||
*/
|
||||
DEEDEBUG("Ceating new cred files.\n");
|
||||
sec_login_set_context(lcontext, &st);
|
||||
if (st) {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Unable to set context for %s because %s\n",
|
||||
username, err_string);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now free up the local context and leave the
|
||||
* network context with its pag
|
||||
*/
|
||||
#if 0
|
||||
sec_login_release_context(&lcontext, &st);
|
||||
if (st) {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Unable to release context for %s because %s\n",
|
||||
username, err_string);
|
||||
goto abort;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DEEDEBUG2("validate failed %d\n",st);
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Unable to validate %s because %s\n", username,
|
||||
err_string);
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dce_error_inq_text(st, err_string, &lst);
|
||||
fprintf(stderr,
|
||||
"Unable to setup login entry for %s because %s\n",
|
||||
username, err_string);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
done:
|
||||
/* if we were root, get back to root */
|
||||
|
||||
DEEDEBUG2("sec_login_inq_pag %8.8x\n",
|
||||
sec_login_inq_pag(lcontext, &st));
|
||||
|
||||
if (uid == 0) {
|
||||
seteuid(0);
|
||||
}
|
||||
|
||||
DEEDEBUG("completed\n");
|
||||
return(0);
|
||||
|
||||
abort:
|
||||
if (uid == 0) {
|
||||
seteuid(0);
|
||||
}
|
||||
|
||||
DEEDEBUG("Aborting\n");
|
||||
return(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------*/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int status;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
int rv;
|
||||
|
||||
char *lusername = NULL;
|
||||
char *pname = NULL;
|
||||
int fflag = 0;
|
||||
struct passwd *pw;
|
||||
uid_t luid;
|
||||
uid_t myuid;
|
||||
char *ccname;
|
||||
krb5_creds *tgt = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
close(2);
|
||||
open("/tmp/k5dce.debug",O_WRONLY|O_CREAT|O_APPEND);
|
||||
#endif
|
||||
|
||||
if (myuid = getuid()) {
|
||||
DEEDEBUG2("UID = %d\n",myuid);
|
||||
exit(33); /* must be root to run this, get out now */
|
||||
}
|
||||
|
||||
while ((rv = getopt(argc,argv,"l:p:fs")) != -1) {
|
||||
DEEDEBUG2("Arg = %c\n", rv);
|
||||
switch(rv) {
|
||||
case 'l': /* user name */
|
||||
lusername = optarg;
|
||||
DEEDEBUG2("Optarg = %s\n", optarg);
|
||||
break;
|
||||
case 'p': /* principal name */
|
||||
pname = optarg;
|
||||
DEEDEBUG2("Optarg = %s\n", optarg);
|
||||
break;
|
||||
case 'f': /* convert a forwarded TGT to a context */
|
||||
fflag++;
|
||||
break;
|
||||
case 's': /* old test parameter, ignore it */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
krb5_init_ets();
|
||||
time(&now); /* set time to check expired tickets */
|
||||
|
||||
/* if lusername == NULL, Then user is passed as the USER= variable */
|
||||
|
||||
if (!lusername) {
|
||||
lusername = getenv("USER");
|
||||
if (!lusername) {
|
||||
fprintf(stderr, "USER not in environment\n");
|
||||
return(3);
|
||||
}
|
||||
}
|
||||
|
||||
if ((pw = getpwnam(lusername)) == NULL) {
|
||||
fprintf(stderr, "Who are you?\n");
|
||||
return(44);
|
||||
}
|
||||
|
||||
luid = pw->pw_uid;
|
||||
|
||||
if (fflag) {
|
||||
status = k5dcecon(luid, lusername, pname);
|
||||
} else {
|
||||
status = k5dcesession(luid, pname, &tgt, NULL, 0);
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
printf("%s",getenv("KRB5CCNAME")); /* return via stdout to caller */
|
||||
DEEDEBUG2("KRB5CCNAME=%s\n",getenv("KRB5CCNAME"));
|
||||
}
|
||||
|
||||
DEEDEBUG2("Returning status %d\n",status);
|
||||
return (status);
|
||||
}
|
150
appl/dceutils/testpag.c
Normal file
150
appl/dceutils/testpag.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/* Test the k5dcepag routine by setting a pag, and
|
||||
* and execing a shell under this pag.
|
||||
*
|
||||
* This allows you to join a PAG which was created
|
||||
* earlier by some other means.
|
||||
* for example k5dcecon
|
||||
*
|
||||
* Must be run as root for testing only.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define POSIX_SETJMP
|
||||
#define POSIX_SIGNALS
|
||||
|
||||
#ifdef POSIX_SIGNALS
|
||||
typedef struct sigaction handler;
|
||||
#define handler_init(H,F) (sigemptyset(&(H).sa_mask), \
|
||||
(H).sa_flags=0, \
|
||||
(H).sa_handler=(F))
|
||||
#define handler_swap(S,NEW,OLD) sigaction(S, &NEW, &OLD)
|
||||
#define handler_set(S,OLD) sigaction(S, &OLD, NULL)
|
||||
#else
|
||||
typedef sigtype (*handler)();
|
||||
#define handler_init(H,F) ((H) = (F))
|
||||
#define handler_swap(S,NEW,OLD) ((OLD) = signal ((S), (NEW)))
|
||||
|
||||
#define handler_set(S,OLD) (signal ((S), (OLD)))
|
||||
#endif
|
||||
|
||||
typedef void sigtype;
|
||||
|
||||
/*
|
||||
* We could include the dcedfs/syscall.h which should have these
|
||||
* numbers, but it has extra baggage. So for
|
||||
* simplicity sake now, we define these here.
|
||||
*/
|
||||
|
||||
|
||||
#define AFSCALL_SETPAG 2
|
||||
#define AFSCALL_GETPAG 11
|
||||
|
||||
#if defined(sun)
|
||||
#define AFS_SYSCALL 72
|
||||
|
||||
#elif defined(hpux)
|
||||
/* assume HPUX 10 + or is it 50 */
|
||||
#define AFS_SYSCALL 326
|
||||
|
||||
#elif defined(_AIX)
|
||||
#define DPAGAIX "dpagaix"
|
||||
/* #define DPAGAIX "/krb5/sbin/dpagaix" */
|
||||
|
||||
#elif defined(sgi) || defined(_sgi)
|
||||
#define AFS_SYSCALL 206+1000
|
||||
|
||||
#else
|
||||
#define AFS_SYSCALL (Unknown_DFS_AFS_SYSCALL)
|
||||
#endif
|
||||
|
||||
static sigjmp_buf setpag_buf;
|
||||
|
||||
static sigtype mysig()
|
||||
{
|
||||
siglongjmp(setpag_buf, 1);
|
||||
}
|
||||
|
||||
|
||||
int krb5_dfs_newpag(new_pag)
|
||||
int new_pag;
|
||||
{
|
||||
handler sa1, osa1;
|
||||
handler sa2, osa2;
|
||||
int pag = -1;
|
||||
|
||||
handler_init (sa1, mysig);
|
||||
handler_init (sa2, mysig);
|
||||
handler_swap (SIGSYS, sa1, osa1);
|
||||
handler_swap (SIGSEGV, sa2, osa2);
|
||||
|
||||
if (sigsetjmp(setpag_buf, 1) == 0) {
|
||||
#if defined(_AIX)
|
||||
int (*dpagaix)(int, int, int, int, int, int);
|
||||
|
||||
if (dpagaix = load(DPAGAIX, 0, 0))
|
||||
pag = (*dpagaix)(AFSCALL_SETPAG, new_pag, 0, 0, 0, 0);
|
||||
#else
|
||||
pag = syscall(AFS_SYSCALL,AFSCALL_SETPAG, new_pag, 0, 0, 0, 0);
|
||||
#endif
|
||||
handler_set (SIGSYS, osa1);
|
||||
handler_set (SIGSEGV, osa2);
|
||||
return(pag);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Setpag failed with a system error\n");
|
||||
/* syscall failed! return 0 */
|
||||
handler_set (SIGSYS, osa1);
|
||||
handler_set (SIGSEGV, osa2);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
int rv;
|
||||
int rc;
|
||||
unsigned int pag;
|
||||
unsigned int newpag = 0;
|
||||
char ccname[256];
|
||||
int nflag = 0;
|
||||
|
||||
while((rv = getopt(argc,argv,"n:")) != -1) {
|
||||
switch(rv) {
|
||||
case 'n':
|
||||
nflag++;
|
||||
sscanf(optarg,"%8x",&newpag);
|
||||
break;
|
||||
default:
|
||||
printf("Usage: k5dcepagt -n pag \n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (nflag) {
|
||||
fprintf (stderr,"calling k5dcepag newpag=%8.8x\n",newpag);
|
||||
pag = krb5_dfs_newpag(newpag);
|
||||
|
||||
fprintf (stderr,"PAG returned = %8.8x\n",pag);
|
||||
if ((pag != 0) && (pag != -1)) {
|
||||
sprintf (ccname,
|
||||
"FILE:/opt/dcelocal/var/security/creds/dcecred_%8.8x",
|
||||
pag);
|
||||
setenv("KRB5CCNAME",ccname,1);
|
||||
execl("/bin/csh","csh",0);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr," Not a good pag value\n");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user