krb5 commit [krb5-1.13]: Fix ksu crash in cases where it obtains the TGT

Tom Yu tlyu at mit.edu
Thu Sep 18 16:46:07 EDT 2014


https://github.com/krb5/krb5/commit/5ccab825a11b1c7f3edf4287d56202d00dd5b233
commit 5ccab825a11b1c7f3edf4287d56202d00dd5b233
Author: Nalin Dahyabhai <nalin at redhat.com>
Date:   Tue Sep 16 13:50:05 2014 -0400

    Fix ksu crash in cases where it obtains the TGT
    
    In order to allow ksu to use any locally-present service key for
    verifying creds, the previous change to ksu switched from using a
    retrieved or obtained TGT to fetch creds for the local "host" service,
    and then passing those creds to krb5_verify_init_creds(), to passing the
    retrieved TGT directly to krb5_verify_init_creds().
    
    It did not take care to retrieve the TGT from the temporary ccache if it
    had obtained them, and in those cases it would attempt to verify NULL
    creds.
    
    Modify the krb5_get_tkt_via_passwd() function to call
    krb5_get_init_creds_password(), to pass back the freshly-obtained creds,
    to take a "krb5_get_init_creds_opt" pointer instead of a locally-defined
    options structure, and rename it to ksu_get_tgt_via_passwd().
    
    (cherry picked from commit 5fd5a67c5a93514e7d0a64425baa007ad91f57de)
    
    ticket: 8015
    version_fixed: 1.13
    status: resolved

 src/clients/ksu/heuristic.c   |    4 +-
 src/clients/ksu/krb_auth_su.c |   58 ++++++++++++----------------------------
 src/clients/ksu/ksu.h         |   17 +++--------
 src/clients/ksu/main.c        |   56 ++++++++++++++++-----------------------
 4 files changed, 48 insertions(+), 87 deletions(-)

diff --git a/src/clients/ksu/heuristic.c b/src/clients/ksu/heuristic.c
index f73b8eb..0d055e4 100644
--- a/src/clients/ksu/heuristic.c
+++ b/src/clients/ksu/heuristic.c
@@ -527,7 +527,7 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid,
     char *source_user;
     char *target_user;
     krb5_ccache cc_source;
-    opt_info *options;
+    krb5_get_init_creds_opt *options;
     char *cmd;
     char *hostname;
     krb5_principal *client;
