diff options
Diffstat (limited to 'tdm/backend/krb5auth.c')
-rw-r--r-- | tdm/backend/krb5auth.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/tdm/backend/krb5auth.c b/tdm/backend/krb5auth.c new file mode 100644 index 000000000..16b640a35 --- /dev/null +++ b/tdm/backend/krb5auth.c @@ -0,0 +1,248 @@ +/* + +Copyright 1994, 1998 The Open Group +Copyright 2003 Oswald Buddenhagen <ossi@kde.org> + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the copyright holder. + +*/ + +/* + * xdm - display manager daemon + * Author: Stephen Gildea, The Open Group + * + * generate Kerberos Version 5 authorization records + */ + +#include <config.h> + +#ifdef K5AUTH + +#include "dm.h" +#include "dm_auth.h" +#include "dm_error.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <krb5/krb5.h> + +static krb5_context ctx; + +/*ARGSUSED*/ +void +Krb5InitAuth( unsigned short name_len ATTR_UNUSED, const char *name ATTR_UNUSED ) +{ + if (krb5_init_context( &ctx )) + LogError( "Error while initializing Krb5 context\n" ); +} + +/* + * Returns malloc'ed string that is the credentials cache name. + * name should be freed by caller. + */ +static char * +Krb5CCacheName( const char *dname ) +{ + char *name; + const char *tmpdir; + int dnl, nl; + + tmpdir = getenv( "TMPDIR" ); + if (!tmpdir) + tmpdir = "/tmp"; + dnl = strlen( dname ); + name = Malloc( strlen( tmpdir ) + dnl + 20 ); + if (!name) + return NULL; + nl = sprintf( name, "FILE:%s/K5C", tmpdir ); + CleanUpFileName( dname, name + nl, dnl + 1 ); + return name; +} + +Xauth * +Krb5GetAuthFor( unsigned short namelen, const char *name, const char *dname ) +{ + Xauth *new; + char *filename; + + if (!(new = (Xauth *)Malloc( sizeof(*new) ))) + return (Xauth *)0; + new->family = FamilyWild; + new->address_length = 0; + new->address = 0; + new->number_length = 0; + new->number = 0; + + if (dname) { + if (!(filename = Krb5CCacheName( dname ))) { + free( (char *)new ); + return (Xauth *)0; + } + new->data = 0; + if (!StrApp( &new->data, "UU:", filename, (char *)0 )) { + free( filename ); + free( (char *)new ); + return (Xauth *)0; + } + free( filename ); + new->data_length = strlen( new->data ); + } else { + new->data = NULL; + new->data_length = 0; + } + + if (!(new->name = (char *)Malloc( namelen ))) { + free( (char *)new->data ); + free( (char *)new ); + return (Xauth *)0; + } + memmove( new->name, name, namelen ); + new->name_length = namelen; + return new; +} + + +Xauth * +Krb5GetAuth( unsigned short namelen, const char *name ) +{ + return Krb5GetAuthFor( namelen, name, NULL ); +} + + +static krb5_error_code +Krb5DisplayCCache( const char *dname, krb5_ccache *ccache_return, char **name ) +{ + char *ccname; + krb5_error_code code; + + if (!(ccname = Krb5CCacheName( dname ))) + return ENOMEM; + Debug( "resolving Kerberos cache %s\n", ccname ); + if ((code = krb5_cc_resolve( ctx, ccname, ccache_return )) || !name) + free( ccname ); + else + *name = ccname; + return code; +} + +char * +Krb5Init( const char *user, const char *passwd, const char *dname ) +{ + krb5_error_code code; + krb5_get_init_creds_opt options; + krb5_principal me; + krb5_creds my_creds; + krb5_ccache ccache; + char *ccname; + + if (!ctx) + return 0; + + if ((code = krb5_parse_name( ctx, user, &me ))) { + LogError( "%s while parsing Krb5 user %\"s\n", + error_message( code ), user ); + return 0; + } + + krb5_get_init_creds_opt_init( &options ); + /*krb5_get_init_creds_opt_set_tkt_life (&options, 60*60*8);*/ /* 8 hours */ + + if ((code = krb5_get_init_creds_password( ctx, &my_creds, + me, /* principal */ + (char * /* for MIT */) passwd, + 0, /* prompter */ + 0, /* prompter ctx */ + 0, /* start time delta */ + 0, /* service */ + &options ))) + { + char *my_name = NULL; + int code2 = krb5_unparse_name( ctx, me, &my_name ); + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) + LogError( "Password incorrect for Krb5 principal %\"s\n", + code2 ? user : my_name ); + else + LogError( "%s while getting initial Krb5 credentials for %\"s\n", + error_message( code ), code2 ? user : my_name ); + if (my_name) + free( my_name ); + goto err3; + } + + if ((code = Krb5DisplayCCache( dname, &ccache, &ccname ))) { + LogError( "%s while getting Krb5 ccache for %\"s\n", + error_message( code ), dname ); + goto err2; + } + + if ((code = krb5_cc_initialize( ctx, ccache, me ))) { + LogError( "%s while initializing Krb5 cache %\"s\n", + error_message( code ), ccname ); + goto err1; + } + + if ((code = krb5_cc_store_cred( ctx, ccache, &my_creds ))) { + LogError( "%s while storing Krb5 credentials to cache %\"s\n", + error_message( code ), ccname ); + err1: + krb5_cc_close( ctx, ccache ); + free( ccname ); + err2: + krb5_free_cred_contents( ctx, &my_creds ); + err3: + krb5_free_principal( ctx, me ); + return 0; + } + + krb5_cc_close( ctx, ccache ); + krb5_free_cred_contents( ctx, &my_creds ); + krb5_free_principal( ctx, me ); + return ccname; +} + +void +Krb5Destroy( const char *dname ) +{ + krb5_error_code code; + krb5_ccache ccache; + + if (!ctx) + return; + + if ((code = Krb5DisplayCCache( dname, &ccache, 0 ))) + LogError( "%s while getting Krb5 ccache to destroy\n", + error_message( code ) ); + else { + if ((code = krb5_cc_destroy( ctx, ccache ))) { + if (code == KRB5_FCC_NOFILE) + Debug( "no Kerberos ccache file found to destroy\n" ); + else + LogError( "%s while destroying Krb5 credentials cache\n", + error_message( code ) ); + } else + Debug( "kerberos ccache destroyed\n" ); + } +} + +#endif |