xref: /freebsd/crypto/heimdal/lib/krb5/rd_cred.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
1 /*
2  * Copyright (c) 1997 - 2000 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: rd_cred.c,v 1.9 2000/02/06 05:19:52 assar Exp $");
37 
38 krb5_error_code
39 krb5_rd_cred (krb5_context      context,
40 	      krb5_auth_context auth_context,
41 	      krb5_ccache       ccache,
42 	      krb5_data         *in_data)
43 {
44     krb5_error_code ret;
45     size_t len;
46     KRB_CRED cred;
47     EncKrbCredPart enc_krb_cred_part;
48     krb5_data enc_krb_cred_part_data;
49     krb5_crypto crypto;
50     int i;
51 
52     ret = decode_KRB_CRED (in_data->data, in_data->length,
53 			   &cred, &len);
54     if (ret)
55 	return ret;
56 
57     if (cred.pvno != 5) {
58 	ret = KRB5KRB_AP_ERR_BADVERSION;
59 	goto out;
60     }
61 
62     if (cred.msg_type != krb_cred) {
63 	ret = KRB5KRB_AP_ERR_MSG_TYPE;
64 	goto out;
65     }
66 
67     krb5_crypto_init(context, auth_context->remote_subkey, 0, &crypto);
68     ret = krb5_decrypt_EncryptedData(context,
69 				     crypto,
70 				     KRB5_KU_KRB_CRED,
71 				     &cred.enc_part,
72 				     &enc_krb_cred_part_data);
73     krb5_crypto_destroy(context, crypto);
74     if (ret)
75 	goto out;
76 
77 
78     ret = krb5_decode_EncKrbCredPart (context,
79 				      enc_krb_cred_part_data.data,
80 				      enc_krb_cred_part_data.length,
81 				      &enc_krb_cred_part,
82 				      &len);
83     if (ret)
84 	goto out;
85 
86     /* check sender address */
87 
88     if (enc_krb_cred_part.s_address
89 	&& auth_context->remote_address) {
90 	krb5_address *a;
91 	int cmp;
92 
93 	ret = krb5_make_addrport (&a,
94 				  auth_context->remote_address,
95 				  auth_context->remote_port);
96 	if (ret)
97 	    goto out;
98 
99 
100 	cmp = krb5_address_compare (context,
101 				    a,
102 				    enc_krb_cred_part.s_address);
103 
104 	krb5_free_address (context, a);
105 	free (a);
106 
107 	if (cmp == 0) {
108 	    ret = KRB5KRB_AP_ERR_BADADDR;
109 	    goto out;
110 	}
111     }
112 
113     /* check receiver address */
114 
115     if (enc_krb_cred_part.r_address
116 	&& !krb5_address_compare (context,
117 				  auth_context->local_address,
118 				  enc_krb_cred_part.r_address)) {
119 	ret = KRB5KRB_AP_ERR_BADADDR;
120 	goto out;
121     }
122 
123     /* check timestamp */
124     if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
125 	krb5_timestamp sec;
126 
127 	krb5_timeofday (context, &sec);
128 
129 	if (enc_krb_cred_part.timestamp == NULL ||
130 	    enc_krb_cred_part.usec      == NULL ||
131 	    abs(*enc_krb_cred_part.timestamp - sec)
132 	    > context->max_skew) {
133 	    ret = KRB5KRB_AP_ERR_SKEW;
134 	    goto out;
135 	}
136     }
137 
138     /* XXX - check replay cache */
139 
140     /* Store the creds in the ccache */
141 
142     for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) {
143 	KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i];
144 	krb5_creds creds;
145 	u_char buf[1024];
146 	size_t len;
147 
148 	memset (&creds, 0, sizeof(creds));
149 
150 	ret = encode_Ticket (buf + sizeof(buf) - 1, sizeof(buf),
151 			     &cred.tickets.val[i],
152 			     &len);
153 	if (ret)
154 	    goto out;
155 	krb5_data_copy (&creds.ticket, buf + sizeof(buf) - len, len);
156 	copy_EncryptionKey (&kci->key, &creds.session);
157 	if (kci->prealm && kci->pname)
158 	    principalname2krb5_principal (&creds.client,
159 					  *kci->pname,
160 					  *kci->prealm);
161 	if (kci->flags)
162 	    creds.flags.b = *kci->flags;
163 	if (kci->authtime)
164 	    creds.times.authtime = *kci->authtime;
165 	if (kci->starttime)
166 	    creds.times.starttime = *kci->starttime;
167 	if (kci->endtime)
168 	    creds.times.endtime = *kci->endtime;
169 	if (kci->renew_till)
170 	    creds.times.renew_till = *kci->renew_till;
171 	if (kci->srealm && kci->sname)
172 	    principalname2krb5_principal (&creds.server,
173 					  *kci->sname,
174 					  *kci->srealm);
175 	if (kci->caddr)
176 	    krb5_copy_addresses (context,
177 				 kci->caddr,
178 				 &creds.addresses);
179 	krb5_cc_store_cred (context, ccache, &creds);
180     }
181 
182 out:
183     free_KRB_CRED (&cred);
184     return ret;
185 }
186