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