+Tue Apr 25 21:23:28 1995 Chris Provenzano (proven@mit.edu)
+
+ * forward.c (rd_and_store_for_creds()) : Rewritten to use
+ auth_context and the new krb5_rd_creds().
+ * forward.c (get_for_creds()) : New function replacing
+ krb5_get_for_creds() and uses auth_context and new
+ krb5_mk_creds() routine.
+ * kerberos5.c (kerberos5_send()): Set initial flags on auth_context
+ to KRB5_AUTH_CONTEXT_RET_TIME, and use new
+ rd_and_store_for_creds() routine.
+ * kerberos5.c (kerberos5_forward()): Use the new get_for_creds().
+
Sat Apr 22 00:50:14 1995 Theodore Y. Ts'o (tytso@dcl)
* kerberos5.c (kerberos5_init): Only call krb5_init_context if
/* General-purpose forwarding routines. These routines may be put into */
/* libkrb5.a to allow widespread use */
-#if defined(KRB5) && defined(FORWARD)
+#if defined(KERBEROS) || defined(KRB5)
#include <stdio.h>
#include <pwd.h>
#include <netdb.h>
-
-#include "krb5.h"
-
+
+#include "k5-int.h"
+
/* Decode, decrypt and store the forwarded creds in the local ccache. */
krb5_error_code
-rd_and_store_for_creds(context, inbuf, ticket, lusername)
- krb5_context context;
- krb5_data *inbuf;
- krb5_ticket *ticket;
- char *lusername;
+rd_and_store_for_creds(context, auth_context, inbuf, ticket, lusername)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_data *inbuf;
+ krb5_ticket *ticket;
+ char *lusername;
{
- krb5_creds creds;
+ krb5_creds **creds;
krb5_error_code retval;
char ccname[35];
krb5_ccache ccache = NULL;
struct passwd *pwd;
- if (retval = krb5_rd_cred(context, inbuf, ticket->enc_part2->session,
- &creds, 0, 0)) {
- return(retval);
- }
-
- if (!(pwd = (struct passwd *) getpwnam(lusername))) {
+ if (!(pwd = (struct passwd *) getpwnam(lusername)))
return -1;
- }
+
+ if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
+ return(retval);
sprintf(ccname, "FILE:/tmp/krb5cc_%d", pwd->pw_uid);
- if (retval = krb5_cc_resolve(context, ccname, &ccache)) {
- return(retval);
+ if (retval = krb5_cc_resolve(context, ccname, &ccache))
+ goto cleanup;
+
+ if (retval = krb5_cc_initialize(context, ccache, ticket->enc_part2->client))
+ goto cleanup;
+
+ if (retval = krb5_cc_store_cred(context, ccache, *creds))
+ goto cleanup;
+
+ if (retval = chown(ccname+5, pwd->pw_uid, -1))
+ goto cleanup;
+
+cleanup:
+ krb5_free_creds(context, *creds);
+ return retval;
+}
+
+
+#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */
+/* helper function: convert flags to necessary KDC options */
+#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
+
+/* Get a TGT for use at the remote host */
+krb5_error_code INTERFACE
+get_for_creds(context, auth_context, rhost, client, forwardable, outbuf)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *rhost;
+ krb5_principal client;
+ int forwardable; /* Should forwarded TGT also be forwardable? */
+ krb5_data *outbuf;
+{
+ krb5_replay_data replaydata;
+ krb5_data * scratch;
+ struct hostent *hp;
+ krb5_address **addrs;
+ krb5_error_code retval;
+ krb5_error *err_reply;
+ krb5_creds creds, tgt;
+ krb5_creds *pcreds;
+ krb5_ccache cc;
+ krb5_flags kdcoptions;
+ krb5_timestamp now;
+ char *remote_host = 0;
+ char **hrealms = 0;
+ int i;
+
+ memset((char *)&creds, 0, sizeof(creds));
+
+ if (!rhost || !(hp = gethostbyname(rhost)))
+ return KRB5_ERR_BAD_HOSTNAME;
+
+ remote_host = (char *) malloc(strlen(hp->h_name)+1);
+ if (!remote_host) {
+ retval = ENOMEM;
+ goto errout;
+ }
+ strcpy(remote_host, hp->h_name);
+
+ if (retval = krb5_get_host_realm(context, remote_host, &hrealms))
+ goto errout;
+ if (!hrealms[0]) {
+ retval = KRB5_ERR_HOST_REALM_UNKNOWN;
+ goto errout;
}
- if (retval = krb5_cc_initialize(context, ccache,
- ticket->enc_part2->client)) {
- return(retval);
+ /* Count elements */
+ for(i=0; hp->h_addr_list[i]; i++);
+
+ addrs = (krb5_address **) malloc ((i+1)*sizeof(*addrs));
+ if (!addrs) {
+ retval = ENOMEM;
+ goto errout;
}
+ memset(addrs, 0, (i+1)*sizeof(*addrs));
+
+ for(i=0; hp->h_addr_list[i]; i++) {
+ addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
+ if (!addrs[i]) {
+ retval = ENOMEM;
+ goto errout;
+ }
+ addrs[i]->addrtype = hp->h_addrtype;
+ addrs[i]->length = hp->h_length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ retval = ENOMEM;
+ goto errout;
+ }
+ memcpy ((char *)addrs[i]->contents, hp->h_addr_list[i],
+ addrs[i]->length);
+ }
+ addrs[i] = 0;
- if (retval = krb5_cc_store_cred(context, ccache, &creds)) {
- return(retval);
+ if (retval = krb5_copy_principal(context, client, &creds.client))
+ goto errout;
+
+ if (retval = krb5_build_principal_ext(context, &creds.server,
+ strlen(hrealms[0]),
+ hrealms[0],
+ KRB5_TGS_NAME_SIZE,
+ KRB5_TGS_NAME,
+ client->realm.length,
+ client->realm.data,
+ 0))
+ goto errout;
+
+ creds.times.starttime = 0;
+ if (retval = krb5_timeofday(context, &now))
+ goto errout;
+
+ creds.times.endtime = now + KRB5_DEFAULT_LIFE;
+ creds.times.renew_till = 0;
+
+ if (retval = krb5_cc_default(context, &cc))
+ goto errout;
+
+ /* fetch tgt directly from cache */
+ retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_MATCH_SRV_NAMEONLY,
+ &creds, &tgt);
+ krb5_cc_close(context, cc);
+ if (retval)
+ goto errout;
+
+ /* tgt->client must be equal to creds.client */
+ if (!krb5_principal_compare(context, tgt.client, creds.client)) {
+ retval = KRB5_PRINC_NOMATCH;
+ goto errout;
}
- if (retval = chown(ccname+5, pwd->pw_uid, -1)) {
- return(retval);
+ if (!tgt.ticket.length) {
+ retval = KRB5_NO_TKT_SUPPLIED;
+ goto errout;
}
+ kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
+
+ if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
+ kdcoptions &= ~(KDC_OPT_FORWARDABLE);
+
+ if (retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
+ addrs, &creds, &pcreds))
+ goto errout;
+
+ retval = krb5_mk_1cred(context, auth_context, pcreds,
+ &scratch, &replaydata);
+ krb5_free_creds(context, pcreds);
+ *outbuf = *scratch;
+ krb5_xfree(scratch);
+
+errout:
+ if (remote_host)
+ free(remote_host);
+ if (hrealms)
+ krb5_xfree(hrealms);
+ if (addrs)
+ krb5_free_addresses(context, addrs);
+ krb5_free_cred_contents(context, &creds);
return retval;
}
#include "misc.h"
extern auth_debug_mode;
+extern int net;
#ifdef FORWARD
int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
ap_opts |= AP_OPTS_USE_SUBKEY;
#endif /* ENCRYPTION */
- auth_context = 0;
- r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
- NULL, new_creds, &auth);
+ if (r = krb5_auth_con_init(telnet_context, &auth_context)) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: failed to init auth_context (%s)\r\n",
+ error_message(r));
+ }
+ return(0);
+ }
+
+ krb5_auth_con_setflags(telnet_context, auth_context,
+ KRB5_AUTH_CONTEXT_RET_TIME);
+
+ r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
+ NULL, new_creds, &auth);
#ifdef ENCRYPTION
krb5_auth_con_getlocalsubkey(telnet_context, auth_context, &newkey);
break;
#ifdef FORWARD
case KRB_FORWARD:
- inbuf.data = (char *)data;
inbuf.length = cnt;
- if (r = rd_and_store_for_creds(telnet_context, &inbuf, ticket,
- UserNameRequested)) {
+ inbuf.data = (char *)data;
+ if ((r = krb5_auth_con_genaddrs(telnet_context, auth_context,
+ net, KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) ||
+ (r = rd_and_store_for_creds(telnet_context, auth_context,
+ &inbuf, ticket, UserNameRequested))) {
+
char errbuf[128];
(void) strcpy(errbuf, "Read forwarded creds failed: ");
}
#ifdef FORWARD
- void
+
+void
kerberos5_forward(ap)
Authenticator *ap;
{
- krb5_creds *local_creds, * new_creds;
krb5_error_code r;
- krb5_data forw_creds;
- extern krb5_cksumtype krb5_kdc_req_sumtype;
krb5_ccache ccache;
-
- if (!(local_creds = (krb5_creds *)
- calloc(1, sizeof(*local_creds)))) {
- if (auth_debug_mode)
- printf("Kerberos V5: could not allocate memory for credentials\r\n");
- return;
- }
-
- if (r = krb5_sname_to_principal(telnet_context, RemoteHostName, "host",
- KRB5_NT_SRV_HST, &local_creds->server)) {
- if (auth_debug_mode)
- printf("Kerberos V5: could not build server name - %s\r\n",
- error_message(r));
- krb5_free_creds(telnet_context, local_creds);
- return;
- }
-
- if (telnet_krb5_realm != NULL) {
- krb5_data rdata;
-
- rdata.length = strlen(telnet_krb5_realm);
- rdata.data = (char *) malloc(rdata.length + 1);
- if (rdata.data == NULL) {
- fprintf(stderr, "malloc failed\n");
- return;
- }
- strcpy(rdata.data, telnet_krb5_realm);
- krb5_princ_set_realm(telnet_context, local_creds->server, &rdata);
- }
+ krb5_principal client;
+ krb5_data forw_creds;
if (r = krb5_cc_default(telnet_context, &ccache)) {
if (auth_debug_mode)
- printf("Kerberos V5: could not get default ccache - %s\r\n",
- error_message(r));
- krb5_free_creds(telnet_context, local_creds);
+ printf("Kerberos V5: could not get default ccache - %s\r\n",
+ error_message(r));
return;
}
- if (r = krb5_cc_get_principal(telnet_context,ccache,&local_creds->client)) {
+ if (r = krb5_cc_get_principal(telnet_context, ccache, &client)) {
if (auth_debug_mode)
- printf("Kerberos V5: could not get default principal - %s\r\n",
- error_message(r));
- krb5_free_creds(telnet_context, local_creds);
+ printf("Kerberos V5: could not get default principal - %s\r\n",
+ error_message(r));
return;
}
- /* Get ticket from credentials cache */
- if (r = krb5_get_credentials(telnet_context, KRB5_GC_CACHED,
- ccache, local_creds, &new_creds)) {
- if (auth_debug_mode)
- printf("Kerberos V5: could not obtain credentials - %s\r\n",
- error_message(r));
- krb5_free_creds(telnet_context, local_creds);
- krb5_free_creds(telnet_context, new_creds);
+ if (r = krb5_auth_con_genaddrs(telnet_context, auth_context, net,
+ KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: could not gen local full address - %s\r\n",
+ error_message(r));
return;
}
- if (r = krb5_get_for_creds(telnet_context,
- krb5_kdc_req_sumtype,
- RemoteHostName,
- new_creds->client,
- &new_creds->keyblock,
- forward_flags & OPTS_FORWARDABLE_CREDS,
- &forw_creds)) {
+ if (r = get_for_creds(telnet_context, auth_context, RemoteHostName, client,
+ forward_flags & OPTS_FORWARDABLE_CREDS, &forw_creds)){
if (auth_debug_mode)
- printf("Kerberos V5: error getting forwarded creds - %s\r\n",
- error_message(r));
- krb5_free_creds(telnet_context, local_creds);
- krb5_free_creds(telnet_context, new_creds);
+ printf("Kerberos V5: error getting forwarded creds - %s\r\n",
+ error_message(r));
return;
}
/* Send forwarded credentials */
if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
if (auth_debug_mode)
- printf("Not enough room for authentication data\r\n");
- }
- else {
+ printf("Not enough room for authentication data\r\n");
+ } else {
if (auth_debug_mode)
- printf("Forwarded local Kerberos V5 credentials to server\r\n");
+ printf("Forwarded local Kerberos V5 credentials to server\r\n");
}
-
- krb5_free_creds(telnet_context, local_creds);
- krb5_free_creds(telnet_context, new_creds);
}
#endif /* FORWARD */