This commit was manufactured by cvs2svn to create tag
[krb5.git] / src / lib / krb5 / krb / get_in_tkt.c
index 679ecc492d984c49668979c955778490054b362e..298f1528f025f8a5fb6861d941a8c7a0f2fc29f6 100644 (file)
  * this permission notice appear in supporting documentation, and that
  * the name of M.I.T. not be used in advertising or publicity pertaining
  * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
  * 
@@ -81,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;
@@ -113,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;
@@ -454,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;
@@ -535,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);
@@ -571,7 +597,8 @@ static char *conf_no[] = {
     0,
 };
 
-static int conf_boolean(s)
+int
+_krb5_conf_boolean(s)
      char *s;
 {
     char **p;
@@ -591,7 +618,7 @@ static int 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;
@@ -651,24 +678,25 @@ goodbye:
        return(ENOENT);
 
     if (!nameval[0]) {
-       free(nameval);
-       return(ENOENT);
+        retval = ENOENT;
+    } else {
+        *ret_value = malloc(strlen(nameval[0]) + 1);
+        if (!*ret_value)
+            retval = ENOMEM;
+        else
+            strcpy(*ret_value, nameval[0]);
     }
 
-    *ret_value = nameval[0];
-
-    for (cpp = &nameval[1]; *cpp; cpp++)
-       free(*cpp);
+    profile_free_list(nameval);
 
-    free(nameval);
-
-    return 0;
+    return retval;
 }
 
 /* not static so verify_init_creds() can call it */
+/* 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;
@@ -677,12 +705,12 @@ 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);
 
-    *ret_value = conf_boolean(string);
+    *ret_value = _krb5_conf_boolean(string);
     free(string);
 
     return(0);
@@ -691,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;
@@ -702,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;
@@ -717,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 */
 
@@ -729,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
      */
@@ -743,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
@@ -755,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
@@ -767,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)) {
@@ -860,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) {
            ;
@@ -903,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;
 
@@ -915,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) {
@@ -948,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