Merge from vendor branch FILE:
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / krb5 / mk_req_ext.c
1 /*
2  * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright 
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the distribution. 
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors 
18  *    may be used to endorse or promote products derived from this software 
19  *    without specific prior written permission. 
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31  * SUCH DAMAGE. 
32  */
33
34 #include <krb5_locl.h>
35
36 RCSID("$Id: mk_req_ext.c,v 1.26.4.1 2003/09/18 20:34:30 lha Exp $");
37
38 krb5_error_code
39 krb5_mk_req_internal(krb5_context context,
40                      krb5_auth_context *auth_context,
41                      const krb5_flags ap_req_options,
42                      krb5_data *in_data,
43                      krb5_creds *in_creds,
44                      krb5_data *outbuf,
45                      krb5_key_usage checksum_usage,
46                      krb5_key_usage encrypt_usage)
47 {
48   krb5_error_code ret;
49   krb5_data authenticator;
50   Checksum c;
51   Checksum *c_opt;
52   krb5_auth_context ac;
53
54   if(auth_context) {
55       if(*auth_context == NULL)
56           ret = krb5_auth_con_init(context, auth_context);
57       else
58           ret = 0;
59       ac = *auth_context;
60   } else
61       ret = krb5_auth_con_init(context, &ac);
62   if(ret)
63       return ret;
64       
65   if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
66       ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session);
67       if(ret)
68           return ret;
69   }
70
71 #if 0
72   {
73       /* This is somewhat bogus since we're possibly overwriting a
74          value specified by the user, but it's the easiest way to make
75          the code use a compatible enctype */
76       Ticket ticket;
77       krb5_keytype ticket_keytype;
78
79       ret = decode_Ticket(in_creds->ticket.data, 
80                           in_creds->ticket.length, 
81                           &ticket, 
82                           NULL);
83       krb5_enctype_to_keytype (context,
84                                ticket.enc_part.etype,
85                                &ticket_keytype);
86
87       if (ticket_keytype == in_creds->session.keytype)
88           krb5_auth_setenctype(context, 
89                                ac,
90                                ticket.enc_part.etype);
91       free_Ticket(&ticket);
92   }
93 #endif
94
95   krb5_free_keyblock(context, ac->keyblock);
96   krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
97   
98   /* it's unclear what type of checksum we can use.  try the best one, except:
99    * a) if it's configured differently for the current realm, or
100    * b) if the session key is des-cbc-crc
101    */
102
103   if (in_data) {
104       if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) {
105           /* this is to make DCE secd (and older MIT kdcs?) happy */
106           ret = krb5_create_checksum(context, 
107                                      NULL,
108                                      0,
109                                      CKSUMTYPE_RSA_MD4,
110                                      in_data->data,
111                                      in_data->length,
112                                      &c);
113       } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5) {
114           /* this is to make MS kdc happy */ 
115           ret = krb5_create_checksum(context, 
116                                      NULL,
117                                      0,
118                                      CKSUMTYPE_RSA_MD5,
119                                      in_data->data,
120                                      in_data->length,
121                                      &c);
122       } else {
123           krb5_crypto crypto;
124
125           ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
126           if (ret)
127               return ret;
128           ret = krb5_create_checksum(context, 
129                                      crypto,
130                                      checksum_usage,
131                                      0,
132                                      in_data->data,
133                                      in_data->length,
134                                      &c);
135       
136           krb5_crypto_destroy(context, crypto);
137       }
138       c_opt = &c;
139   } else {
140       c_opt = NULL;
141   }
142   
143   ret = krb5_build_authenticator (context,
144                                   ac,
145                                   ac->keyblock->keytype,
146                                   in_creds,
147                                   c_opt,
148                                   NULL,
149                                   &authenticator,
150                                   encrypt_usage);
151   if (c_opt)
152       free_Checksum (c_opt);
153   if (ret)
154     return ret;
155
156   ret = krb5_build_ap_req (context, ac->keyblock->keytype, 
157                            in_creds, ap_req_options, authenticator, outbuf);
158   if(auth_context == NULL)
159       krb5_auth_con_free(context, ac);
160   return ret;
161 }
162
163 krb5_error_code
164 krb5_mk_req_extended(krb5_context context,
165                      krb5_auth_context *auth_context,
166                      const krb5_flags ap_req_options,
167                      krb5_data *in_data,
168                      krb5_creds *in_creds,
169                      krb5_data *outbuf)
170 {
171     return krb5_mk_req_internal (context,
172                                  auth_context,
173                                  ap_req_options,
174                                  in_data,
175                                  in_creds,
176                                  outbuf,
177                                  KRB5_KU_AP_REQ_AUTH_CKSUM,
178                                  KRB5_KU_AP_REQ_AUTH);
179 }