xref: /freebsd/crypto/heimdal/lib/krb5/digest.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov  * Copyright (c) 2006 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson  * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson  * All rights reserved.
5c19800e8SDoug Rabson  *
6c19800e8SDoug Rabson  * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson  * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson  * are met:
9c19800e8SDoug Rabson  *
10c19800e8SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson  *
13c19800e8SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson  *    documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson  *
17c19800e8SDoug Rabson  * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson  *    may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson  *    without specific prior written permission.
20c19800e8SDoug Rabson  *
21c19800e8SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson  * SUCH DAMAGE.
32c19800e8SDoug Rabson  */
33c19800e8SDoug Rabson 
34c19800e8SDoug Rabson #include "krb5_locl.h"
35c19800e8SDoug Rabson #include "digest_asn1.h"
36c19800e8SDoug Rabson 
37*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
38*ae771770SStanislav Sedov 
39c19800e8SDoug Rabson struct krb5_digest_data {
40c19800e8SDoug Rabson     char *cbtype;
41c19800e8SDoug Rabson     char *cbbinding;
42c19800e8SDoug Rabson 
43c19800e8SDoug Rabson     DigestInit init;
44c19800e8SDoug Rabson     DigestInitReply initReply;
45c19800e8SDoug Rabson     DigestRequest request;
46c19800e8SDoug Rabson     DigestResponse response;
47c19800e8SDoug Rabson };
48c19800e8SDoug Rabson 
49*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_alloc(krb5_context context,krb5_digest * digest)50c19800e8SDoug Rabson krb5_digest_alloc(krb5_context context, krb5_digest *digest)
51c19800e8SDoug Rabson {
52c19800e8SDoug Rabson     krb5_digest d;
53c19800e8SDoug Rabson 
54c19800e8SDoug Rabson     d = calloc(1, sizeof(*d));
55c19800e8SDoug Rabson     if (d == NULL) {
56c19800e8SDoug Rabson 	*digest = NULL;
57*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
58c19800e8SDoug Rabson 	return ENOMEM;
59c19800e8SDoug Rabson     }
60c19800e8SDoug Rabson     *digest = d;
61c19800e8SDoug Rabson 
62c19800e8SDoug Rabson     return 0;
63c19800e8SDoug Rabson }
64c19800e8SDoug Rabson 
65*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_digest_free(krb5_digest digest)66c19800e8SDoug Rabson krb5_digest_free(krb5_digest digest)
67c19800e8SDoug Rabson {
68c19800e8SDoug Rabson     if (digest == NULL)
69c19800e8SDoug Rabson 	return;
70c19800e8SDoug Rabson     free_DigestInit(&digest->init);
71c19800e8SDoug Rabson     free_DigestInitReply(&digest->initReply);
72c19800e8SDoug Rabson     free_DigestRequest(&digest->request);
73c19800e8SDoug Rabson     free_DigestResponse(&digest->response);
74c19800e8SDoug Rabson     memset(digest, 0, sizeof(*digest));
75c19800e8SDoug Rabson     free(digest);
76c19800e8SDoug Rabson     return;
77c19800e8SDoug Rabson }
78c19800e8SDoug Rabson 
79*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_server_cb(krb5_context context,krb5_digest digest,const char * type,const char * binding)80c19800e8SDoug Rabson krb5_digest_set_server_cb(krb5_context context,
81c19800e8SDoug Rabson 			  krb5_digest digest,
82c19800e8SDoug Rabson 			  const char *type,
83c19800e8SDoug Rabson 			  const char *binding)
84c19800e8SDoug Rabson {
85c19800e8SDoug Rabson     if (digest->init.channel) {
86*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
87*ae771770SStanislav Sedov 			       N_("server channel binding already set", ""));
88c19800e8SDoug Rabson 	return EINVAL;
89c19800e8SDoug Rabson     }
90c19800e8SDoug Rabson     digest->init.channel = calloc(1, sizeof(*digest->init.channel));
91c19800e8SDoug Rabson     if (digest->init.channel == NULL)
92c19800e8SDoug Rabson 	goto error;
93c19800e8SDoug Rabson 
94c19800e8SDoug Rabson     digest->init.channel->cb_type = strdup(type);
95c19800e8SDoug Rabson     if (digest->init.channel->cb_type == NULL)
96c19800e8SDoug Rabson 	goto error;
97c19800e8SDoug Rabson 
98c19800e8SDoug Rabson     digest->init.channel->cb_binding = strdup(binding);
99c19800e8SDoug Rabson     if (digest->init.channel->cb_binding == NULL)
100c19800e8SDoug Rabson 	goto error;
101c19800e8SDoug Rabson     return 0;
102c19800e8SDoug Rabson  error:
103c19800e8SDoug Rabson     if (digest->init.channel) {
104c19800e8SDoug Rabson 	free(digest->init.channel->cb_type);
105c19800e8SDoug Rabson 	free(digest->init.channel->cb_binding);
106c19800e8SDoug Rabson 	free(digest->init.channel);
107c19800e8SDoug Rabson 	digest->init.channel = NULL;
108c19800e8SDoug Rabson     }
109*ae771770SStanislav Sedov     krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
110c19800e8SDoug Rabson     return ENOMEM;
111c19800e8SDoug Rabson }
112c19800e8SDoug Rabson 
113*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_type(krb5_context context,krb5_digest digest,const char * type)114c19800e8SDoug Rabson krb5_digest_set_type(krb5_context context,
115c19800e8SDoug Rabson 		     krb5_digest digest,
116c19800e8SDoug Rabson 		     const char *type)
117c19800e8SDoug Rabson {
118c19800e8SDoug Rabson     if (digest->init.type) {
119*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "client type already set");
120c19800e8SDoug Rabson 	return EINVAL;
121c19800e8SDoug Rabson     }
122c19800e8SDoug Rabson     digest->init.type = strdup(type);
123c19800e8SDoug Rabson     if (digest->init.type == NULL) {
124*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
125c19800e8SDoug Rabson 	return ENOMEM;
126c19800e8SDoug Rabson     }
127c19800e8SDoug Rabson     return 0;
128c19800e8SDoug Rabson }
129c19800e8SDoug Rabson 
130*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_hostname(krb5_context context,krb5_digest digest,const char * hostname)131c19800e8SDoug Rabson krb5_digest_set_hostname(krb5_context context,
132c19800e8SDoug Rabson 			 krb5_digest digest,
133c19800e8SDoug Rabson 			 const char *hostname)
134c19800e8SDoug Rabson {
135c19800e8SDoug Rabson     if (digest->init.hostname) {
136*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "server hostname already set");
137c19800e8SDoug Rabson 	return EINVAL;
138c19800e8SDoug Rabson     }
139c19800e8SDoug Rabson     digest->init.hostname = malloc(sizeof(*digest->init.hostname));
140c19800e8SDoug Rabson     if (digest->init.hostname == NULL) {
141*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
142c19800e8SDoug Rabson 	return ENOMEM;
143c19800e8SDoug Rabson     }
144c19800e8SDoug Rabson     *digest->init.hostname = strdup(hostname);
145c19800e8SDoug Rabson     if (*digest->init.hostname == NULL) {
146*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
147c19800e8SDoug Rabson 	free(digest->init.hostname);
148c19800e8SDoug Rabson 	digest->init.hostname = NULL;
149c19800e8SDoug Rabson 	return ENOMEM;
150c19800e8SDoug Rabson     }
151c19800e8SDoug Rabson     return 0;
152c19800e8SDoug Rabson }
153c19800e8SDoug Rabson 
154*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
krb5_digest_get_server_nonce(krb5_context context,krb5_digest digest)155c19800e8SDoug Rabson krb5_digest_get_server_nonce(krb5_context context,
156c19800e8SDoug Rabson 			     krb5_digest digest)
157c19800e8SDoug Rabson {
158c19800e8SDoug Rabson     return digest->initReply.nonce;
159c19800e8SDoug Rabson }
160c19800e8SDoug Rabson 
161*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_server_nonce(krb5_context context,krb5_digest digest,const char * nonce)162c19800e8SDoug Rabson krb5_digest_set_server_nonce(krb5_context context,
163c19800e8SDoug Rabson 			     krb5_digest digest,
164c19800e8SDoug Rabson 			     const char *nonce)
165c19800e8SDoug Rabson {
166c19800e8SDoug Rabson     if (digest->request.serverNonce) {
167*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, N_("nonce already set", ""));
168c19800e8SDoug Rabson 	return EINVAL;
169c19800e8SDoug Rabson     }
170c19800e8SDoug Rabson     digest->request.serverNonce = strdup(nonce);
171c19800e8SDoug Rabson     if (digest->request.serverNonce == NULL) {
172*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
173c19800e8SDoug Rabson 	return ENOMEM;
174c19800e8SDoug Rabson     }
175c19800e8SDoug Rabson     return 0;
176c19800e8SDoug Rabson }
177c19800e8SDoug Rabson 
178*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
krb5_digest_get_opaque(krb5_context context,krb5_digest digest)179c19800e8SDoug Rabson krb5_digest_get_opaque(krb5_context context,
180c19800e8SDoug Rabson 		       krb5_digest digest)
181c19800e8SDoug Rabson {
182c19800e8SDoug Rabson     return digest->initReply.opaque;
183c19800e8SDoug Rabson }
184c19800e8SDoug Rabson 
185*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_opaque(krb5_context context,krb5_digest digest,const char * opaque)186c19800e8SDoug Rabson krb5_digest_set_opaque(krb5_context context,
187c19800e8SDoug Rabson 		       krb5_digest digest,
188c19800e8SDoug Rabson 		       const char *opaque)
189c19800e8SDoug Rabson {
190c19800e8SDoug Rabson     if (digest->request.opaque) {
191*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "opaque already set");
192c19800e8SDoug Rabson 	return EINVAL;
193c19800e8SDoug Rabson     }
194c19800e8SDoug Rabson     digest->request.opaque = strdup(opaque);
195c19800e8SDoug Rabson     if (digest->request.opaque == NULL) {
196*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
197c19800e8SDoug Rabson 	return ENOMEM;
198c19800e8SDoug Rabson     }
199c19800e8SDoug Rabson     return 0;
200c19800e8SDoug Rabson }
201c19800e8SDoug Rabson 
202*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
krb5_digest_get_identifier(krb5_context context,krb5_digest digest)203c19800e8SDoug Rabson krb5_digest_get_identifier(krb5_context context,
204c19800e8SDoug Rabson 			   krb5_digest digest)
205c19800e8SDoug Rabson {
206c19800e8SDoug Rabson     if (digest->initReply.identifier == NULL)
207c19800e8SDoug Rabson 	return NULL;
208c19800e8SDoug Rabson     return *digest->initReply.identifier;
209c19800e8SDoug Rabson }
210c19800e8SDoug Rabson 
211*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_identifier(krb5_context context,krb5_digest digest,const char * id)212c19800e8SDoug Rabson krb5_digest_set_identifier(krb5_context context,
213c19800e8SDoug Rabson 			   krb5_digest digest,
214c19800e8SDoug Rabson 			   const char *id)
215c19800e8SDoug Rabson {
216c19800e8SDoug Rabson     if (digest->request.identifier) {
217*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, N_("identifier already set", ""));
218c19800e8SDoug Rabson 	return EINVAL;
219c19800e8SDoug Rabson     }
220c19800e8SDoug Rabson     digest->request.identifier = calloc(1, sizeof(*digest->request.identifier));
221c19800e8SDoug Rabson     if (digest->request.identifier == NULL) {
222*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
223c19800e8SDoug Rabson 	return ENOMEM;
224c19800e8SDoug Rabson     }
225c19800e8SDoug Rabson     *digest->request.identifier = strdup(id);
226c19800e8SDoug Rabson     if (*digest->request.identifier == NULL) {
227*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
228c19800e8SDoug Rabson 	free(digest->request.identifier);
229c19800e8SDoug Rabson 	digest->request.identifier = NULL;
230c19800e8SDoug Rabson 	return ENOMEM;
231c19800e8SDoug Rabson     }
232c19800e8SDoug Rabson     return 0;
233c19800e8SDoug Rabson }
234c19800e8SDoug Rabson 
235c19800e8SDoug Rabson static krb5_error_code
digest_request(krb5_context context,krb5_realm realm,krb5_ccache ccache,krb5_key_usage usage,const DigestReqInner * ireq,DigestRepInner * irep)236c19800e8SDoug Rabson digest_request(krb5_context context,
237c19800e8SDoug Rabson 	       krb5_realm realm,
238c19800e8SDoug Rabson 	       krb5_ccache ccache,
239c19800e8SDoug Rabson 	       krb5_key_usage usage,
240c19800e8SDoug Rabson 	       const DigestReqInner *ireq,
241c19800e8SDoug Rabson 	       DigestRepInner *irep)
242c19800e8SDoug Rabson {
243c19800e8SDoug Rabson     DigestREQ req;
244c19800e8SDoug Rabson     DigestREP rep;
245c19800e8SDoug Rabson     krb5_error_code ret;
246c19800e8SDoug Rabson     krb5_data data, data2;
247*ae771770SStanislav Sedov     size_t size = 0;
248c19800e8SDoug Rabson     krb5_crypto crypto = NULL;
249c19800e8SDoug Rabson     krb5_auth_context ac = NULL;
250c19800e8SDoug Rabson     krb5_principal principal = NULL;
251c19800e8SDoug Rabson     krb5_ccache id = NULL;
252c19800e8SDoug Rabson     krb5_realm r = NULL;
253c19800e8SDoug Rabson 
254c19800e8SDoug Rabson     krb5_data_zero(&data);
255c19800e8SDoug Rabson     krb5_data_zero(&data2);
256c19800e8SDoug Rabson     memset(&req, 0, sizeof(req));
257c19800e8SDoug Rabson     memset(&rep, 0, sizeof(rep));
258c19800e8SDoug Rabson 
259c19800e8SDoug Rabson     if (ccache == NULL) {
260c19800e8SDoug Rabson 	ret = krb5_cc_default(context, &id);
261c19800e8SDoug Rabson 	if (ret)
262c19800e8SDoug Rabson 	    goto out;
263c19800e8SDoug Rabson     } else
264c19800e8SDoug Rabson 	id = ccache;
265c19800e8SDoug Rabson 
266c19800e8SDoug Rabson     if (realm == NULL) {
267c19800e8SDoug Rabson 	ret = krb5_get_default_realm(context, &r);
268c19800e8SDoug Rabson 	if (ret)
269c19800e8SDoug Rabson 	    goto out;
270c19800e8SDoug Rabson     } else
271c19800e8SDoug Rabson 	r = realm;
272c19800e8SDoug Rabson 
273c19800e8SDoug Rabson     /*
274c19800e8SDoug Rabson      *
275c19800e8SDoug Rabson      */
276c19800e8SDoug Rabson 
277c19800e8SDoug Rabson     ret = krb5_make_principal(context, &principal,
278c19800e8SDoug Rabson 			      r, KRB5_DIGEST_NAME, r, NULL);
279c19800e8SDoug Rabson     if (ret)
280c19800e8SDoug Rabson 	goto out;
281c19800e8SDoug Rabson 
282c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length,
283c19800e8SDoug Rabson 		       ireq, &size, ret);
284c19800e8SDoug Rabson     if (ret) {
285*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
286*ae771770SStanislav Sedov 			       N_("Failed to encode digest inner request", ""));
287c19800e8SDoug Rabson 	goto out;
288c19800e8SDoug Rabson     }
289c19800e8SDoug Rabson     if (size != data.length)
290c19800e8SDoug Rabson 	krb5_abortx(context, "ASN.1 internal encoder error");
291c19800e8SDoug Rabson 
292c19800e8SDoug Rabson     ret = krb5_mk_req_exact(context, &ac,
293c19800e8SDoug Rabson 			    AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED,
294c19800e8SDoug Rabson 			    principal, NULL, id, &req.apReq);
295c19800e8SDoug Rabson     if (ret)
296c19800e8SDoug Rabson 	goto out;
297c19800e8SDoug Rabson 
298c19800e8SDoug Rabson     {
299c19800e8SDoug Rabson 	krb5_keyblock *key;
300c19800e8SDoug Rabson 
301c19800e8SDoug Rabson 	ret = krb5_auth_con_getlocalsubkey(context, ac, &key);
302c19800e8SDoug Rabson 	if (ret)
303c19800e8SDoug Rabson 	    goto out;
304c19800e8SDoug Rabson 	if (key == NULL) {
305c19800e8SDoug Rabson 	    ret = EINVAL;
306*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
307*ae771770SStanislav Sedov 				   N_("Digest failed to get local subkey", ""));
308c19800e8SDoug Rabson 	    goto out;
309c19800e8SDoug Rabson 	}
310c19800e8SDoug Rabson 
311c19800e8SDoug Rabson 	ret = krb5_crypto_init(context, key, 0, &crypto);
312c19800e8SDoug Rabson 	krb5_free_keyblock (context, key);
313c19800e8SDoug Rabson 	if (ret)
314c19800e8SDoug Rabson 	    goto out;
315c19800e8SDoug Rabson     }
316c19800e8SDoug Rabson 
317c19800e8SDoug Rabson     ret = krb5_encrypt_EncryptedData(context, crypto, usage,
318c19800e8SDoug Rabson 				     data.data, data.length, 0,
319c19800e8SDoug Rabson 				     &req.innerReq);
320c19800e8SDoug Rabson     if (ret)
321c19800e8SDoug Rabson 	goto out;
322c19800e8SDoug Rabson 
323c19800e8SDoug Rabson     krb5_data_free(&data);
324c19800e8SDoug Rabson 
325c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length,
326c19800e8SDoug Rabson 		       &req, &size, ret);
327c19800e8SDoug Rabson     if (ret) {
328*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
329*ae771770SStanislav Sedov 			       N_("Failed to encode DigestREQest", ""));
330c19800e8SDoug Rabson 	goto out;
331c19800e8SDoug Rabson     }
332c19800e8SDoug Rabson     if (size != data.length)
333c19800e8SDoug Rabson 	krb5_abortx(context, "ASN.1 internal encoder error");
334c19800e8SDoug Rabson 
335c19800e8SDoug Rabson     ret = krb5_sendto_kdc(context, &data, &r, &data2);
336c19800e8SDoug Rabson     if (ret)
337c19800e8SDoug Rabson 	goto out;
338c19800e8SDoug Rabson 
339c19800e8SDoug Rabson     ret = decode_DigestREP(data2.data, data2.length, &rep, NULL);
340c19800e8SDoug Rabson     if (ret) {
341*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
342*ae771770SStanislav Sedov 			       N_("Failed to parse digest response", ""));
343c19800e8SDoug Rabson 	goto out;
344c19800e8SDoug Rabson     }
345c19800e8SDoug Rabson 
346c19800e8SDoug Rabson     {
347c19800e8SDoug Rabson 	krb5_ap_rep_enc_part *repl;
348c19800e8SDoug Rabson 
349c19800e8SDoug Rabson 	ret = krb5_rd_rep(context, ac, &rep.apRep, &repl);
350c19800e8SDoug Rabson 	if (ret)
351c19800e8SDoug Rabson 	    goto out;
352c19800e8SDoug Rabson 
353c19800e8SDoug Rabson 	krb5_free_ap_rep_enc_part(context, repl);
354c19800e8SDoug Rabson     }
355c19800e8SDoug Rabson     {
356c19800e8SDoug Rabson 	krb5_keyblock *key;
357c19800e8SDoug Rabson 
358c19800e8SDoug Rabson 	ret = krb5_auth_con_getremotesubkey(context, ac, &key);
359c19800e8SDoug Rabson 	if (ret)
360c19800e8SDoug Rabson 	    goto out;
361c19800e8SDoug Rabson 	if (key == NULL) {
362c19800e8SDoug Rabson 	    ret = EINVAL;
363*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
364*ae771770SStanislav Sedov 				   N_("Digest reply have no remote subkey", ""));
365c19800e8SDoug Rabson 	    goto out;
366c19800e8SDoug Rabson 	}
367c19800e8SDoug Rabson 
368c19800e8SDoug Rabson 	krb5_crypto_destroy(context, crypto);
369c19800e8SDoug Rabson 	ret = krb5_crypto_init(context, key, 0, &crypto);
370c19800e8SDoug Rabson 	krb5_free_keyblock (context, key);
371c19800e8SDoug Rabson 	if (ret)
372c19800e8SDoug Rabson 	    goto out;
373c19800e8SDoug Rabson     }
374c19800e8SDoug Rabson 
375c19800e8SDoug Rabson     krb5_data_free(&data);
376c19800e8SDoug Rabson     ret = krb5_decrypt_EncryptedData(context, crypto, usage,
377c19800e8SDoug Rabson 				     &rep.innerRep, &data);
378c19800e8SDoug Rabson     if (ret)
379c19800e8SDoug Rabson 	goto out;
380c19800e8SDoug Rabson 
381c19800e8SDoug Rabson     ret = decode_DigestRepInner(data.data, data.length, irep, NULL);
382c19800e8SDoug Rabson     if (ret) {
383*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
384*ae771770SStanislav Sedov 			       N_("Failed to decode digest inner reply", ""));
385c19800e8SDoug Rabson 	goto out;
386c19800e8SDoug Rabson     }
387c19800e8SDoug Rabson 
388c19800e8SDoug Rabson  out:
389c19800e8SDoug Rabson     if (ccache == NULL && id)
390c19800e8SDoug Rabson 	krb5_cc_close(context, id);
391c19800e8SDoug Rabson     if (realm == NULL && r)
392c19800e8SDoug Rabson 	free(r);
393c19800e8SDoug Rabson     if (crypto)
394c19800e8SDoug Rabson 	krb5_crypto_destroy(context, crypto);
395c19800e8SDoug Rabson     if (ac)
396c19800e8SDoug Rabson 	krb5_auth_con_free(context, ac);
397c19800e8SDoug Rabson     if (principal)
398c19800e8SDoug Rabson 	krb5_free_principal(context, principal);
399c19800e8SDoug Rabson 
400c19800e8SDoug Rabson     krb5_data_free(&data);
401c19800e8SDoug Rabson     krb5_data_free(&data2);
402c19800e8SDoug Rabson 
403c19800e8SDoug Rabson     free_DigestREQ(&req);
404c19800e8SDoug Rabson     free_DigestREP(&rep);
405c19800e8SDoug Rabson 
406c19800e8SDoug Rabson     return ret;
407c19800e8SDoug Rabson }
408c19800e8SDoug Rabson 
409*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_init_request(krb5_context context,krb5_digest digest,krb5_realm realm,krb5_ccache ccache)410c19800e8SDoug Rabson krb5_digest_init_request(krb5_context context,
411c19800e8SDoug Rabson 			 krb5_digest digest,
412c19800e8SDoug Rabson 			 krb5_realm realm,
413c19800e8SDoug Rabson 			 krb5_ccache ccache)
414c19800e8SDoug Rabson {
415c19800e8SDoug Rabson     DigestReqInner ireq;
416c19800e8SDoug Rabson     DigestRepInner irep;
417c19800e8SDoug Rabson     krb5_error_code ret;
418c19800e8SDoug Rabson 
419c19800e8SDoug Rabson     memset(&ireq, 0, sizeof(ireq));
420c19800e8SDoug Rabson     memset(&irep, 0, sizeof(irep));
421c19800e8SDoug Rabson 
422c19800e8SDoug Rabson     if (digest->init.type == NULL) {
423*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
424*ae771770SStanislav Sedov 			       N_("Type missing from init req", ""));
425c19800e8SDoug Rabson 	return EINVAL;
426c19800e8SDoug Rabson     }
427c19800e8SDoug Rabson 
428c19800e8SDoug Rabson     ireq.element = choice_DigestReqInner_init;
429c19800e8SDoug Rabson     ireq.u.init = digest->init;
430c19800e8SDoug Rabson 
431c19800e8SDoug Rabson     ret = digest_request(context, realm, ccache,
432c19800e8SDoug Rabson 			 KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep);
433c19800e8SDoug Rabson     if (ret)
434c19800e8SDoug Rabson 	goto out;
435c19800e8SDoug Rabson 
436c19800e8SDoug Rabson     if (irep.element == choice_DigestRepInner_error) {
437c19800e8SDoug Rabson 	ret = irep.u.error.code;
438*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("Digest init error: %s", ""),
439*ae771770SStanislav Sedov 			       irep.u.error.reason);
440c19800e8SDoug Rabson 	goto out;
441c19800e8SDoug Rabson     }
442c19800e8SDoug Rabson 
443c19800e8SDoug Rabson     if (irep.element != choice_DigestRepInner_initReply) {
444c19800e8SDoug Rabson 	ret = EINVAL;
445*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
446*ae771770SStanislav Sedov 			       N_("digest reply not an initReply", ""));
447c19800e8SDoug Rabson 	goto out;
448c19800e8SDoug Rabson     }
449c19800e8SDoug Rabson 
450c19800e8SDoug Rabson     ret = copy_DigestInitReply(&irep.u.initReply, &digest->initReply);
451c19800e8SDoug Rabson     if (ret) {
452*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
453*ae771770SStanislav Sedov 			       N_("Failed to copy initReply", ""));
454c19800e8SDoug Rabson 	goto out;
455c19800e8SDoug Rabson     }
456c19800e8SDoug Rabson 
457c19800e8SDoug Rabson  out:
458c19800e8SDoug Rabson     free_DigestRepInner(&irep);
459c19800e8SDoug Rabson 
460c19800e8SDoug Rabson     return ret;
461c19800e8SDoug Rabson }
462c19800e8SDoug Rabson 
463c19800e8SDoug Rabson 
464*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_client_nonce(krb5_context context,krb5_digest digest,const char * nonce)465c19800e8SDoug Rabson krb5_digest_set_client_nonce(krb5_context context,
466c19800e8SDoug Rabson 			     krb5_digest digest,
467c19800e8SDoug Rabson 			     const char *nonce)
468c19800e8SDoug Rabson {
469c19800e8SDoug Rabson     if (digest->request.clientNonce) {
470*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
471*ae771770SStanislav Sedov 			       N_("clientNonce already set", ""));
472c19800e8SDoug Rabson 	return EINVAL;
473c19800e8SDoug Rabson     }
474c19800e8SDoug Rabson     digest->request.clientNonce =
475c19800e8SDoug Rabson 	calloc(1, sizeof(*digest->request.clientNonce));
476c19800e8SDoug Rabson     if (digest->request.clientNonce == NULL) {
477*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
478c19800e8SDoug Rabson 	return ENOMEM;
479c19800e8SDoug Rabson     }
480c19800e8SDoug Rabson     *digest->request.clientNonce = strdup(nonce);
481c19800e8SDoug Rabson     if (*digest->request.clientNonce == NULL) {
482*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
483c19800e8SDoug Rabson 	free(digest->request.clientNonce);
484c19800e8SDoug Rabson 	digest->request.clientNonce = NULL;
485c19800e8SDoug Rabson 	return ENOMEM;
486c19800e8SDoug Rabson     }
487c19800e8SDoug Rabson     return 0;
488c19800e8SDoug Rabson }
489c19800e8SDoug Rabson 
490*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_digest(krb5_context context,krb5_digest digest,const char * dgst)491c19800e8SDoug Rabson krb5_digest_set_digest(krb5_context context,
492c19800e8SDoug Rabson 		       krb5_digest digest,
493c19800e8SDoug Rabson 		       const char *dgst)
494c19800e8SDoug Rabson {
495c19800e8SDoug Rabson     if (digest->request.digest) {
496*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
497*ae771770SStanislav Sedov 			       N_("digest already set", ""));
498c19800e8SDoug Rabson 	return EINVAL;
499c19800e8SDoug Rabson     }
500c19800e8SDoug Rabson     digest->request.digest = strdup(dgst);
501c19800e8SDoug Rabson     if (digest->request.digest == NULL) {
502*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
503c19800e8SDoug Rabson 	return ENOMEM;
504c19800e8SDoug Rabson     }
505c19800e8SDoug Rabson     return 0;
506c19800e8SDoug Rabson }
507c19800e8SDoug Rabson 
508*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_username(krb5_context context,krb5_digest digest,const char * username)509c19800e8SDoug Rabson krb5_digest_set_username(krb5_context context,
510c19800e8SDoug Rabson 			 krb5_digest digest,
511c19800e8SDoug Rabson 			 const char *username)
512c19800e8SDoug Rabson {
513c19800e8SDoug Rabson     if (digest->request.username) {
514*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "username already set");
515c19800e8SDoug Rabson 	return EINVAL;
516c19800e8SDoug Rabson     }
517c19800e8SDoug Rabson     digest->request.username = strdup(username);
518c19800e8SDoug Rabson     if (digest->request.username == NULL) {
519*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
520c19800e8SDoug Rabson 	return ENOMEM;
521c19800e8SDoug Rabson     }
522c19800e8SDoug Rabson     return 0;
523c19800e8SDoug Rabson }
524c19800e8SDoug Rabson 
525*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_authid(krb5_context context,krb5_digest digest,const char * authid)526c19800e8SDoug Rabson krb5_digest_set_authid(krb5_context context,
527c19800e8SDoug Rabson 		       krb5_digest digest,
528c19800e8SDoug Rabson 		       const char *authid)
529c19800e8SDoug Rabson {
530c19800e8SDoug Rabson     if (digest->request.authid) {
531*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "authid already set");
532c19800e8SDoug Rabson 	return EINVAL;
533c19800e8SDoug Rabson     }
534c19800e8SDoug Rabson     digest->request.authid = malloc(sizeof(*digest->request.authid));
535c19800e8SDoug Rabson     if (digest->request.authid == NULL) {
536*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
537c19800e8SDoug Rabson 	return ENOMEM;
538c19800e8SDoug Rabson     }
539c19800e8SDoug Rabson     *digest->request.authid = strdup(authid);
540c19800e8SDoug Rabson     if (*digest->request.authid == NULL) {
541*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
542c19800e8SDoug Rabson 	free(digest->request.authid);
543c19800e8SDoug Rabson 	digest->request.authid = NULL;
544c19800e8SDoug Rabson 	return ENOMEM;
545c19800e8SDoug Rabson     }
546c19800e8SDoug Rabson     return 0;
547c19800e8SDoug Rabson }
548c19800e8SDoug Rabson 
549*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_authentication_user(krb5_context context,krb5_digest digest,krb5_principal authentication_user)550c19800e8SDoug Rabson krb5_digest_set_authentication_user(krb5_context context,
551c19800e8SDoug Rabson 				    krb5_digest digest,
552c19800e8SDoug Rabson 				    krb5_principal authentication_user)
553c19800e8SDoug Rabson {
554c19800e8SDoug Rabson     krb5_error_code ret;
555c19800e8SDoug Rabson 
556c19800e8SDoug Rabson     if (digest->request.authentication_user) {
557*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
558*ae771770SStanislav Sedov 			       N_("authentication_user already set", ""));
559c19800e8SDoug Rabson 	return EINVAL;
560c19800e8SDoug Rabson     }
561c19800e8SDoug Rabson     ret = krb5_copy_principal(context,
562c19800e8SDoug Rabson 			      authentication_user,
563c19800e8SDoug Rabson 			      &digest->request.authentication_user);
564*ae771770SStanislav Sedov     if (ret)
565*ae771770SStanislav Sedov 	return ret;
566c19800e8SDoug Rabson     return 0;
567c19800e8SDoug Rabson }
568c19800e8SDoug Rabson 
569*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_realm(krb5_context context,krb5_digest digest,const char * realm)570c19800e8SDoug Rabson krb5_digest_set_realm(krb5_context context,
571c19800e8SDoug Rabson 		      krb5_digest digest,
572c19800e8SDoug Rabson 		      const char *realm)
573c19800e8SDoug Rabson {
574c19800e8SDoug Rabson     if (digest->request.realm) {
575*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "realm already set");
576c19800e8SDoug Rabson 	return EINVAL;
577c19800e8SDoug Rabson     }
578c19800e8SDoug Rabson     digest->request.realm = malloc(sizeof(*digest->request.realm));
579c19800e8SDoug Rabson     if (digest->request.realm == NULL) {
580*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
581c19800e8SDoug Rabson 	return ENOMEM;
582c19800e8SDoug Rabson     }
583c19800e8SDoug Rabson     *digest->request.realm = strdup(realm);
584c19800e8SDoug Rabson     if (*digest->request.realm == NULL) {
585*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
586c19800e8SDoug Rabson 	free(digest->request.realm);
587c19800e8SDoug Rabson 	digest->request.realm = NULL;
588c19800e8SDoug Rabson 	return ENOMEM;
589c19800e8SDoug Rabson     }
590c19800e8SDoug Rabson     return 0;
591c19800e8SDoug Rabson }
592c19800e8SDoug Rabson 
593*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_method(krb5_context context,krb5_digest digest,const char * method)594c19800e8SDoug Rabson krb5_digest_set_method(krb5_context context,
595c19800e8SDoug Rabson 		       krb5_digest digest,
596c19800e8SDoug Rabson 		       const char *method)
597c19800e8SDoug Rabson {
598c19800e8SDoug Rabson     if (digest->request.method) {
599*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
600*ae771770SStanislav Sedov 			       N_("method already set", ""));
601c19800e8SDoug Rabson 	return EINVAL;
602c19800e8SDoug Rabson     }
603c19800e8SDoug Rabson     digest->request.method = malloc(sizeof(*digest->request.method));
604c19800e8SDoug Rabson     if (digest->request.method == NULL) {
605*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
606c19800e8SDoug Rabson 	return ENOMEM;
607c19800e8SDoug Rabson     }
608c19800e8SDoug Rabson     *digest->request.method = strdup(method);
609c19800e8SDoug Rabson     if (*digest->request.method == NULL) {
610*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
611c19800e8SDoug Rabson 	free(digest->request.method);
612c19800e8SDoug Rabson 	digest->request.method = NULL;
613c19800e8SDoug Rabson 	return ENOMEM;
614c19800e8SDoug Rabson     }
615c19800e8SDoug Rabson     return 0;
616c19800e8SDoug Rabson }
617c19800e8SDoug Rabson 
618*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_uri(krb5_context context,krb5_digest digest,const char * uri)619c19800e8SDoug Rabson krb5_digest_set_uri(krb5_context context,
620c19800e8SDoug Rabson 		    krb5_digest digest,
621c19800e8SDoug Rabson 		    const char *uri)
622c19800e8SDoug Rabson {
623c19800e8SDoug Rabson     if (digest->request.uri) {
624*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, N_("uri already set", ""));
625c19800e8SDoug Rabson 	return EINVAL;
626c19800e8SDoug Rabson     }
627c19800e8SDoug Rabson     digest->request.uri = malloc(sizeof(*digest->request.uri));
628c19800e8SDoug Rabson     if (digest->request.uri == NULL) {
629*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
630c19800e8SDoug Rabson 	return ENOMEM;
631c19800e8SDoug Rabson     }
632c19800e8SDoug Rabson     *digest->request.uri = strdup(uri);
633c19800e8SDoug Rabson     if (*digest->request.uri == NULL) {
634*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
635c19800e8SDoug Rabson 	free(digest->request.uri);
636c19800e8SDoug Rabson 	digest->request.uri = NULL;
637c19800e8SDoug Rabson 	return ENOMEM;
638c19800e8SDoug Rabson     }
639c19800e8SDoug Rabson     return 0;
640c19800e8SDoug Rabson }
641c19800e8SDoug Rabson 
642*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_nonceCount(krb5_context context,krb5_digest digest,const char * nonce_count)643c19800e8SDoug Rabson krb5_digest_set_nonceCount(krb5_context context,
644c19800e8SDoug Rabson 			   krb5_digest digest,
645c19800e8SDoug Rabson 			   const char *nonce_count)
646c19800e8SDoug Rabson {
647c19800e8SDoug Rabson     if (digest->request.nonceCount) {
648*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
649*ae771770SStanislav Sedov 			       N_("nonceCount already set", ""));
650c19800e8SDoug Rabson 	return EINVAL;
651c19800e8SDoug Rabson     }
652c19800e8SDoug Rabson     digest->request.nonceCount =
653c19800e8SDoug Rabson 	malloc(sizeof(*digest->request.nonceCount));
654c19800e8SDoug Rabson     if (digest->request.nonceCount == NULL) {
655*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
656c19800e8SDoug Rabson 	return ENOMEM;
657c19800e8SDoug Rabson     }
658c19800e8SDoug Rabson     *digest->request.nonceCount = strdup(nonce_count);
659c19800e8SDoug Rabson     if (*digest->request.nonceCount == NULL) {
660*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
661c19800e8SDoug Rabson 	free(digest->request.nonceCount);
662c19800e8SDoug Rabson 	digest->request.nonceCount = NULL;
663c19800e8SDoug Rabson 	return ENOMEM;
664c19800e8SDoug Rabson     }
665c19800e8SDoug Rabson     return 0;
666c19800e8SDoug Rabson }
667c19800e8SDoug Rabson 
668*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_set_qop(krb5_context context,krb5_digest digest,const char * qop)669c19800e8SDoug Rabson krb5_digest_set_qop(krb5_context context,
670c19800e8SDoug Rabson 		    krb5_digest digest,
671c19800e8SDoug Rabson 		    const char *qop)
672c19800e8SDoug Rabson {
673c19800e8SDoug Rabson     if (digest->request.qop) {
674*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL, "qop already set");
675c19800e8SDoug Rabson 	return EINVAL;
676c19800e8SDoug Rabson     }
677c19800e8SDoug Rabson     digest->request.qop = malloc(sizeof(*digest->request.qop));
678c19800e8SDoug Rabson     if (digest->request.qop == NULL) {
679*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
680c19800e8SDoug Rabson 	return ENOMEM;
681c19800e8SDoug Rabson     }
682c19800e8SDoug Rabson     *digest->request.qop = strdup(qop);
683c19800e8SDoug Rabson     if (*digest->request.qop == NULL) {
684*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
685c19800e8SDoug Rabson 	free(digest->request.qop);
686c19800e8SDoug Rabson 	digest->request.qop = NULL;
687c19800e8SDoug Rabson 	return ENOMEM;
688c19800e8SDoug Rabson     }
689c19800e8SDoug Rabson     return 0;
690c19800e8SDoug Rabson }
691c19800e8SDoug Rabson 
692*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_digest_set_responseData(krb5_context context,krb5_digest digest,const char * response)693c19800e8SDoug Rabson krb5_digest_set_responseData(krb5_context context,
694c19800e8SDoug Rabson 			     krb5_digest digest,
695c19800e8SDoug Rabson 			     const char *response)
696c19800e8SDoug Rabson {
697c19800e8SDoug Rabson     digest->request.responseData = strdup(response);
698c19800e8SDoug Rabson     if (digest->request.responseData == NULL) {
699*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
700c19800e8SDoug Rabson 	return ENOMEM;
701c19800e8SDoug Rabson     }
702c19800e8SDoug Rabson     return 0;
703c19800e8SDoug Rabson }
704c19800e8SDoug Rabson 
705*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_request(krb5_context context,krb5_digest digest,krb5_realm realm,krb5_ccache ccache)706c19800e8SDoug Rabson krb5_digest_request(krb5_context context,
707c19800e8SDoug Rabson 		    krb5_digest digest,
708c19800e8SDoug Rabson 		    krb5_realm realm,
709c19800e8SDoug Rabson 		    krb5_ccache ccache)
710c19800e8SDoug Rabson {
711c19800e8SDoug Rabson     DigestReqInner ireq;
712c19800e8SDoug Rabson     DigestRepInner irep;
713c19800e8SDoug Rabson     krb5_error_code ret;
714c19800e8SDoug Rabson 
715c19800e8SDoug Rabson     memset(&ireq, 0, sizeof(ireq));
716c19800e8SDoug Rabson     memset(&irep, 0, sizeof(irep));
717c19800e8SDoug Rabson 
718c19800e8SDoug Rabson     ireq.element = choice_DigestReqInner_digestRequest;
719c19800e8SDoug Rabson     ireq.u.digestRequest = digest->request;
720c19800e8SDoug Rabson 
721c19800e8SDoug Rabson     if (digest->request.type == NULL) {
722c19800e8SDoug Rabson 	if (digest->init.type == NULL) {
723*ae771770SStanislav Sedov 	    krb5_set_error_message(context, EINVAL,
724*ae771770SStanislav Sedov 				   N_("Type missing from req", ""));
725c19800e8SDoug Rabson 	    return EINVAL;
726c19800e8SDoug Rabson 	}
727c19800e8SDoug Rabson 	ireq.u.digestRequest.type = digest->init.type;
728c19800e8SDoug Rabson     }
729c19800e8SDoug Rabson 
730*ae771770SStanislav Sedov     if (ireq.u.digestRequest.digest == NULL) {
731*ae771770SStanislav Sedov 	static char md5[] = "md5";
732*ae771770SStanislav Sedov 	ireq.u.digestRequest.digest = md5;
733*ae771770SStanislav Sedov     }
734c19800e8SDoug Rabson 
735c19800e8SDoug Rabson     ret = digest_request(context, realm, ccache,
736c19800e8SDoug Rabson 			 KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep);
737c19800e8SDoug Rabson     if (ret)
738c19800e8SDoug Rabson 	return ret;
739c19800e8SDoug Rabson 
740c19800e8SDoug Rabson     if (irep.element == choice_DigestRepInner_error) {
741c19800e8SDoug Rabson 	ret = irep.u.error.code;
742*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
743*ae771770SStanislav Sedov 			       N_("Digest response error: %s", ""),
744*ae771770SStanislav Sedov 			       irep.u.error.reason);
745c19800e8SDoug Rabson 	goto out;
746c19800e8SDoug Rabson     }
747c19800e8SDoug Rabson 
748c19800e8SDoug Rabson     if (irep.element != choice_DigestRepInner_response) {
749*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
750*ae771770SStanislav Sedov 			       N_("digest reply not an DigestResponse", ""));
751c19800e8SDoug Rabson 	ret = EINVAL;
752c19800e8SDoug Rabson 	goto out;
753c19800e8SDoug Rabson     }
754c19800e8SDoug Rabson 
755c19800e8SDoug Rabson     ret = copy_DigestResponse(&irep.u.response, &digest->response);
756c19800e8SDoug Rabson     if (ret) {
757*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
758*ae771770SStanislav Sedov 			       N_("Failed to copy initReply,", ""));
759c19800e8SDoug Rabson 	goto out;
760c19800e8SDoug Rabson     }
761c19800e8SDoug Rabson 
762c19800e8SDoug Rabson  out:
763c19800e8SDoug Rabson     free_DigestRepInner(&irep);
764c19800e8SDoug Rabson 
765c19800e8SDoug Rabson     return ret;
766c19800e8SDoug Rabson }
767c19800e8SDoug Rabson 
768*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_digest_rep_get_status(krb5_context context,krb5_digest digest)769c19800e8SDoug Rabson krb5_digest_rep_get_status(krb5_context context,
770c19800e8SDoug Rabson 			   krb5_digest digest)
771c19800e8SDoug Rabson {
772c19800e8SDoug Rabson     return digest->response.success ? TRUE : FALSE;
773c19800e8SDoug Rabson }
774c19800e8SDoug Rabson 
775*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
krb5_digest_get_rsp(krb5_context context,krb5_digest digest)776c19800e8SDoug Rabson krb5_digest_get_rsp(krb5_context context,
777c19800e8SDoug Rabson 		    krb5_digest digest)
778c19800e8SDoug Rabson {
779c19800e8SDoug Rabson     if (digest->response.rsp == NULL)
780c19800e8SDoug Rabson 	return NULL;
781c19800e8SDoug Rabson     return *digest->response.rsp;
782c19800e8SDoug Rabson }
783c19800e8SDoug Rabson 
784*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_get_tickets(krb5_context context,krb5_digest digest,Ticket ** tickets)785c19800e8SDoug Rabson krb5_digest_get_tickets(krb5_context context,
786c19800e8SDoug Rabson 			krb5_digest digest,
787c19800e8SDoug Rabson 			Ticket **tickets)
788c19800e8SDoug Rabson {
789c19800e8SDoug Rabson     *tickets = NULL;
790c19800e8SDoug Rabson     return 0;
791c19800e8SDoug Rabson }
792c19800e8SDoug Rabson 
793c19800e8SDoug Rabson 
794*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_get_client_binding(krb5_context context,krb5_digest digest,char ** type,char ** binding)795c19800e8SDoug Rabson krb5_digest_get_client_binding(krb5_context context,
796c19800e8SDoug Rabson 			       krb5_digest digest,
797c19800e8SDoug Rabson 			       char **type,
798c19800e8SDoug Rabson 			       char **binding)
799c19800e8SDoug Rabson {
800c19800e8SDoug Rabson     if (digest->response.channel) {
801c19800e8SDoug Rabson 	*type = strdup(digest->response.channel->cb_type);
802c19800e8SDoug Rabson 	*binding = strdup(digest->response.channel->cb_binding);
803c19800e8SDoug Rabson 	if (*type == NULL || *binding == NULL) {
804c19800e8SDoug Rabson 	    free(*type);
805c19800e8SDoug Rabson 	    free(*binding);
806*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
807c19800e8SDoug Rabson 	    return ENOMEM;
808c19800e8SDoug Rabson 	}
809c19800e8SDoug Rabson     } else {
810c19800e8SDoug Rabson 	*type = NULL;
811c19800e8SDoug Rabson 	*binding = NULL;
812c19800e8SDoug Rabson     }
813c19800e8SDoug Rabson     return 0;
814c19800e8SDoug Rabson }
815c19800e8SDoug Rabson 
816*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_get_session_key(krb5_context context,krb5_digest digest,krb5_data * data)817c19800e8SDoug Rabson krb5_digest_get_session_key(krb5_context context,
818c19800e8SDoug Rabson 			    krb5_digest digest,
819c19800e8SDoug Rabson 			    krb5_data *data)
820c19800e8SDoug Rabson {
821c19800e8SDoug Rabson     krb5_error_code ret;
822c19800e8SDoug Rabson 
823c19800e8SDoug Rabson     krb5_data_zero(data);
824c19800e8SDoug Rabson     if (digest->response.session_key == NULL)
825c19800e8SDoug Rabson 	return 0;
826c19800e8SDoug Rabson     ret = der_copy_octet_string(digest->response.session_key, data);
827c19800e8SDoug Rabson     if (ret)
828*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
829c19800e8SDoug Rabson 
830c19800e8SDoug Rabson     return ret;
831c19800e8SDoug Rabson }
832c19800e8SDoug Rabson 
833c19800e8SDoug Rabson struct krb5_ntlm_data {
834c19800e8SDoug Rabson     NTLMInit init;
835c19800e8SDoug Rabson     NTLMInitReply initReply;
836c19800e8SDoug Rabson     NTLMRequest request;
837c19800e8SDoug Rabson     NTLMResponse response;
838c19800e8SDoug Rabson };
839c19800e8SDoug Rabson 
840*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_alloc(krb5_context context,krb5_ntlm * ntlm)841c19800e8SDoug Rabson krb5_ntlm_alloc(krb5_context context,
842c19800e8SDoug Rabson 		krb5_ntlm *ntlm)
843c19800e8SDoug Rabson {
844c19800e8SDoug Rabson     *ntlm = calloc(1, sizeof(**ntlm));
845c19800e8SDoug Rabson     if (*ntlm == NULL) {
846*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
847c19800e8SDoug Rabson 	return ENOMEM;
848c19800e8SDoug Rabson     }
849c19800e8SDoug Rabson     return 0;
850c19800e8SDoug Rabson }
851c19800e8SDoug Rabson 
852*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_free(krb5_context context,krb5_ntlm ntlm)853c19800e8SDoug Rabson krb5_ntlm_free(krb5_context context, krb5_ntlm ntlm)
854c19800e8SDoug Rabson {
855c19800e8SDoug Rabson     free_NTLMInit(&ntlm->init);
856c19800e8SDoug Rabson     free_NTLMInitReply(&ntlm->initReply);
857c19800e8SDoug Rabson     free_NTLMRequest(&ntlm->request);
858c19800e8SDoug Rabson     free_NTLMResponse(&ntlm->response);
859c19800e8SDoug Rabson     memset(ntlm, 0, sizeof(*ntlm));
860c19800e8SDoug Rabson     free(ntlm);
861c19800e8SDoug Rabson     return 0;
862c19800e8SDoug Rabson }
863c19800e8SDoug Rabson 
864c19800e8SDoug Rabson 
865*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_request(krb5_context context,krb5_ntlm ntlm,krb5_realm realm,krb5_ccache ccache,uint32_t flags,const char * hostname,const char * domainname)866c19800e8SDoug Rabson krb5_ntlm_init_request(krb5_context context,
867c19800e8SDoug Rabson 		       krb5_ntlm ntlm,
868c19800e8SDoug Rabson 		       krb5_realm realm,
869c19800e8SDoug Rabson 		       krb5_ccache ccache,
870c19800e8SDoug Rabson 		       uint32_t flags,
871c19800e8SDoug Rabson 		       const char *hostname,
872c19800e8SDoug Rabson 		       const char *domainname)
873c19800e8SDoug Rabson {
874c19800e8SDoug Rabson     DigestReqInner ireq;
875c19800e8SDoug Rabson     DigestRepInner irep;
876c19800e8SDoug Rabson     krb5_error_code ret;
877c19800e8SDoug Rabson 
878c19800e8SDoug Rabson     memset(&ireq, 0, sizeof(ireq));
879c19800e8SDoug Rabson     memset(&irep, 0, sizeof(irep));
880c19800e8SDoug Rabson 
881c19800e8SDoug Rabson     ntlm->init.flags = flags;
882c19800e8SDoug Rabson     if (hostname) {
883c19800e8SDoug Rabson 	ALLOC(ntlm->init.hostname, 1);
884c19800e8SDoug Rabson 	*ntlm->init.hostname = strdup(hostname);
885c19800e8SDoug Rabson     }
886c19800e8SDoug Rabson     if (domainname) {
887c19800e8SDoug Rabson 	ALLOC(ntlm->init.domain, 1);
888c19800e8SDoug Rabson 	*ntlm->init.domain = strdup(domainname);
889c19800e8SDoug Rabson     }
890c19800e8SDoug Rabson 
891c19800e8SDoug Rabson     ireq.element = choice_DigestReqInner_ntlmInit;
892c19800e8SDoug Rabson     ireq.u.ntlmInit = ntlm->init;
893c19800e8SDoug Rabson 
894c19800e8SDoug Rabson     ret = digest_request(context, realm, ccache,
895c19800e8SDoug Rabson 			 KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep);
896c19800e8SDoug Rabson     if (ret)
897c19800e8SDoug Rabson 	goto out;
898c19800e8SDoug Rabson 
899c19800e8SDoug Rabson     if (irep.element == choice_DigestRepInner_error) {
900c19800e8SDoug Rabson 	ret = irep.u.error.code;
901*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, N_("Digest init error: %s", ""),
902*ae771770SStanislav Sedov 			       irep.u.error.reason);
903c19800e8SDoug Rabson 	goto out;
904c19800e8SDoug Rabson     }
905c19800e8SDoug Rabson 
906c19800e8SDoug Rabson     if (irep.element != choice_DigestRepInner_ntlmInitReply) {
907c19800e8SDoug Rabson 	ret = EINVAL;
908*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
909*ae771770SStanislav Sedov 			       N_("ntlm reply not an initReply", ""));
910c19800e8SDoug Rabson 	goto out;
911c19800e8SDoug Rabson     }
912c19800e8SDoug Rabson 
913c19800e8SDoug Rabson     ret = copy_NTLMInitReply(&irep.u.ntlmInitReply, &ntlm->initReply);
914c19800e8SDoug Rabson     if (ret) {
915*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
916*ae771770SStanislav Sedov 			       N_("Failed to copy initReply", ""));
917c19800e8SDoug Rabson 	goto out;
918c19800e8SDoug Rabson     }
919c19800e8SDoug Rabson 
920c19800e8SDoug Rabson  out:
921c19800e8SDoug Rabson     free_DigestRepInner(&irep);
922c19800e8SDoug Rabson 
923c19800e8SDoug Rabson     return ret;
924c19800e8SDoug Rabson }
925c19800e8SDoug Rabson 
926*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_get_flags(krb5_context context,krb5_ntlm ntlm,uint32_t * flags)927c19800e8SDoug Rabson krb5_ntlm_init_get_flags(krb5_context context,
928c19800e8SDoug Rabson 			 krb5_ntlm ntlm,
929c19800e8SDoug Rabson 			 uint32_t *flags)
930c19800e8SDoug Rabson {
931c19800e8SDoug Rabson     *flags = ntlm->initReply.flags;
932c19800e8SDoug Rabson     return 0;
933c19800e8SDoug Rabson }
934c19800e8SDoug Rabson 
935*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_get_challange(krb5_context context,krb5_ntlm ntlm,krb5_data * challange)936c19800e8SDoug Rabson krb5_ntlm_init_get_challange(krb5_context context,
937c19800e8SDoug Rabson 			     krb5_ntlm ntlm,
938c19800e8SDoug Rabson 			     krb5_data *challange)
939c19800e8SDoug Rabson {
940c19800e8SDoug Rabson     krb5_error_code ret;
941c19800e8SDoug Rabson 
942c19800e8SDoug Rabson     ret = der_copy_octet_string(&ntlm->initReply.challange, challange);
943c19800e8SDoug Rabson     if (ret)
944*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
945c19800e8SDoug Rabson 
946c19800e8SDoug Rabson     return ret;
947c19800e8SDoug Rabson }
948c19800e8SDoug Rabson 
949*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_get_opaque(krb5_context context,krb5_ntlm ntlm,krb5_data * opaque)950c19800e8SDoug Rabson krb5_ntlm_init_get_opaque(krb5_context context,
951c19800e8SDoug Rabson 			  krb5_ntlm ntlm,
952c19800e8SDoug Rabson 			  krb5_data *opaque)
953c19800e8SDoug Rabson {
954c19800e8SDoug Rabson     krb5_error_code ret;
955c19800e8SDoug Rabson 
956c19800e8SDoug Rabson     ret = der_copy_octet_string(&ntlm->initReply.opaque, opaque);
957c19800e8SDoug Rabson     if (ret)
958*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
959c19800e8SDoug Rabson 
960c19800e8SDoug Rabson     return ret;
961c19800e8SDoug Rabson }
962c19800e8SDoug Rabson 
963*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_get_targetname(krb5_context context,krb5_ntlm ntlm,char ** name)964c19800e8SDoug Rabson krb5_ntlm_init_get_targetname(krb5_context context,
965c19800e8SDoug Rabson 			      krb5_ntlm ntlm,
966c19800e8SDoug Rabson 			      char **name)
967c19800e8SDoug Rabson {
968c19800e8SDoug Rabson     *name = strdup(ntlm->initReply.targetname);
969c19800e8SDoug Rabson     if (*name == NULL) {
970*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
971c19800e8SDoug Rabson 	return ENOMEM;
972c19800e8SDoug Rabson     }
973c19800e8SDoug Rabson     return 0;
974c19800e8SDoug Rabson }
975c19800e8SDoug Rabson 
976*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_init_get_targetinfo(krb5_context context,krb5_ntlm ntlm,krb5_data * data)977c19800e8SDoug Rabson krb5_ntlm_init_get_targetinfo(krb5_context context,
978c19800e8SDoug Rabson 			      krb5_ntlm ntlm,
979c19800e8SDoug Rabson 			      krb5_data *data)
980c19800e8SDoug Rabson {
981c19800e8SDoug Rabson     krb5_error_code ret;
982c19800e8SDoug Rabson 
983c19800e8SDoug Rabson     if (ntlm->initReply.targetinfo == NULL) {
984c19800e8SDoug Rabson 	krb5_data_zero(data);
985c19800e8SDoug Rabson 	return 0;
986c19800e8SDoug Rabson     }
987c19800e8SDoug Rabson 
988c19800e8SDoug Rabson     ret = krb5_data_copy(data,
989c19800e8SDoug Rabson 			 ntlm->initReply.targetinfo->data,
990c19800e8SDoug Rabson 			 ntlm->initReply.targetinfo->length);
991c19800e8SDoug Rabson     if (ret) {
992*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
993c19800e8SDoug Rabson 	return ret;
994c19800e8SDoug Rabson     }
995c19800e8SDoug Rabson     return 0;
996c19800e8SDoug Rabson }
997c19800e8SDoug Rabson 
998c19800e8SDoug Rabson 
999*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_request(krb5_context context,krb5_ntlm ntlm,krb5_realm realm,krb5_ccache ccache)1000c19800e8SDoug Rabson krb5_ntlm_request(krb5_context context,
1001c19800e8SDoug Rabson 		  krb5_ntlm ntlm,
1002c19800e8SDoug Rabson 		  krb5_realm realm,
1003c19800e8SDoug Rabson 		  krb5_ccache ccache)
1004c19800e8SDoug Rabson {
1005c19800e8SDoug Rabson     DigestReqInner ireq;
1006c19800e8SDoug Rabson     DigestRepInner irep;
1007c19800e8SDoug Rabson     krb5_error_code ret;
1008c19800e8SDoug Rabson 
1009c19800e8SDoug Rabson     memset(&ireq, 0, sizeof(ireq));
1010c19800e8SDoug Rabson     memset(&irep, 0, sizeof(irep));
1011c19800e8SDoug Rabson 
1012c19800e8SDoug Rabson     ireq.element = choice_DigestReqInner_ntlmRequest;
1013c19800e8SDoug Rabson     ireq.u.ntlmRequest = ntlm->request;
1014c19800e8SDoug Rabson 
1015c19800e8SDoug Rabson     ret = digest_request(context, realm, ccache,
1016c19800e8SDoug Rabson 			 KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep);
1017c19800e8SDoug Rabson     if (ret)
1018c19800e8SDoug Rabson 	return ret;
1019c19800e8SDoug Rabson 
1020c19800e8SDoug Rabson     if (irep.element == choice_DigestRepInner_error) {
1021c19800e8SDoug Rabson 	ret = irep.u.error.code;
1022*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
1023*ae771770SStanislav Sedov 			       N_("NTLM response error: %s", ""),
1024*ae771770SStanislav Sedov 			       irep.u.error.reason);
1025c19800e8SDoug Rabson 	goto out;
1026c19800e8SDoug Rabson     }
1027c19800e8SDoug Rabson 
1028c19800e8SDoug Rabson     if (irep.element != choice_DigestRepInner_ntlmResponse) {
1029c19800e8SDoug Rabson 	ret = EINVAL;
1030*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
1031*ae771770SStanislav Sedov 			       N_("NTLM reply not an NTLMResponse", ""));
1032c19800e8SDoug Rabson 	goto out;
1033c19800e8SDoug Rabson     }
1034c19800e8SDoug Rabson 
1035c19800e8SDoug Rabson     ret = copy_NTLMResponse(&irep.u.ntlmResponse, &ntlm->response);
1036c19800e8SDoug Rabson     if (ret) {
1037*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
1038*ae771770SStanislav Sedov 			       N_("Failed to copy NTLMResponse", ""));
1039c19800e8SDoug Rabson 	goto out;
1040c19800e8SDoug Rabson     }
1041c19800e8SDoug Rabson 
1042c19800e8SDoug Rabson  out:
1043c19800e8SDoug Rabson     free_DigestRepInner(&irep);
1044c19800e8SDoug Rabson 
1045c19800e8SDoug Rabson     return ret;
1046c19800e8SDoug Rabson }
1047c19800e8SDoug Rabson 
1048*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_flags(krb5_context context,krb5_ntlm ntlm,uint32_t flags)1049c19800e8SDoug Rabson krb5_ntlm_req_set_flags(krb5_context context,
1050c19800e8SDoug Rabson 			krb5_ntlm ntlm,
1051c19800e8SDoug Rabson 			uint32_t flags)
1052c19800e8SDoug Rabson {
1053c19800e8SDoug Rabson     ntlm->request.flags = flags;
1054c19800e8SDoug Rabson     return 0;
1055c19800e8SDoug Rabson }
1056c19800e8SDoug Rabson 
1057*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_username(krb5_context context,krb5_ntlm ntlm,const char * username)1058c19800e8SDoug Rabson krb5_ntlm_req_set_username(krb5_context context,
1059c19800e8SDoug Rabson 			   krb5_ntlm ntlm,
1060c19800e8SDoug Rabson 			   const char *username)
1061c19800e8SDoug Rabson {
1062c19800e8SDoug Rabson     ntlm->request.username = strdup(username);
1063c19800e8SDoug Rabson     if (ntlm->request.username == NULL) {
1064*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1065c19800e8SDoug Rabson 	return ENOMEM;
1066c19800e8SDoug Rabson     }
1067c19800e8SDoug Rabson     return 0;
1068c19800e8SDoug Rabson }
1069c19800e8SDoug Rabson 
1070*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_targetname(krb5_context context,krb5_ntlm ntlm,const char * targetname)1071c19800e8SDoug Rabson krb5_ntlm_req_set_targetname(krb5_context context,
1072c19800e8SDoug Rabson 			     krb5_ntlm ntlm,
1073c19800e8SDoug Rabson 			     const char *targetname)
1074c19800e8SDoug Rabson {
1075c19800e8SDoug Rabson     ntlm->request.targetname = strdup(targetname);
1076c19800e8SDoug Rabson     if (ntlm->request.targetname == NULL) {
1077*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1078c19800e8SDoug Rabson 	return ENOMEM;
1079c19800e8SDoug Rabson     }
1080c19800e8SDoug Rabson     return 0;
1081c19800e8SDoug Rabson }
1082c19800e8SDoug Rabson 
1083*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_lm(krb5_context context,krb5_ntlm ntlm,void * hash,size_t len)1084c19800e8SDoug Rabson krb5_ntlm_req_set_lm(krb5_context context,
1085c19800e8SDoug Rabson 		     krb5_ntlm ntlm,
1086c19800e8SDoug Rabson 		     void *hash, size_t len)
1087c19800e8SDoug Rabson {
1088c19800e8SDoug Rabson     ntlm->request.lm.data = malloc(len);
1089*ae771770SStanislav Sedov     if (ntlm->request.lm.data == NULL && len != 0) {
1090*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1091c19800e8SDoug Rabson 	return ENOMEM;
1092c19800e8SDoug Rabson     }
1093c19800e8SDoug Rabson     ntlm->request.lm.length = len;
1094c19800e8SDoug Rabson     memcpy(ntlm->request.lm.data, hash, len);
1095c19800e8SDoug Rabson     return 0;
1096c19800e8SDoug Rabson }
1097c19800e8SDoug Rabson 
1098*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_ntlm(krb5_context context,krb5_ntlm ntlm,void * hash,size_t len)1099c19800e8SDoug Rabson krb5_ntlm_req_set_ntlm(krb5_context context,
1100c19800e8SDoug Rabson 		       krb5_ntlm ntlm,
1101c19800e8SDoug Rabson 		       void *hash, size_t len)
1102c19800e8SDoug Rabson {
1103c19800e8SDoug Rabson     ntlm->request.ntlm.data = malloc(len);
1104*ae771770SStanislav Sedov     if (ntlm->request.ntlm.data == NULL && len != 0) {
1105*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1106c19800e8SDoug Rabson 	return ENOMEM;
1107c19800e8SDoug Rabson     }
1108c19800e8SDoug Rabson     ntlm->request.ntlm.length = len;
1109c19800e8SDoug Rabson     memcpy(ntlm->request.ntlm.data, hash, len);
1110c19800e8SDoug Rabson     return 0;
1111c19800e8SDoug Rabson }
1112c19800e8SDoug Rabson 
1113*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_opaque(krb5_context context,krb5_ntlm ntlm,krb5_data * opaque)1114c19800e8SDoug Rabson krb5_ntlm_req_set_opaque(krb5_context context,
1115c19800e8SDoug Rabson 			 krb5_ntlm ntlm,
1116c19800e8SDoug Rabson 			 krb5_data *opaque)
1117c19800e8SDoug Rabson {
1118c19800e8SDoug Rabson     ntlm->request.opaque.data = malloc(opaque->length);
1119*ae771770SStanislav Sedov     if (ntlm->request.opaque.data == NULL && opaque->length != 0) {
1120*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1121c19800e8SDoug Rabson 	return ENOMEM;
1122c19800e8SDoug Rabson     }
1123c19800e8SDoug Rabson     ntlm->request.opaque.length = opaque->length;
1124c19800e8SDoug Rabson     memcpy(ntlm->request.opaque.data, opaque->data, opaque->length);
1125c19800e8SDoug Rabson     return 0;
1126c19800e8SDoug Rabson }
1127c19800e8SDoug Rabson 
1128*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_req_set_session(krb5_context context,krb5_ntlm ntlm,void * sessionkey,size_t length)1129c19800e8SDoug Rabson krb5_ntlm_req_set_session(krb5_context context,
1130c19800e8SDoug Rabson 			  krb5_ntlm ntlm,
1131c19800e8SDoug Rabson 			  void *sessionkey, size_t length)
1132c19800e8SDoug Rabson {
1133c19800e8SDoug Rabson     ntlm->request.sessionkey = calloc(1, sizeof(*ntlm->request.sessionkey));
1134c19800e8SDoug Rabson     if (ntlm->request.sessionkey == NULL) {
1135*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1136c19800e8SDoug Rabson 	return ENOMEM;
1137c19800e8SDoug Rabson     }
1138c19800e8SDoug Rabson     ntlm->request.sessionkey->data = malloc(length);
1139*ae771770SStanislav Sedov     if (ntlm->request.sessionkey->data == NULL && length != 0) {
1140*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1141c19800e8SDoug Rabson 	return ENOMEM;
1142c19800e8SDoug Rabson     }
1143c19800e8SDoug Rabson     memcpy(ntlm->request.sessionkey->data, sessionkey, length);
1144c19800e8SDoug Rabson     ntlm->request.sessionkey->length = length;
1145c19800e8SDoug Rabson     return 0;
1146c19800e8SDoug Rabson }
1147c19800e8SDoug Rabson 
1148*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_ntlm_rep_get_status(krb5_context context,krb5_ntlm ntlm)1149c19800e8SDoug Rabson krb5_ntlm_rep_get_status(krb5_context context,
1150c19800e8SDoug Rabson 			 krb5_ntlm ntlm)
1151c19800e8SDoug Rabson {
1152c19800e8SDoug Rabson     return ntlm->response.success ? TRUE : FALSE;
1153c19800e8SDoug Rabson }
1154c19800e8SDoug Rabson 
1155*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ntlm_rep_get_sessionkey(krb5_context context,krb5_ntlm ntlm,krb5_data * data)1156c19800e8SDoug Rabson krb5_ntlm_rep_get_sessionkey(krb5_context context,
1157c19800e8SDoug Rabson 			     krb5_ntlm ntlm,
1158c19800e8SDoug Rabson 			     krb5_data *data)
1159c19800e8SDoug Rabson {
1160c19800e8SDoug Rabson     if (ntlm->response.sessionkey == NULL) {
1161*ae771770SStanislav Sedov 	krb5_set_error_message(context, EINVAL,
1162*ae771770SStanislav Sedov 			       N_("no ntlm session key", ""));
1163c19800e8SDoug Rabson 	return EINVAL;
1164c19800e8SDoug Rabson     }
1165*ae771770SStanislav Sedov     krb5_clear_error_message(context);
1166c19800e8SDoug Rabson     return krb5_data_copy(data,
1167c19800e8SDoug Rabson 			  ntlm->response.sessionkey->data,
1168c19800e8SDoug Rabson 			  ntlm->response.sessionkey->length);
1169c19800e8SDoug Rabson }
1170c19800e8SDoug Rabson 
1171c19800e8SDoug Rabson /**
1172c19800e8SDoug Rabson  * Get the supported/allowed mechanism for this principal.
1173c19800e8SDoug Rabson  *
1174c19800e8SDoug Rabson  * @param context A Keberos context.
1175c19800e8SDoug Rabson  * @param realm The realm of the KDC.
1176c19800e8SDoug Rabson  * @param ccache The credential cache to use when talking to the KDC.
1177c19800e8SDoug Rabson  * @param flags The supported mechanism.
1178c19800e8SDoug Rabson  *
1179c19800e8SDoug Rabson  * @return Return an error code or 0.
1180c19800e8SDoug Rabson  *
1181c19800e8SDoug Rabson  * @ingroup krb5_digest
1182c19800e8SDoug Rabson  */
1183c19800e8SDoug Rabson 
1184*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_digest_probe(krb5_context context,krb5_realm realm,krb5_ccache ccache,unsigned * flags)1185c19800e8SDoug Rabson krb5_digest_probe(krb5_context context,
1186c19800e8SDoug Rabson 		  krb5_realm realm,
1187c19800e8SDoug Rabson 		  krb5_ccache ccache,
1188c19800e8SDoug Rabson 		  unsigned *flags)
1189c19800e8SDoug Rabson {
1190c19800e8SDoug Rabson     DigestReqInner ireq;
1191c19800e8SDoug Rabson     DigestRepInner irep;
1192c19800e8SDoug Rabson     krb5_error_code ret;
1193c19800e8SDoug Rabson 
1194c19800e8SDoug Rabson     memset(&ireq, 0, sizeof(ireq));
1195c19800e8SDoug Rabson     memset(&irep, 0, sizeof(irep));
1196c19800e8SDoug Rabson 
1197c19800e8SDoug Rabson     ireq.element = choice_DigestReqInner_supportedMechs;
1198c19800e8SDoug Rabson 
1199c19800e8SDoug Rabson     ret = digest_request(context, realm, ccache,
1200c19800e8SDoug Rabson 			 KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep);
1201c19800e8SDoug Rabson     if (ret)
1202c19800e8SDoug Rabson 	goto out;
1203c19800e8SDoug Rabson 
1204c19800e8SDoug Rabson     if (irep.element == choice_DigestRepInner_error) {
1205c19800e8SDoug Rabson 	ret = irep.u.error.code;
1206*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, "Digest probe error: %s",
1207*ae771770SStanislav Sedov 			       irep.u.error.reason);
1208c19800e8SDoug Rabson 	goto out;
1209c19800e8SDoug Rabson     }
1210c19800e8SDoug Rabson 
1211c19800e8SDoug Rabson     if (irep.element != choice_DigestRepInner_supportedMechs) {
1212c19800e8SDoug Rabson 	ret = EINVAL;
1213*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret, "Digest reply not an probe");
1214c19800e8SDoug Rabson 	goto out;
1215c19800e8SDoug Rabson     }
1216c19800e8SDoug Rabson 
1217c19800e8SDoug Rabson     *flags = DigestTypes2int(irep.u.supportedMechs);
1218c19800e8SDoug Rabson 
1219c19800e8SDoug Rabson  out:
1220c19800e8SDoug Rabson     free_DigestRepInner(&irep);
1221c19800e8SDoug Rabson 
1222c19800e8SDoug Rabson     return ret;
1223c19800e8SDoug Rabson }
1224*ae771770SStanislav Sedov 
1225*ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */
1226