]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Fix ksu crash in cases where it obtains the TGT
authorNalin Dahyabhai <nalin@redhat.com>
Tue, 16 Sep 2014 17:50:05 +0000 (13:50 -0400)
committerGreg Hudson <ghudson@mit.edu>
Thu, 18 Sep 2014 19:26:21 +0000 (15:26 -0400)
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().

ticket: 8015 (new)
target_version: 1.13
tags: pullup

src/clients/ksu/heuristic.c
src/clients/ksu/krb_auth_su.c
src/clients/ksu/ksu.h
src/clients/ksu/main.c

index f73b8eb52f3c36436511cb34e5c8a6d3977e747b..0d055e471c54e63d7e0e152bc9da63a4b090d65e 100644 (file)
@@ -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)) {
index dd0a1272c5ca545cd2333761b9e0b3ce1c6e093d..50dbefc06bfb0d92a9e9ce746084e52d12b8cb3e 100644 (file)
 
 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);
 }
 
index 5ba5cebc8c1310381f650b37220f3c2e2b961afb..ee8e9d6a0f798050e20a578fea89ee82978a1a34 100644 (file)
@@ -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 *,
index 622c36af4a2b8bbdd8f548aa6375d4984ca41859..0492e38af8fe84366e8b1689084d698ab009f647 100644 (file)
@@ -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 */