This commit was manufactured by cvs2svn to create tag
[krb5.git] / src / lib / krb5 / krb / get_in_tkt.c
index 86978f3602a046c85c5551d455e66363d56c1a78..298f1528f025f8a5fb6861d941a8c7a0f2fc29f6 100644 (file)
@@ -84,13 +84,13 @@ static krb5_error_code make_preauth_list PROTOTYPE((krb5_context,
  */
 static krb5_error_code
 send_as_request(context, request, time_now, ret_err_reply, ret_as_reply,
-               master)
+               use_master)
     krb5_context               context;
     krb5_kdc_req               *request;
     krb5_timestamp             *time_now;
     krb5_error **              ret_err_reply;
     krb5_kdc_rep **            ret_as_reply;
-    int *                      master;
+    int                        use_master;
 {
     krb5_kdc_rep *as_reply = 0;
     krb5_error_code retval;
@@ -116,7 +116,7 @@ send_as_request(context, request, time_now, ret_err_reply, ret_as_reply,
     k4_version = packet->data[0];
     retval = krb5_sendto_kdc(context, packet, 
                             krb5_princ_realm(context, request->client),
-                            &reply, master);
+                            &reply, use_master);
     krb5_free_data(context, packet);
     if (retval)
        goto cleanup;
@@ -457,12 +457,35 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed,
     request.from = creds->times.starttime;
     request.till = creds->times.endtime;
     request.rtime = creds->times.renew_till;
-    if (ktypes)
-       request.ktype = ktypes;
-    else
-       if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype)))
-           goto cleanup;
+    if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype)))
+       goto cleanup;
     for (request.nktypes = 0;request.ktype[request.nktypes];request.nktypes++);
+    if (ktypes) {
+       int i, req, next = 0;
+       for (req = 0; ktypes[req]; req++) {
+           if (ktypes[req] == request.ktype[next]) {
+               next++;
+               continue;
+           }
+           for (i = next + 1; i < request.nktypes; i++)
+               if (ktypes[req] == request.ktype[i]) {
+                   /* Found the enctype we want, but not in the
+                      position we want.  Move it, but keep the old
+                      one from the desired slot around in case it's
+                      later in our requested-ktypes list.  */
+                   krb5_enctype t;
+                   t = request.ktype[next];
+                   request.ktype[next] = request.ktype[i];
+                   request.ktype[i] = t;
+                   next++;
+                   break;
+               }
+           /* If we didn't find it, don't do anything special, just
+              drop it.  */
+       }
+       request.ktype[next] = 0;
+       request.nktypes = next;
+    }
     request.authorization_data.ciphertext.length = 0;
     request.authorization_data.ciphertext.data = 0;
     request.unenc_authdata = 0;
@@ -538,7 +561,7 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed,
        goto cleanup;
 
 cleanup:
-    if (!ktypes && request.ktype)
+    if (request.ktype)
        free(request.ktype);
     if (!addrs && request.addresses)
        krb5_free_addresses(context, request.addresses);
@@ -559,7 +582,7 @@ cleanup:
     return (retval);
 }
 
-/* begin appdefaults parsing code.  This should almost certainly move
+/* begin libdefaults parsing code.  This should almost certainly move
    somewhere else, but I don't know where the correct somewhere else
    is yet. */
 
@@ -595,7 +618,7 @@ _krb5_conf_boolean(s)
 }
 
 static krb5_error_code
-krb5_appdefault_string(context, realm, option, ret_value)
+krb5_libdefault_string(context, realm, option, ret_value)
      krb5_context context;
      const krb5_data *realm;
      const char *option;
@@ -673,7 +696,7 @@ goodbye:
 /* as well as the DNS code */
 
 krb5_error_code
-krb5_appdefault_boolean(context, realm, option, ret_value)
+krb5_libdefault_boolean(context, realm, option, ret_value)
      krb5_context context;
      const char *option;
      const krb5_data *realm;
@@ -682,7 +705,7 @@ krb5_appdefault_boolean(context, realm, option, ret_value)
     char *string = NULL;
     krb5_error_code retval;
 