@@ -550,7 +550,7 @@ krb5_error_code get_best_princ_for_target(context, source_uid, target_uid,
     *path_out = 0;
 
     /* -n option was specified client is set we are done */
-    if (options->princ)
+    if (*client != NULL)
         return 0;
 
     if (ks_ccache_is_initialized(context, cc_source)) {
diff --git a/src/clients/ksu/krb_auth_su.c b/src/clients/ksu/krb_auth_su.c
index dd0a127..50dbefc 100644
--- a/src/clients/ksu/krb_auth_su.c
+++ b/src/clients/ksu/krb_auth_su.c
@@ -31,19 +31,12 @@
 
 void plain_dump_principal ();
 
-/*
- * Try no preauthentication first; then try the encrypted timestamp
- */
-krb5_preauthtype * preauth_ptr = NULL;
-
-
-
 krb5_boolean krb5_auth_check(context, client_pname, hostname, options,
                              target_user, cc, path_passwd, target_uid)
     krb5_context context;
     krb5_principal client_pname;
     char *hostname;
-    opt_info *options;
+    krb5_get_init_creds_opt *options;
     char *target_user;
     uid_t target_uid;
     krb5_ccache cc;
@@ -109,9 +102,9 @@ krb5_boolean krb5_auth_check(context, client_pname, hostname, options,
         fprintf(stderr, _("         in remotely using an unsecure "
                           "(non-encrypted) channel. \n"));
 
-        /*get the ticket granting ticket, via passwd(promt for passwd)*/
-        if (krb5_get_tkt_via_passwd (context, &cc, client, tgtq.server,
-                                     options, & zero_password) == FALSE){
+        /*get the ticket granting ticket, via passwd(prompt for passwd)*/
+        if (ksu_get_tgt_via_passwd(context, client, options, &zero_password,
+                                   &tgt) == FALSE) {
             krb5_seteuid(0);
 
             return FALSE;
@@ -144,55 +137,37 @@ krb5_boolean krb5_auth_check(context, client_pname, hostname, options,
     return (TRUE);
 }
 
-krb5_boolean krb5_get_tkt_via_passwd (context, ccache, client, server,
-                                      options, zero_password)
+krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password,
+                                    creds_out)
     krb5_context context;
-    krb5_ccache *ccache;
     krb5_principal client;
-    krb5_principal server;
-    opt_info *options;
+    krb5_get_init_creds_opt *options;
     krb5_boolean *zero_password;
+    krb5_creds *creds_out;
 {
     krb5_error_code code;
-    krb5_creds my_creds;
+    krb5_creds creds;
     krb5_timestamp now;
     unsigned int pwsize;
     char password[255], *client_name, prompt[255];
     int result;
 
     *zero_password = FALSE;
+    if (creds_out != NULL)
+        memset(creds_out, 0, sizeof(*creds_out));
 
     if ((code = krb5_unparse_name(context, client, &client_name))) {
         com_err (prog_name, code, _("when unparsing name"));
         return (FALSE);
     }
 
-    memset(&my_creds, 0, sizeof(my_creds));
-
-    if ((code = krb5_copy_principal(context, client, &my_creds.client))){
-        com_err (prog_name, code, _("while copying principal"));
-        return (FALSE);
-    }
-
-    if ((code = krb5_copy_principal(context, server, &my_creds.server))){
-        com_err (prog_name, code, _("while copying principal"));
-        return (FALSE);
-    }
+    memset(&creds, 0, sizeof(creds));
 
     if ((code = krb5_timeofday(context, &now))) {
         com_err(prog_name, code, _("while getting time of day"));
         return (FALSE);
     }
 
-    my_creds.times.starttime = 0;       /* start timer when request
-                                           gets to KDC */
-
-    my_creds.times.endtime = now + options->lifetime;
-    if (options->opt & KDC_OPT_RENEWABLE) {
-        my_creds.times.renew_till = now + options->rlife;
-    } else
-        my_creds.times.renew_till = 0;
-
     result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "),
                       client_name);
     if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) {
@@ -219,9 +194,8 @@ krb5_boolean krb5_get_tkt_via_passwd (context, ccache, client, server,
         return (FALSE);
     }
 
-    code = krb5_get_in_tkt_with_password(context, options->opt,
-                                         0, NULL, preauth_ptr,
-                                         password, *ccache, &my_creds, 0);
+    code = krb5_get_init_creds_password(context, &creds, client, password,
+                                        NULL, NULL, 0, NULL, options);
     memset(password, 0, sizeof(password));
 
 
@@ -232,6 +206,10 @@ krb5_boolean krb5_get_tkt_via_passwd (context, ccache, client, server,
             com_err(prog_name, code, _("while getting initial credentials"));
         return (FALSE);
     }
+    if (creds_out != NULL)
+        *creds_out = creds;
+    else
+        krb5_free_cred_contents(context, &creds);
     return (TRUE);
 }
 
diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h
index 5ba5ceb..ee8e9d6 100644
--- a/src/clients/ksu/ksu.h
+++ b/src/clients/ksu/ksu.h
@@ -69,25 +69,18 @@ extern char k5users_path[MAXPATHLEN];
 extern char * gb_err;
 /***********/
 
-typedef struct opt_info{
-    int opt;
-    krb5_deltat lifetime;
-    krb5_deltat rlife;
-    int princ;
-}opt_info;
-
 /* krb_auth_su.c */
 extern krb5_boolean krb5_auth_check
-(krb5_context, krb5_principal, char *, opt_info *,
+(krb5_context, krb5_principal, char *, krb5_get_init_creds_opt *,
  char *, krb5_ccache, int *, uid_t);
 
 extern krb5_boolean krb5_fast_auth
 (krb5_context, krb5_principal, krb5_principal, char *,
  krb5_ccache);
 
-extern krb5_boolean krb5_get_tkt_via_passwd
-(krb5_context, krb5_ccache *, krb5_principal,
- krb5_principal, opt_info *, krb5_boolean *);
+extern krb5_boolean ksu_get_tgt_via_passwd
+(krb5_context,
+ krb5_principal, krb5_get_init_creds_opt *, krb5_boolean *, krb5_creds *);
 
 extern void dump_principal
 (krb5_context, char *, krb5_principal);
@@ -229,7 +222,7 @@ extern krb5_error_code find_princ_in_list
 
 extern krb5_error_code get_best_princ_for_target
 (krb5_context, uid_t, uid_t, char *, char *, krb5_ccache,
- opt_info *, char *, char *, krb5_principal *, int *);
+ krb5_get_init_creds_opt *, char *, char *, krb5_principal *, int *);
 
 extern krb5_error_code ksu_tgtname (krb5_context, const krb5_data *,
                                     const krb5_data *,
diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
index 622c36a..0492e38 100644
--- a/src/clients/ksu/main.c
+++ b/src/clients/ksu/main.c
@@ -87,7 +87,7 @@ main (argc, argv)
     int some_rest_copy = 0;
     int all_rest_copy = 0;
     char *localhostname = NULL;
-    opt_info options;
+    krb5_get_init_creds_opt *options = NULL;
     int option=0;
     int statusp=0;
     krb5_error_code retval = 0;
@@ -117,19 +117,13 @@ main (argc, argv)
     int pargc;
     char ** pargv;
     krb5_boolean stored = FALSE, cc_reused = FALSE;
-    krb5_principal  kdc_server;
     krb5_boolean zero_password;
     krb5_boolean restrict_creds;
-
-    options.opt = KRB5_DEFAULT_OPTIONS;
-    options.lifetime = KRB5_DEFAULT_TKT_LIFE;
-    options.rlife =0;
-    options.princ =0;
+    krb5_deltat lifetime, rlife;
 
     params = (char **) xcalloc (2, sizeof (char *));
     params[1] = NULL;
 
-
     unsetenv ("KRB5_CONFIG");
 
     retval = krb5_init_secure_context(&ksu_context);
@@ -138,6 +132,12 @@ main (argc, argv)
         exit(1);
     }
 
+    retval = krb5_get_init_creds_opt_alloc(ksu_context, &options);
+    if (retval) {
+        com_err(argv[0], retval, _("while initializing krb5"));
+        exit(1);
+    }
+
     if (strrchr(argv[0], '/'))
         argv[0] = strrchr(argv[0], '/')+1;
     prog_name = argv[0];
@@ -189,14 +189,14 @@ main (argc, argv)
     while(!done && ((option = getopt(pargc, pargv,"n:c:r:a:zZDfpkql:e:")) != -1)){
         switch (option) {
         case 'r':
-            options.opt |= KDC_OPT_RENEWABLE;
             if (strlen (optarg) >= 14)
                 optarg = "bad-time";
-            retval = krb5_string_to_deltat(optarg, &options.rlife);
-            if (retval != 0 || options.rlife == 0) {
+            retval = krb5_string_to_deltat(optarg, &rlife);
+            if (retval != 0 || rlife == 0) {
                 fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
                 errflg++;
             }
+            krb5_get_init_creds_opt_set_renew_life(options, rlife);
             break;
         case 'a':
             /* when integrating this remember to pass in pargc, pargv and
@@ -212,10 +212,10 @@ main (argc, argv)
             done = 1;
             break;
         case 'p':
-            options.opt |= KDC_OPT_PROXIABLE;
+            krb5_get_init_creds_opt_set_proxiable(options, 1);
             break;
         case 'f':
-            options.opt |= KDC_OPT_FORWARDABLE;
+            krb5_get_init_creds_opt_set_forwardable(options, 1);
             break;
         case 'k':
             keep_target_cache =1;
@@ -226,20 +226,18 @@ main (argc, argv)
         case 'l':
             if (strlen (optarg) >= 14)
                 optarg = "bad-time";
-            retval = krb5_string_to_deltat(optarg, &options.lifetime);
-            if (retval != 0 || options.lifetime == 0) {
+            retval = krb5_string_to_deltat(optarg, &lifetime);
+            if (retval != 0 || lifetime == 0) {
                 fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
                 errflg++;
             }
+            krb5_get_init_creds_opt_set_tkt_life(options, lifetime);
             break;
         case 'n':
             if ((retval = krb5_parse_name(ksu_context, optarg, &client))){
                 com_err(prog_name, retval, _("when parsing name %s"), optarg);
                 errflg++;
             }
-
-            options.princ = 1;
-
             break;
 #ifdef DEBUG
         case 'D':
@@ -386,7 +384,7 @@ main (argc, argv)
     if ((retval = get_best_princ_for_target(ksu_context, source_uid,
                                             target_uid, source_user,
                                             target_user, cc_source,
-                                            &options, cmd, localhostname,
+                                            options, cmd, localhostname,
                                             &client, &hp))){
         com_err(prog_name,retval, _("while selecting the best principal"));
         exit(1);
@@ -458,6 +456,8 @@ main (argc, argv)
     }
     krb5_cc_close(ksu_context, cc_source);
 
+    krb5_get_init_creds_opt_set_out_ccache(ksu_context, options, cc_tmp);
+
     /* Become root for authentication*/
 
     if (krb5_seteuid(0)) {
@@ -467,23 +467,13 @@ main (argc, argv)
 
     if ((source_uid == 0) || (target_uid == source_uid)){
 #ifdef GET_TGT_VIA_PASSWD
-        if ((!all_rest_copy) && options.princ && (stored == FALSE)){
-            if ((retval = ksu_tgtname(ksu_context,
-                                      krb5_princ_realm (ksu_context, client),
-                                      krb5_princ_realm(ksu_context, client),
-                                      &kdc_server))){
-                com_err(prog_name, retval,
-                        _("while creating tgt for local realm"));
-                exit(1);
-            }
-
+        if ((!all_rest_copy) && client != NULL && (stored == FALSE)){
             fprintf(stderr, _("WARNING: Your password may be exposed if you "
                               "enter it here and are logged\n"));
             fprintf(stderr, _("         in remotely using an unsecure "
                               "(non-encrypted) channel.\n"));
-            if (krb5_get_tkt_via_passwd(ksu_context, &cc_tmp, client,
-                                        kdc_server, &options,
-                                        &zero_password) == FALSE){
+            if (ksu_get_tgt_via_passwd(ksu_context, client, options,
+                                       &zero_password, NULL) == FALSE) {
 
                 if (zero_password == FALSE){
                     fprintf(stderr, _("Goodbye\n"));
@@ -506,7 +496,7 @@ main (argc, argv)
         char * client_name;
 
         auth_val = krb5_auth_check(ksu_context, client, localhostname,
-                                   &options, target_user, cc_tmp,
+                                   options, target_user, cc_tmp,
                                    &path_passwd, target_uid);
 
         /* if Kerberos authentication failed then exit */


More information about the cvs-krb5 mailing list