[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: kerberos support in ssh/lsh



nisse@lysator.liu.se (Niels Möller) writes:

> I'm quite new to this list and to kerberos, and I would need some
> advice.

[...]

> 2. fork() off an extra process, which duplicates most of the work done
>    by kinit.

I ended up with the short program below, based losely on Heimdal's
implementation of su. Am I on the right track? What are the chances
that it will work also with MIT kerberos, not just heimdal?

/Niels

: /* lsh-krb-checkpw.c
:  * [ copyright notice skipped ] */
:
: #include "lsh_types.h"
: 
: #include <assert.h>
: #include <stdlib.h>
: #include <stdio.h>
: 
: #include <krb5.h>
: 
: static void usage(void) NORETURN;
: static void die(char *msg) NORETURN;
: 
: /* NOTE: It is essential that this program never ever exits successfully unless
:  * the the user was accepted by kerberos. */
: static void
: usage(void)
: {
:   printf("Usage: lsh-krb-checkpw user < password\n");
:   exit(EXIT_FAILURE);
: }
: 
: static void
: die(char *msg) 
: {
:   fprintf(stderr, "lsh-krb-checkpw: %s\n", msg);
:   exit(EXIT_FAILURE);
: }
: 
: #define PW_MAX_SIZE 40
: 
: static char *
: read_pw(FILE *f)
: {
:   /* An extra byte for the terminating NUL. */
:   char *buf = malloc(PW_MAX_SIZE+1);
:   size_t length;
:   
:   if (!buf)
:     return NULL;
: 
:   length = fread(buf, 1, PW_MAX_SIZE, f);
: 
:   if (!length || !feof(f))
:     {
: 	free(buf);
: 	return NULL;
:     }
: 
:   assert(length <= PW_MAX_SIZE);
:   buf[length] = '\0';
: 
:   return buf;
: }
: 
: int
: main(int argc, char **argv)
: {
:   krb5_context context;
:   krb5_ccache ccache;
:   krb5_principal p;
:   char *name;
:   char *pw;
:   
:   if (argc != 2)
:     usage();
: 
:   name = argv[1];
:   pw = read_pw(stdin);
: 
:   if (!pw)
:     die("No proper password provided.");
: 
:   if (!strcmp(name, "root"))
:     /* In this case, heimdal's su.c creates a principal for the
:      * current uid, but I don't quite understand why. */
:     die("Won't log in root.");
:   
:   if (krb5_init_context (&context))
:     die("krb5_init_context failed.");
: 
:   if (krb5_make_principal(context, &p, NULL, name, NULL))
:     die("krb5_init_context failed.");
:   
:   if (!krb5_kuserok(context, p, name))
:     die("krb5_kuserok doesn't know the user.");
: 
:   if (krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache))
:     die("krb5_cc_gen_new failed.");
: 
:   if (krb5_verify_user_lrealm(context, p, ccache, pw, TRUE, NULL))
:     die("krb5_verify_user_lrealm failed.");
: 
:   /* Authentication successful. */
: 
:   /* TODO: Keep the credential cache in some way. Perhaps write it to
:    * disk, and, write the file name used to stdout. */
: 
:   return EXIT_SUCCESS;
: }