-    retval = krb5_appdefault_string(context, realm, option, &string);
+    retval = krb5_libdefault_string(context, realm, option, &string);
 
     if (retval)
        return(retval);
@@ -696,7 +719,7 @@ krb5_appdefault_boolean(context, realm, option, ret_value)
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 krb5_get_init_creds(context, creds, client, prompter, prompter_data,
                    start_time, in_tkt_service, options, gak_fct, gak_data,
-                   master, as_reply)
+                   use_master, as_reply)
      krb5_context context;
      krb5_creds *creds;
      krb5_principal client;
@@ -707,7 +730,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
      krb5_get_init_creds_opt *options;
      krb5_gic_get_as_key_fct gak_fct;
      void *gak_data;
-     int *master;
+     int  use_master;
      krb5_kdc_rep **as_reply;
 {
     krb5_error_code ret;
@@ -722,6 +745,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
     krb5_error *err_reply;
     krb5_kdc_rep *local_as_reply;
     krb5_timestamp time_now;
+    krb5_enctype etype = 0;
 
     /* initialize everything which will be freed at cleanup */
 
@@ -734,6 +758,8 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
     salt.length = 0;
     salt.data = NULL;
 
+       local_as_reply = 0;
+
     /*
      * Set up the basic request structure
      */
@@ -748,7 +774,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
 
     if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE))
        tempint = options->forwardable;
-    else if ((ret = krb5_appdefault_boolean(context, &client->realm,
+    else if ((ret = krb5_libdefault_boolean(context, &client->realm,
                                            "forwardable", &tempint)) == 0)
            ;
     else
@@ -760,7 +786,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
 
     if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE))
        tempint = options->proxiable;
-    else if ((ret = krb5_appdefault_boolean(context, &client->realm,
+    else if ((ret = krb5_libdefault_boolean(context, &client->realm,
                                            "proxiable", &tempint)) == 0)
            ;
     else
@@ -772,7 +798,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
 
     if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)) {
        renew_life = options->renew_life;
-    } else if ((ret = krb5_appdefault_string(context, &client->realm,
+    } else if ((ret = krb5_libdefault_string(context, &client->realm,
                                             "renew_lifetime", &tempstr))
               == 0) {
        if (ret = krb5_string_to_deltat(tempstr, &renew_life)) {
@@ -865,7 +891,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
     }
     /* it would be nice if this parsed out an address list, but
        that would be work. */
-    else if (((ret = krb5_appdefault_boolean(context, &client->realm,
+    else if (((ret = krb5_libdefault_boolean(context, &client->realm,
                                            "noaddresses", &tempint)) == 0)
             && tempint) {
            ;
@@ -908,7 +934,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
 
        if (ret = krb5_do_preauth(context, &request,
                                  padata, &request.padata,
-                                 &salt, &as_key, prompter,
+                                 &salt, &etype, &as_key, prompter,
                                  prompter_data, gak_fct, gak_data))
            goto cleanup;
 
@@ -920,7 +946,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
        err_reply = 0;
        local_as_reply = 0;
        if ((ret = send_as_request(context, &request, &time_now, &err_reply,
-                                  &local_as_reply, master)))
+                                  &local_as_reply, use_master)))
            goto cleanup;
 
        if (err_reply) {
@@ -953,13 +979,19 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data,
 
     if (ret = krb5_do_preauth(context, &request,
                              local_as_reply->padata, &padata,
-                             &salt, &as_key, prompter,
+                             &salt, &etype, &as_key, prompter,
                              prompter_data, gak_fct, gak_data))
        goto cleanup;
 
     /* XXX if there's padata on output, something is wrong, but it's
        not obviously an error */
 
+    /* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY,
+       the AS_REP comes back encrypted in the user's longterm key
+       instead of in the SAD. If there was a SAM preauth, there
+       will be an as_key here which will be the SAD. If that fails,
+       use the gak_fct to get the password, and try again. */
+      
     /* XXX because etypes are handled poorly (particularly wrt SAM,
        where the etype is fixed by the kdc), we may want to try
        decrypt_as_reply twice.  If there's an as_key available, try