* forward.c (rd_and_store_for_creds()) : Rewritten to use
authorChris Provenzano <proven@mit.edu>
Wed, 26 Apr 1995 02:58:00 +0000 (02:58 +0000)
committerChris Provenzano <proven@mit.edu>
Wed, 26 Apr 1995 02:58:00 +0000 (02:58 +0000)
                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().

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5485 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/telnet/libtelnet/ChangeLog
src/appl/telnet/libtelnet/forward.c
src/appl/telnet/libtelnet/kerberos5.c

index a9a555b616c7c2a2e3d133e70e784b3f340fbf94..31aeb4c10864f58161e0cd6c1c5c3cafac766dc6 100644 (file)
@@ -1,3 +1,15 @@
+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 
index f80f6b15519543f91d7a0c71cf69645a998d9cca..ac42885cab6e95af3229ad4807d827bc91225d09 100644 (file)
 /* 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;
 }
 
index 5f1685e650a52165e6dbabf3bbde8aef5cdce0b5..af7a3cb4a9354af2912178ab245900f0899be6f7 100644 (file)
@@ -74,6 +74,7 @@
 #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 */
@@ -251,9 +252,19 @@ kerberos5_send(ap)
        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);
@@ -405,10 +416,13 @@ kerberos5_is(ap, data, cnt)
                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: ");
@@ -605,99 +619,54 @@ kerberos5_printsub(data, cnt, buf, buflen)
 }
 
 #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 */