diff options
author | Hans Insulander <hin@cvs.openbsd.org> | 2001-05-25 10:23:08 +0000 |
---|---|---|
committer | Hans Insulander <hin@cvs.openbsd.org> | 2001-05-25 10:23:08 +0000 |
commit | dd9e896da481d498f32b58d839efdf947b25a2ff (patch) | |
tree | 91c58e8382007a28f1b09df818943173a0840fe8 /lib/libtelnet/kerberos5.c | |
parent | 1346fe2b7456f0c8948b24720f7afa4650704cd8 (diff) |
KerberosV stuff taken from Heimdal.
Diffstat (limited to 'lib/libtelnet/kerberos5.c')
-rw-r--r-- | lib/libtelnet/kerberos5.c | 280 |
1 files changed, 183 insertions, 97 deletions
diff --git a/lib/libtelnet/kerberos5.c b/lib/libtelnet/kerberos5.c index 229798391f5..575a9d72571 100644 --- a/lib/libtelnet/kerberos5.c +++ b/lib/libtelnet/kerberos5.c @@ -1,5 +1,4 @@ -/* $OpenBSD: kerberos5.c,v 1.1 1998/03/12 04:48:52 art Exp $ */ -/* $Id: kerberos5.c,v 1.1 1998/03/12 04:48:52 art Exp $ */ +/* $OpenBSD: kerberos5.c,v 1.2 2001/05/25 10:23:07 hin Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -65,6 +64,9 @@ * this software for any purpose. It is provided "as is" without express * or implied warranty. */ + +/* $KTH: kerberos5.c,v 1.47 2001/01/09 18:45:33 assar Exp $ */ + #ifdef KRB5 #include <arpa/telnet.h> @@ -75,23 +77,22 @@ #include <netdb.h> #include <ctype.h> #include <pwd.h> +#include <errno.h> #define Authenticator k5_Authenticator -#include <krb5.h> +#include <kerberosV/krb5.h> #undef Authenticator + #include "encrypt.h" #include "auth.h" #include "misc.h" -extern int auth_debug_mode; - -/* where should this really reside? */ - -#ifdef KRB5 -#define FORWARD +#if defined(DCE) +int dfsk5ok = 0; +int dfspag = 0; +int dfsfwd = 0; #endif -#ifdef FORWARD int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ /* These values need to be the same as those defined in telnet/main.c. */ @@ -101,8 +102,6 @@ int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ void kerberos5_forward (Authenticator *); -#endif /* FORWARD */ - static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V5, }; @@ -111,11 +110,9 @@ static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, #define KRB_ACCEPT 2 /* Accepted */ #define KRB_RESPONSE 3 /* Response for mutual auth. */ -#ifdef FORWARD #define KRB_FORWARD 4 /* Forwarded credentials follow */ #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ -#endif /* FORWARD */ static krb5_data auth; static krb5_ticket *ticket; @@ -124,6 +121,41 @@ static krb5_context context; static krb5_auth_context auth_context; static int +check_krb5_tickets() +{ + krb5_error_code ret; + krb5_context context; + krb5_ccache ccache; + krb5_principal principal; + int retval = 1; + + ret = krb5_init_context(&context); + if(ret) + errx(1, "krb5_init_context failt: %d", ret); + + ret = krb5_cc_default(context, &ccache); + if(ret) + errx(1, "krb5_cc_default: %d", ret); + + ret = krb5_cc_get_principal (context, ccache, &principal); + switch(ret) { + case ENOENT: + retval = 0; + goto done; + case 0: + retval = 1; + goto done; + default: + errx(1, "krb5_cc_get_principal: %d", ret); + break; + } + + done: + krb5_free_context(context); + return retval; +} + +static int Data(Authenticator *ap, int type, void *d, int c) { unsigned char *p = str_data + 4; @@ -151,20 +183,40 @@ Data(Authenticator *ap, int type, void *d, int c) *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - &str_data[2]); - return(net_write(str_data, p - str_data)); + return(telnet_net_write(str_data, p - str_data)); } int kerberos5_init(Authenticator *ap, int server) { - if (server) + krb5_error_code ret; + + ret = krb5_init_context(&context); + if (ret) + return 0; + if (server) { + krb5_keytab kt; + krb5_kt_cursor cursor; + + ret = krb5_kt_default(context, &kt); + if (ret) + return 0; + + ret = krb5_kt_start_seq_get (context, kt, &cursor); + if (ret) { + krb5_kt_close (context, kt); + return 0; + } + krb5_kt_end_seq_get (context, kt, &cursor); + krb5_kt_close (context, kt); + str_data[3] = TELQUAL_REPLY; - else + } else str_data[3] = TELQUAL_IS; - krb5_init_context(&context); return(1); } +extern int net; static int kerberos5_send(char *name, Authenticator *ap) { @@ -173,8 +225,10 @@ kerberos5_send(char *name, Authenticator *ap) int ap_opts; krb5_data cksum_data; char foo[2]; + + if(check_krb5_tickets() != 1) + return 0; - printf("[ Trying %s ... ]\r\n", name); if (!UserNameRequested) { if (auth_debug_mode) { printf("Kerberos V5: no user name supplied\r\n"); @@ -205,19 +259,63 @@ kerberos5_send(char *name, Authenticator *ap) return(0); } - krb5_auth_setenctype (context, auth_context, ETYPE_DES_CBC_MD5); + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &net); + if (ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } + + krb5_auth_setkeytype (context, auth_context, KEYTYPE_DES); foo[0] = ap->type; foo[1] = ap->way; cksum_data.length = sizeof(foo); cksum_data.data = foo; - ret = krb5_mk_req(context, &auth_context, ap_opts, - "host", RemoteHostName, - &cksum_data, ccache, &auth); + + { + krb5_principal service; + char sname[128]; + + + ret = krb5_sname_to_principal (context, + RemoteHostName, + NULL, + KRB5_NT_SRV_HST, + &service); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_sname_to_principal(%s) failed (%s)\r\n", + RemoteHostName, krb5_get_err_text(context, ret)); + } + return 0; + } + ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname)); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_unparse_name_fixed failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return 0; + } + printf("[ Trying %s (%s)... ]\r\n", name, sname); + ret = krb5_mk_req_exact(context, &auth_context, ap_opts, + service, + &cksum_data, ccache, &auth); + krb5_free_principal (context, service); + + } if (ret) { - if (auth_debug_mode) { + if (1 || auth_debug_mode) { printf("Kerberos V5: mk_req failed (%s)\r\n", krb5_get_err_text(context, ret)); } @@ -261,7 +359,6 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) krb5_keyblock *key_block; char *name; krb5_principal server; - krb5_authenticator authenticator; int zero = 0; if (cnt-- < 1) @@ -318,8 +415,8 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) NULL, NULL, &ticket); - krb5_free_principal (context, server); + krb5_free_principal (context, server); if (ret) { char *errbuf; @@ -332,55 +429,29 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) free (errbuf); return; } - - ret = krb5_auth_con_getkey(context, auth_context, &key_block); - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_con_getkey failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - ret = krb5_auth_getauthenticator (context, - auth_context, - &authenticator); - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_getauthenticator failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_getauthenticator failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - - if (authenticator->cksum) { + { char foo[2]; - + foo[0] = ap->type; foo[1] = ap->way; + + ret = krb5_verify_authenticator_checksum(context, + auth_context, + foo, + sizeof(foo)); - ret = krb5_verify_checksum (context, - foo, - sizeof(foo), - key_block, - authenticator->cksum); if (ret) { - Data(ap, KRB_REJECT, "No checksum", -1); + char *errbuf; + asprintf(&errbuf, "Bad checksum: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) - printf ("No checksum\r\n"); - krb5_free_authenticator (context, - &authenticator); - + printf ("%s\r\n", errbuf); + free(errbuf); return; } } - krb5_free_authenticator (context, - &authenticator); - ret = krb5_auth_con_getremotesubkey (context, auth_context, &key_block); @@ -396,7 +467,7 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) } if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - ret = krb5_mk_rep(context, &auth_context, &outbuf); + ret = krb5_mk_rep(context, auth_context, &outbuf); if (ret) { Data(ap, KRB_REJECT, "krb5_mk_rep failed", -1); @@ -421,7 +492,9 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) name ? name : ""); } - if(key_block->keytype == KEYTYPE_DES) { + if(key_block->keytype == ETYPE_DES_CBC_MD5 || + key_block->keytype == ETYPE_DES_CBC_MD4 || + key_block->keytype == ETYPE_DES_CBC_CRC) { Session_Key skey; skey.type = SK_DES; @@ -443,13 +516,14 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) Data(ap, KRB_REJECT, (void *)msg, -1); free(msg); } + auth_finished (ap, AUTH_REJECT); + krb5_free_keyblock_contents(context, key_block); + break; } auth_finished(ap, AUTH_USER); - krb5_free_keyblock_contents(context, key_block); break; -#ifdef FORWARD case KRB_FORWARD: { struct passwd *pwd; char ccname[1024]; /* XXX */ @@ -483,10 +557,13 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) break; } - ret = krb5_rd_cred (context, - auth_context, - ccache, - &inbuf); +#if defined(DCE) + esetenv("KRB5CCNAME", ccname, 1); +#endif + ret = krb5_rd_cred2 (context, + auth_context, + ccache, + &inbuf); if(ret) { char *errbuf; @@ -501,14 +578,17 @@ kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) printf("Could not read forwarded credentials: %s\r\n", errbuf); free (errbuf); - } else + } else { Data(ap, KRB_FORWARD_ACCEPT, 0, 0); +#if defined(DCE) + dfsfwd = 1; +#endif + } chown (ccname + 5, pwd->pw_uid, -1); if (auth_debug_mode) printf("Forwarded credentials obtained\r\n"); break; } -#endif /* FORWARD */ default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); @@ -569,10 +649,8 @@ kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) encrypt_session_key(&skey, 0); krb5_free_keyblock_contents (context, keyblock); auth_finished(ap, AUTH_USER); -#ifdef FORWARD if (forward_flags & OPTS_FORWARD_CREDS) kerberos5_forward(ap); -#endif /* FORWARD */ break; } case KRB_RESPONSE: @@ -596,7 +674,6 @@ kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) mutual_complete = 1; } return; -#ifdef FORWARD case KRB_FORWARD_ACCEPT: printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); return; @@ -604,7 +681,6 @@ kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", cnt, data); return; -#endif /* FORWARD */ default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); @@ -613,7 +689,7 @@ kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) } int -kerberos5_status(Authenticator *ap, char *name, int level) +kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level) { if (level < AUTH_USER) return(level); @@ -623,7 +699,10 @@ kerberos5_status(Authenticator *ap, char *name, int level) ticket->client, UserNameRequested)) { - strcpy(name, UserNameRequested); + strlcpy(name, UserNameRequested, name_sz); +#if defined(DCE) + dfsk5ok = 1; +#endif return(AUTH_VALID); } else return(AUTH_USER); @@ -635,7 +714,6 @@ kerberos5_status(Authenticator *ap, char *name, int level) void kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - char lbuf[32]; int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ @@ -643,11 +721,11 @@ kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) switch(data[3]) { case KRB_REJECT: /* Rejected (reason might follow) */ - strncpy((char *)buf, " REJECT ", buflen); + strlcpy((char *)buf, " REJECT ", buflen); goto common; case KRB_ACCEPT: /* Accepted (name might follow) */ - strncpy((char *)buf, " ACCEPT ", buflen); + strlcpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) @@ -661,43 +739,38 @@ kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) case KRB_AUTH: /* Authentication data follows */ - strncpy((char *)buf, " AUTH", buflen); + strlcpy((char *)buf, " AUTH", buflen); goto common2; case KRB_RESPONSE: - strncpy((char *)buf, " RESPONSE", buflen); + strlcpy((char *)buf, " RESPONSE", buflen); goto common2; -#ifdef FORWARD case KRB_FORWARD: /* Forwarded credentials follow */ - strncpy((char *)buf, " FORWARD", buflen); + strlcpy((char *)buf, " FORWARD", buflen); goto common2; case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ - strncpy((char *)buf, " FORWARD_ACCEPT", buflen); + strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); goto common2; case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ /* (reason might follow) */ - strncpy((char *)buf, " FORWARD_REJECT", buflen); + strlcpy((char *)buf, " FORWARD_REJECT", buflen); goto common2; -#endif /* FORWARD */ default: - snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[3]); - strncpy((char *)buf, lbuf, buflen); + snprintf(buf, buflen, " %d (unknown)", data[3]); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { - snprintf(lbuf, sizeof(lbuf), " %d", data[i]); - strncpy((char *)buf, lbuf, buflen); + snprintf(buf, buflen, " %d", data[i]); BUMP(buf, buflen); } break; } } -#ifdef FORWARD void kerberos5_forward(Authenticator *ap) { @@ -724,6 +797,8 @@ kerberos5_forward(Authenticator *ap) return; } + memset (&creds, 0, sizeof(creds)); + creds.client = principal; ret = krb5_build_principal (context, @@ -757,7 +832,7 @@ kerberos5_forward(Authenticator *ap) &out_data); if (ret) { if (auth_debug_mode) - printf ("Kerberos V5: error gettting forwarded creds: %s\r\n", + printf ("Kerberos V5: error getting forwarded creds: %s\r\n", krb5_get_err_text (context, ret)); return; } @@ -770,6 +845,17 @@ kerberos5_forward(Authenticator *ap) printf("Forwarded local Kerberos V5 credentials to server\r\n"); } } + +#if defined(DCE) +/* if this was a K5 authentication try and join a PAG for the user. */ +void +kerberos5_dfspag(void) +{ + if (dfsk5ok) { + dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, + UserNameRequested); + } +} #endif #endif /* KRB5 */ |