From cf71c7dac06561b14c8be3383fdb2ca4f3a318d9 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Sat, 19 Jan 2008 01:20:38 +0000 Subject: The wallet client now supports a -u option, saying to obtain Kerberos credentials for the given user and use those for authentication rather than using an existing ticket cache. --- client/internal.h | 5 +++++ client/krb5.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ client/wallet.c | 11 +++++++++- client/wallet.pod | 13 +++++++++-- 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 client/krb5.c (limited to 'client') diff --git a/client/internal.h b/client/internal.h index 8595412..88b0e24 100644 --- a/client/internal.h +++ b/client/internal.h @@ -29,6 +29,11 @@ struct remctl; BEGIN_DECLS +/* Given a Kerberos context and a principal name, obtain Kerberos credentials + for that principal and store them in a memory cache for use by later + operations. */ +void kinit(krb5_context, const char *principal); + /* Given a remctl object, run a remctl command. If data is non-NULL, saves the standard output from the command into data with the length in length. Otherwise, prints it to standard output. Either way, prints standard error diff --git a/client/krb5.c b/client/krb5.c new file mode 100644 index 0000000..606cbb9 --- /dev/null +++ b/client/krb5.c @@ -0,0 +1,64 @@ +/* $Id$ +** +** Kerberos support functions for the wallet client. +** +** Currently, the only function here is one to obtain a ticket cache for a +** given principal and store it in memory for use by the rest of the wallet +** client. +** +** Written by Russ Allbery +** Copyright 2007, 2008 Board of Trustees, Leland Stanford Jr. University +*/ + +#include +#include + +#include + +#include +#include + +/* The memory cache used for wallet authentication. */ +#define CACHE_NAME "MEMORY:wallet" + + +/* +** Given a Kerberos context and a principal name, authenticate as that user +** and store the TGT in a memory ticket cache for later use by remctl. Dies +** on failure. +*/ +void +kinit(krb5_context ctx, const char *principal) +{ + krb5_principal princ; + krb5_ccache ccache; + krb5_creds creds; + krb5_get_init_creds_opt opts; + krb5_error_code status; + + /* Obtain a TGT. */ + status = krb5_parse_name(ctx, principal, &princ); + if (status != 0) + die_krb5(ctx, status, "invalid Kerberos principal %s", principal); + krb5_get_init_creds_opt_init(&opts); + memset(&creds, 0, sizeof(creds)); + status = krb5_get_init_creds_password(ctx, &creds, princ, NULL, + krb5_prompter_posix, NULL, 0, NULL, &opts); + if (status != 0) + die_krb5(ctx, status, "authentication failed"); + + /* Put the new credentials into a memory cache. */ + status = krb5_cc_resolve(ctx, CACHE_NAME, &ccache); + if (status != 0) + die_krb5(ctx, status, "cannot create cache %s", CACHE_NAME); + status = krb5_cc_initialize(ctx, ccache, princ); + if (status != 0) + die_krb5(ctx, status, "cannot initialize cache %s", CACHE_NAME); + krb5_free_principal(ctx, princ); + status = krb5_cc_store_cred(ctx, ccache, &creds); + if (status != 0) + die_krb5(ctx, status, "cannot store credentials"); + krb5_cc_close(ctx, ccache); + if (putenv((char *) "KRB5CCNAME=" CACHE_NAME) != 0) + sysdie("cannot set KRB5CCNAME"); +} diff --git a/client/wallet.c b/client/wallet.c index 9dc97c2..8ce7ae0 100644 --- a/client/wallet.c +++ b/client/wallet.c @@ -26,6 +26,7 @@ struct options { char *type; char *server; char *principal; + char *user; int port; }; @@ -114,6 +115,7 @@ set_defaults(krb5_context ctx, struct options *options) default_string(ctx, "wallet_server", WALLET_SERVER, &options->server); default_string(ctx, "wallet_principal", NULL, &options->principal); default_number(ctx, "wallet_port", WALLET_PORT, &options->port); + options->user = NULL; } @@ -144,7 +146,7 @@ main(int argc, char *argv[]) die_krb5(ctx, retval, "cannot initialize Kerberos"); set_defaults(ctx, &options); - while ((option = getopt(argc, argv, "c:f:k:hp:S:s:v")) != EOF) { + while ((option = getopt(argc, argv, "c:f:k:hp:S:s:u:v")) != EOF) { switch (option) { case 'c': options.type = optarg; @@ -171,6 +173,9 @@ main(int argc, char *argv[]) case 's': options.server = optarg; break; + case 'u': + options.user = optarg; + break; case 'v': printf("%s\n", PACKAGE_STRING); exit(0); @@ -200,6 +205,10 @@ main(int argc, char *argv[]) if (options.server == NULL) die("no server specified in krb5.conf or with -s"); + /* If a user was specified, obtain Kerberos tickets. */ + if (options.user != NULL) + kinit(ctx, options.user); + /* Open a remctl connection. */ r = remctl_new(); if (r == NULL) diff --git a/client/wallet.pod b/client/wallet.pod index 0a6f395..de20586 100644 --- a/client/wallet.pod +++ b/client/wallet.pod @@ -6,7 +6,7 @@ wallet - Client for retrieving secure data from a central server B [B<-hv>] [B<-c> I] [B<-f> I] [B<-k> I] [B<-p> I] [S I>] [B<-S> I] -I [I ...] +[B<-u> I] I [I ...] =head1 DESCRIPTION @@ -118,6 +118,15 @@ The wallet server to connect to. The default may be set when compiling the wallet client. If it isn't, either B<-s> must be given or the server must be set in F. See L below. +=item B<-u> I + +Rather than using the user's existing ticket cache for authentication, +authenticate as I first and use those credentials for +authentication to the wallet server. B will prompt for the +password for I. Non-password authentication methods such as +PKINIT aren't supported; to use those, run B first and use an +existing ticket cache. + =item B<-v> Display the version of the B client and exit. All other valid @@ -418,7 +427,7 @@ overrides this setting. =head1 SEE ALSO -krb5.conf(5), remctl(1), remctld(8) +kadmin(8), kinit(1), krb5.conf(5), remctl(1), remctld(8) This program is part of the wallet system. The current version is available from L. -- cgit v1.2.3