155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 2002 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
34233294Sstas#include "krb5_locl.h"
3555682Smarkm
3655682Smarkmkrb5_error_code
37178825Sdfr_krb5_mk_req_internal(krb5_context context,
38178825Sdfr		      krb5_auth_context *auth_context,
39178825Sdfr		      const krb5_flags ap_req_options,
40178825Sdfr		      krb5_data *in_data,
41178825Sdfr		      krb5_creds *in_creds,
42178825Sdfr		      krb5_data *outbuf,
43178825Sdfr		      krb5_key_usage checksum_usage,
44178825Sdfr		      krb5_key_usage encrypt_usage)
4555682Smarkm{
46178825Sdfr    krb5_error_code ret;
47178825Sdfr    krb5_data authenticator;
48178825Sdfr    Checksum c;
49178825Sdfr    Checksum *c_opt;
50178825Sdfr    krb5_auth_context ac;
5155682Smarkm
52178825Sdfr    if(auth_context) {
53178825Sdfr	if(*auth_context == NULL)
54178825Sdfr	    ret = krb5_auth_con_init(context, auth_context);
55178825Sdfr	else
56178825Sdfr	    ret = 0;
57178825Sdfr	ac = *auth_context;
58178825Sdfr    } else
59178825Sdfr	ret = krb5_auth_con_init(context, &ac);
60178825Sdfr    if(ret)
61178825Sdfr	return ret;
62233294Sstas
63178825Sdfr    if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
64178825Sdfr	ret = krb5_auth_con_generatelocalsubkey(context,
65233294Sstas						ac,
66178825Sdfr						&in_creds->session);
67178825Sdfr	if(ret)
68178825Sdfr	    goto out;
69178825Sdfr    }
70103423Snectar
71178825Sdfr    krb5_free_keyblock(context, ac->keyblock);
72178825Sdfr    ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
73178825Sdfr    if (ret)
74178825Sdfr	goto out;
75233294Sstas
76178825Sdfr    /* it's unclear what type of checksum we can use.  try the best one, except:
77178825Sdfr     * a) if it's configured differently for the current realm, or
78178825Sdfr     * b) if the session key is des-cbc-crc
79178825Sdfr     */
8055682Smarkm
81178825Sdfr    if (in_data) {
82178825Sdfr	if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) {
83178825Sdfr	    /* this is to make DCE secd (and older MIT kdcs?) happy */
84233294Sstas	    ret = krb5_create_checksum(context,
85178825Sdfr				       NULL,
86178825Sdfr				       0,
87178825Sdfr				       CKSUMTYPE_RSA_MD4,
88178825Sdfr				       in_data->data,
89178825Sdfr				       in_data->length,
90178825Sdfr				       &c);
91178825Sdfr	} else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
92178825Sdfr		  ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56 ||
93178825Sdfr		  ac->keyblock->keytype == ETYPE_DES_CBC_MD4 ||
94178825Sdfr		  ac->keyblock->keytype == ETYPE_DES_CBC_MD5) {
95233294Sstas	    /* this is to make MS kdc happy */
96233294Sstas	    ret = krb5_create_checksum(context,
97178825Sdfr				       NULL,
98178825Sdfr				       0,
99178825Sdfr				       CKSUMTYPE_RSA_MD5,
100178825Sdfr				       in_data->data,
101178825Sdfr				       in_data->length,
102178825Sdfr				       &c);
103178825Sdfr	} else {
104178825Sdfr	    krb5_crypto crypto;
10555682Smarkm
106178825Sdfr	    ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
107178825Sdfr	    if (ret)
108178825Sdfr		goto out;
109233294Sstas	    ret = krb5_create_checksum(context,
110178825Sdfr				       crypto,
111178825Sdfr				       checksum_usage,
112178825Sdfr				       0,
113178825Sdfr				       in_data->data,
114178825Sdfr				       in_data->length,
115178825Sdfr				       &c);
116178825Sdfr	    krb5_crypto_destroy(context, crypto);
117178825Sdfr	}
118178825Sdfr	c_opt = &c;
119178825Sdfr    } else {
120178825Sdfr	c_opt = NULL;
121178825Sdfr    }
12255682Smarkm
123178825Sdfr    if (ret)
124178825Sdfr	goto out;
125233294Sstas
126233294Sstas    ret = _krb5_build_authenticator(context,
127178825Sdfr				    ac,
128178825Sdfr				    ac->keyblock->keytype,
129178825Sdfr				    in_creds,
130178825Sdfr				    c_opt,
131178825Sdfr				    &authenticator,
132178825Sdfr				    encrypt_usage);
133178825Sdfr    if (c_opt)
134178825Sdfr	free_Checksum (c_opt);
135178825Sdfr    if (ret)
136178825Sdfr	goto out;
13772445Sassar
138233294Sstas    ret = krb5_build_ap_req (context, ac->keyblock->keytype,
139178825Sdfr			     in_creds, ap_req_options, authenticator, outbuf);
140178825Sdfrout:
141178825Sdfr    if(auth_context == NULL)
142178825Sdfr	krb5_auth_con_free(context, ac);
14355682Smarkm    return ret;
14455682Smarkm}
14555682Smarkm
146233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
14755682Smarkmkrb5_mk_req_extended(krb5_context context,
14855682Smarkm		     krb5_auth_context *auth_context,
14955682Smarkm		     const krb5_flags ap_req_options,
15055682Smarkm		     krb5_data *in_data,
15155682Smarkm		     krb5_creds *in_creds,
15255682Smarkm		     krb5_data *outbuf)
15355682Smarkm{
154178825Sdfr    return _krb5_mk_req_internal (context,
15555682Smarkm				 auth_context,
15655682Smarkm				 ap_req_options,
15755682Smarkm				 in_data,
15855682Smarkm				 in_creds,
15955682Smarkm				 outbuf,
16072445Sassar				 KRB5_KU_AP_REQ_AUTH_CKSUM,
16172445Sassar				 KRB5_KU_AP_REQ_AUTH);
16255682Smarkm}
163