xref: /minix3/crypto/external/bsd/heimdal/dist/kuser/kdigest.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: kdigest.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2006 - 2007 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 #define HC_DEPRECATED_CRYPTO
37ebfedea0SLionel Sambuc 
38ebfedea0SLionel Sambuc #include "kuser_locl.h"
39ebfedea0SLionel Sambuc 
40ebfedea0SLionel Sambuc #include <kdigest-commands.h>
41ebfedea0SLionel Sambuc #include <krb5/hex.h>
42ebfedea0SLionel Sambuc #include <krb5/base64.h>
43ebfedea0SLionel Sambuc #include <krb5/heimntlm.h>
44ebfedea0SLionel Sambuc #include "crypto-headers.h"
45ebfedea0SLionel Sambuc 
46ebfedea0SLionel Sambuc static int version_flag = 0;
47ebfedea0SLionel Sambuc static int help_flag	= 0;
48ebfedea0SLionel Sambuc static char *ccache_string;
49ebfedea0SLionel Sambuc static krb5_ccache id;
50ebfedea0SLionel Sambuc 
51ebfedea0SLionel Sambuc static struct getargs args[] = {
52ebfedea0SLionel Sambuc     {"ccache",	0,	arg_string,	&ccache_string, "credential cache", NULL },
53ebfedea0SLionel Sambuc     {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
54ebfedea0SLionel Sambuc     {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
55ebfedea0SLionel Sambuc };
56ebfedea0SLionel Sambuc 
57ebfedea0SLionel Sambuc static void
usage(int ret)58ebfedea0SLionel Sambuc usage (int ret)
59ebfedea0SLionel Sambuc {
60ebfedea0SLionel Sambuc     arg_printusage (args, sizeof(args)/sizeof(*args),
61ebfedea0SLionel Sambuc 		    NULL, "");
62ebfedea0SLionel Sambuc     exit (ret);
63ebfedea0SLionel Sambuc }
64ebfedea0SLionel Sambuc 
65ebfedea0SLionel Sambuc static krb5_context context;
66ebfedea0SLionel Sambuc 
67ebfedea0SLionel Sambuc int
digest_probe(struct digest_probe_options * opt,int argc,char ** argv)68ebfedea0SLionel Sambuc digest_probe(struct digest_probe_options *opt,
69ebfedea0SLionel Sambuc 	     int argc, char ** argv)
70ebfedea0SLionel Sambuc {
71ebfedea0SLionel Sambuc     krb5_error_code ret;
72ebfedea0SLionel Sambuc     krb5_realm realm;
73ebfedea0SLionel Sambuc     unsigned flags;
74ebfedea0SLionel Sambuc 
75ebfedea0SLionel Sambuc     realm = opt->realm_string;
76ebfedea0SLionel Sambuc 
77ebfedea0SLionel Sambuc     if (realm == NULL)
78ebfedea0SLionel Sambuc 	errx(1, "realm missing");
79ebfedea0SLionel Sambuc 
80ebfedea0SLionel Sambuc     ret = krb5_digest_probe(context, realm, id, &flags);
81ebfedea0SLionel Sambuc     if (ret)
82ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "digest_probe");
83ebfedea0SLionel Sambuc 
84ebfedea0SLionel Sambuc     printf("flags: %u\n", flags);
85ebfedea0SLionel Sambuc 
86ebfedea0SLionel Sambuc     return 0;
87ebfedea0SLionel Sambuc }
88ebfedea0SLionel Sambuc 
89ebfedea0SLionel Sambuc int
digest_server_init(struct digest_server_init_options * opt,int argc,char ** argv)90ebfedea0SLionel Sambuc digest_server_init(struct digest_server_init_options *opt,
91ebfedea0SLionel Sambuc 		   int argc, char ** argv)
92ebfedea0SLionel Sambuc {
93ebfedea0SLionel Sambuc     krb5_error_code ret;
94ebfedea0SLionel Sambuc     krb5_digest digest;
95ebfedea0SLionel Sambuc 
96ebfedea0SLionel Sambuc     ret = krb5_digest_alloc(context, &digest);
97ebfedea0SLionel Sambuc     if (ret)
98ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "digest_alloc");
99ebfedea0SLionel Sambuc 
100ebfedea0SLionel Sambuc     ret = krb5_digest_set_type(context, digest, opt->type_string);
101ebfedea0SLionel Sambuc     if (ret)
102ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_type");
103ebfedea0SLionel Sambuc 
104ebfedea0SLionel Sambuc     if (opt->cb_type_string && opt->cb_value_string) {
105ebfedea0SLionel Sambuc 	ret = krb5_digest_set_server_cb(context, digest,
106ebfedea0SLionel Sambuc 					opt->cb_type_string,
107ebfedea0SLionel Sambuc 					opt->cb_value_string);
108ebfedea0SLionel Sambuc 	if (ret)
109ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_digest_set_server_cb");
110ebfedea0SLionel Sambuc     }
111ebfedea0SLionel Sambuc     ret = krb5_digest_init_request(context,
112ebfedea0SLionel Sambuc 				   digest,
113ebfedea0SLionel Sambuc 				   opt->kerberos_realm_string,
114ebfedea0SLionel Sambuc 				   id);
115ebfedea0SLionel Sambuc     if (ret)
116ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_init_request");
117ebfedea0SLionel Sambuc 
118ebfedea0SLionel Sambuc     printf("type=%s\n", opt->type_string);
119ebfedea0SLionel Sambuc     printf("server-nonce=%s\n",
120ebfedea0SLionel Sambuc 	   krb5_digest_get_server_nonce(context, digest));
121ebfedea0SLionel Sambuc     {
122ebfedea0SLionel Sambuc 	const char *s = krb5_digest_get_identifier(context, digest);
123ebfedea0SLionel Sambuc 	if (s)
124ebfedea0SLionel Sambuc 	    printf("identifier=%s\n", s);
125ebfedea0SLionel Sambuc     }
126ebfedea0SLionel Sambuc     printf("opaque=%s\n", krb5_digest_get_opaque(context, digest));
127ebfedea0SLionel Sambuc 
128ebfedea0SLionel Sambuc     krb5_digest_free(digest);
129ebfedea0SLionel Sambuc 
130ebfedea0SLionel Sambuc     return 0;
131ebfedea0SLionel Sambuc }
132ebfedea0SLionel Sambuc 
133ebfedea0SLionel Sambuc int
digest_server_request(struct digest_server_request_options * opt,int argc,char ** argv)134ebfedea0SLionel Sambuc digest_server_request(struct digest_server_request_options *opt,
135ebfedea0SLionel Sambuc 		      int argc, char **argv)
136ebfedea0SLionel Sambuc {
137ebfedea0SLionel Sambuc     krb5_error_code ret;
138ebfedea0SLionel Sambuc     krb5_digest digest;
139ebfedea0SLionel Sambuc     const char *status, *rsp;
140ebfedea0SLionel Sambuc     krb5_data session_key;
141ebfedea0SLionel Sambuc 
142ebfedea0SLionel Sambuc     if (opt->server_nonce_string == NULL)
143ebfedea0SLionel Sambuc 	errx(1, "server nonce missing");
144ebfedea0SLionel Sambuc     if (opt->type_string == NULL)
145ebfedea0SLionel Sambuc 	errx(1, "type missing");
146ebfedea0SLionel Sambuc     if (opt->opaque_string == NULL)
147ebfedea0SLionel Sambuc 	errx(1, "opaque missing");
148ebfedea0SLionel Sambuc     if (opt->client_response_string == NULL)
149ebfedea0SLionel Sambuc 	errx(1, "client response missing");
150ebfedea0SLionel Sambuc 
151ebfedea0SLionel Sambuc     ret = krb5_digest_alloc(context, &digest);
152ebfedea0SLionel Sambuc     if (ret)
153ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "digest_alloc");
154ebfedea0SLionel Sambuc 
155ebfedea0SLionel Sambuc     if (strcasecmp(opt->type_string, "CHAP") == 0) {
156ebfedea0SLionel Sambuc 	if (opt->server_identifier_string == NULL)
157ebfedea0SLionel Sambuc 	    errx(1, "server identifier missing");
158ebfedea0SLionel Sambuc 
159ebfedea0SLionel Sambuc 	ret = krb5_digest_set_identifier(context, digest,
160ebfedea0SLionel Sambuc 					 opt->server_identifier_string);
161ebfedea0SLionel Sambuc 	if (ret)
162ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_digest_set_type");
163ebfedea0SLionel Sambuc     }
164ebfedea0SLionel Sambuc 
165ebfedea0SLionel Sambuc     ret = krb5_digest_set_type(context, digest, opt->type_string);
166ebfedea0SLionel Sambuc     if (ret)
167ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_type");
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc     ret = krb5_digest_set_username(context, digest, opt->username_string);
170ebfedea0SLionel Sambuc     if (ret)
171ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_username");
172ebfedea0SLionel Sambuc 
173ebfedea0SLionel Sambuc     ret = krb5_digest_set_server_nonce(context, digest,
174ebfedea0SLionel Sambuc 				       opt->server_nonce_string);
175ebfedea0SLionel Sambuc     if (ret)
176ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_server_nonce");
177ebfedea0SLionel Sambuc 
178ebfedea0SLionel Sambuc     if(opt->client_nonce_string) {
179ebfedea0SLionel Sambuc 	ret = krb5_digest_set_client_nonce(context, digest,
180ebfedea0SLionel Sambuc 					   opt->client_nonce_string);
181ebfedea0SLionel Sambuc 	if (ret)
182ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_digest_set_client_nonce");
183ebfedea0SLionel Sambuc     }
184ebfedea0SLionel Sambuc 
185ebfedea0SLionel Sambuc 
186ebfedea0SLionel Sambuc     ret = krb5_digest_set_opaque(context, digest, opt->opaque_string);
187ebfedea0SLionel Sambuc     if (ret)
188ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_opaque");
189ebfedea0SLionel Sambuc 
190ebfedea0SLionel Sambuc     ret = krb5_digest_set_responseData(context, digest,
191ebfedea0SLionel Sambuc 				       opt->client_response_string);
192ebfedea0SLionel Sambuc     if (ret)
193ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_set_responseData");
194ebfedea0SLionel Sambuc 
195ebfedea0SLionel Sambuc     ret = krb5_digest_request(context, digest,
196ebfedea0SLionel Sambuc 			      opt->kerberos_realm_string, id);
197ebfedea0SLionel Sambuc     if (ret)
198ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_request");
199ebfedea0SLionel Sambuc 
200ebfedea0SLionel Sambuc     status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed";
201ebfedea0SLionel Sambuc     rsp = krb5_digest_get_rsp(context, digest);
202ebfedea0SLionel Sambuc 
203ebfedea0SLionel Sambuc     printf("status=%s\n", status);
204ebfedea0SLionel Sambuc     if (rsp)
205ebfedea0SLionel Sambuc 	printf("rsp=%s\n", rsp);
206ebfedea0SLionel Sambuc     printf("tickets=no\n");
207ebfedea0SLionel Sambuc 
208ebfedea0SLionel Sambuc     ret = krb5_digest_get_session_key(context, digest, &session_key);
209ebfedea0SLionel Sambuc     if (ret)
210ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_digest_get_session_key");
211ebfedea0SLionel Sambuc 
212ebfedea0SLionel Sambuc     if (session_key.length) {
213ebfedea0SLionel Sambuc 	char *key;
214ebfedea0SLionel Sambuc 	hex_encode(session_key.data, session_key.length, &key);
215ebfedea0SLionel Sambuc 	if (key == NULL)
216ebfedea0SLionel Sambuc 	    krb5_errx(context, 1, "hex_encode");
217ebfedea0SLionel Sambuc 	krb5_data_free(&session_key);
218ebfedea0SLionel Sambuc 	printf("session-key=%s\n", key);
219ebfedea0SLionel Sambuc 	free(key);
220ebfedea0SLionel Sambuc     }
221ebfedea0SLionel Sambuc 
222ebfedea0SLionel Sambuc     krb5_digest_free(digest);
223ebfedea0SLionel Sambuc 
224ebfedea0SLionel Sambuc     return 0;
225ebfedea0SLionel Sambuc }
226ebfedea0SLionel Sambuc 
227ebfedea0SLionel Sambuc static void
client_chap(const void * server_nonce,size_t snoncelen,unsigned char server_identifier,const char * password)228ebfedea0SLionel Sambuc client_chap(const void *server_nonce, size_t snoncelen,
229ebfedea0SLionel Sambuc 	    unsigned char server_identifier,
230ebfedea0SLionel Sambuc 	    const char *password)
231ebfedea0SLionel Sambuc {
232ebfedea0SLionel Sambuc     EVP_MD_CTX *ctx;
233ebfedea0SLionel Sambuc     unsigned char md[MD5_DIGEST_LENGTH];
234ebfedea0SLionel Sambuc     char *h;
235ebfedea0SLionel Sambuc 
236ebfedea0SLionel Sambuc     ctx = EVP_MD_CTX_create();
237ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
238ebfedea0SLionel Sambuc 
239ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, &server_identifier, 1);
240ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, password, strlen(password));
241ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, server_nonce, snoncelen);
242ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, md, NULL);
243ebfedea0SLionel Sambuc 
244ebfedea0SLionel Sambuc     EVP_MD_CTX_destroy(ctx);
245ebfedea0SLionel Sambuc 
246ebfedea0SLionel Sambuc     hex_encode(md, 16, &h);
247ebfedea0SLionel Sambuc 
248ebfedea0SLionel Sambuc     printf("responseData=%s\n", h);
249ebfedea0SLionel Sambuc     free(h);
250ebfedea0SLionel Sambuc }
251ebfedea0SLionel Sambuc 
252ebfedea0SLionel Sambuc static const unsigned char ms_chap_v2_magic1[39] = {
253ebfedea0SLionel Sambuc     0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
254ebfedea0SLionel Sambuc     0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
255ebfedea0SLionel Sambuc     0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
256ebfedea0SLionel Sambuc     0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
257ebfedea0SLionel Sambuc };
258ebfedea0SLionel Sambuc static const unsigned char ms_chap_v2_magic2[41] = {
259ebfedea0SLionel Sambuc     0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
260ebfedea0SLionel Sambuc     0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
261ebfedea0SLionel Sambuc     0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
262ebfedea0SLionel Sambuc     0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
263ebfedea0SLionel Sambuc     0x6E
264ebfedea0SLionel Sambuc };
265ebfedea0SLionel Sambuc static const unsigned char ms_rfc3079_magic1[27] = {
266ebfedea0SLionel Sambuc     0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
267ebfedea0SLionel Sambuc     0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
268ebfedea0SLionel Sambuc     0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
269ebfedea0SLionel Sambuc };
270ebfedea0SLionel Sambuc 
271ebfedea0SLionel Sambuc static void
client_mschapv2(const void * server_nonce,size_t snoncelen,const void * client_nonce,size_t cnoncelen,const char * username,const char * password)272ebfedea0SLionel Sambuc client_mschapv2(const void *server_nonce, size_t snoncelen,
273ebfedea0SLionel Sambuc 		const void *client_nonce, size_t cnoncelen,
274ebfedea0SLionel Sambuc 		const char *username,
275ebfedea0SLionel Sambuc 		const char *password)
276ebfedea0SLionel Sambuc {
277ebfedea0SLionel Sambuc     EVP_MD_CTX *hctx, *ctx;
278ebfedea0SLionel Sambuc     unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH];
279ebfedea0SLionel Sambuc     unsigned char hmd[MD4_DIGEST_LENGTH];
280ebfedea0SLionel Sambuc     struct ntlm_buf answer;
281ebfedea0SLionel Sambuc     int i, len, ret;
282ebfedea0SLionel Sambuc     char *h;
283ebfedea0SLionel Sambuc 
284ebfedea0SLionel Sambuc     ctx = EVP_MD_CTX_create();
285ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
286ebfedea0SLionel Sambuc 
287ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, client_nonce, cnoncelen);
288ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, server_nonce, snoncelen);
289ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, username, strlen(username));
290ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, md, NULL);
291ebfedea0SLionel Sambuc 
292ebfedea0SLionel Sambuc 
293ebfedea0SLionel Sambuc     hctx = EVP_MD_CTX_create();
294ebfedea0SLionel Sambuc     EVP_DigestInit_ex(hctx, EVP_md4(), NULL);
295ebfedea0SLionel Sambuc     len = strlen(password);
296ebfedea0SLionel Sambuc     for (i = 0; i < len; i++) {
297ebfedea0SLionel Sambuc 	EVP_DigestUpdate(hctx, &password[i], 1);
298ebfedea0SLionel Sambuc 	EVP_DigestUpdate(hctx, &password[len], 1);
299ebfedea0SLionel Sambuc     }
300ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(hctx, hmd, NULL);
301ebfedea0SLionel Sambuc 
302ebfedea0SLionel Sambuc 
303ebfedea0SLionel Sambuc     /* ChallengeResponse */
304ebfedea0SLionel Sambuc     ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer);
305ebfedea0SLionel Sambuc     if (ret)
306ebfedea0SLionel Sambuc 	errx(1, "heim_ntlm_calculate_ntlm1");
307ebfedea0SLionel Sambuc 
308ebfedea0SLionel Sambuc     hex_encode(answer.data, answer.length, &h);
309ebfedea0SLionel Sambuc     printf("responseData=%s\n", h);
310ebfedea0SLionel Sambuc     free(h);
311ebfedea0SLionel Sambuc 
312ebfedea0SLionel Sambuc     /* PasswordHash */
313ebfedea0SLionel Sambuc     EVP_DigestInit_ex(hctx, EVP_md4(), NULL);
314ebfedea0SLionel Sambuc     EVP_DigestUpdate(hctx, hmd, sizeof(hmd));
315ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(hctx, hmd, NULL);
316ebfedea0SLionel Sambuc 
317ebfedea0SLionel Sambuc 
318ebfedea0SLionel Sambuc     /* GenerateAuthenticatorResponse */
319ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
320ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, hmd, sizeof(hmd));
321ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, answer.data, answer.length);
322ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1));
323ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, md, NULL);
324ebfedea0SLionel Sambuc 
325ebfedea0SLionel Sambuc     /* ChallengeHash */
326ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
327ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, client_nonce, cnoncelen);
328ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, server_nonce, snoncelen);
329ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, username, strlen(username));
330ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, challenge, NULL);
331ebfedea0SLionel Sambuc 
332ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
333ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, md, sizeof(md));
334ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, challenge, 8);
335ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));
336ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, md, NULL);
337ebfedea0SLionel Sambuc 
338ebfedea0SLionel Sambuc     hex_encode(md, sizeof(md), &h);
339ebfedea0SLionel Sambuc     printf("AuthenticatorResponse=%s\n", h);
340ebfedea0SLionel Sambuc     free(h);
341ebfedea0SLionel Sambuc 
342ebfedea0SLionel Sambuc     /* get_master, rfc 3079 3.4 */
343ebfedea0SLionel Sambuc     EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
344ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, hmd, sizeof(hmd));
345ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, answer.data, answer.length);
346ebfedea0SLionel Sambuc     EVP_DigestUpdate(ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));
347ebfedea0SLionel Sambuc     EVP_DigestFinal_ex(ctx, md, NULL);
348ebfedea0SLionel Sambuc 
349ebfedea0SLionel Sambuc     free(answer.data);
350ebfedea0SLionel Sambuc 
351ebfedea0SLionel Sambuc     hex_encode(md, 16, &h);
352ebfedea0SLionel Sambuc     printf("session-key=%s\n", h);
353ebfedea0SLionel Sambuc     free(h);
354ebfedea0SLionel Sambuc 
355ebfedea0SLionel Sambuc     EVP_MD_CTX_destroy(hctx);
356ebfedea0SLionel Sambuc     EVP_MD_CTX_destroy(ctx);
357ebfedea0SLionel Sambuc }
358ebfedea0SLionel Sambuc 
359ebfedea0SLionel Sambuc 
360ebfedea0SLionel Sambuc int
digest_client_request(struct digest_client_request_options * opt,int argc,char ** argv)361ebfedea0SLionel Sambuc digest_client_request(struct digest_client_request_options *opt,
362ebfedea0SLionel Sambuc 		      int argc, char **argv)
363ebfedea0SLionel Sambuc {
364ebfedea0SLionel Sambuc     char *server_nonce, *client_nonce = NULL, server_identifier;
365ebfedea0SLionel Sambuc     ssize_t snoncelen, cnoncelen = 0;
366ebfedea0SLionel Sambuc 
367ebfedea0SLionel Sambuc     if (opt->server_nonce_string == NULL)
368ebfedea0SLionel Sambuc 	errx(1, "server nonce missing");
369ebfedea0SLionel Sambuc     if (opt->password_string == NULL)
370ebfedea0SLionel Sambuc 	errx(1, "password missing");
371ebfedea0SLionel Sambuc 
372ebfedea0SLionel Sambuc     if (opt->opaque_string == NULL)
373ebfedea0SLionel Sambuc 	errx(1, "opaque missing");
374ebfedea0SLionel Sambuc 
375ebfedea0SLionel Sambuc     snoncelen = strlen(opt->server_nonce_string);
376ebfedea0SLionel Sambuc     server_nonce = malloc(snoncelen);
377ebfedea0SLionel Sambuc     if (server_nonce == NULL)
378ebfedea0SLionel Sambuc 	errx(1, "server_nonce");
379ebfedea0SLionel Sambuc 
380ebfedea0SLionel Sambuc     snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen);
381ebfedea0SLionel Sambuc     if (snoncelen <= 0)
382ebfedea0SLionel Sambuc 	errx(1, "server nonce wrong");
383ebfedea0SLionel Sambuc 
384ebfedea0SLionel Sambuc     if (opt->client_nonce_string) {
385ebfedea0SLionel Sambuc 	cnoncelen = strlen(opt->client_nonce_string);
386ebfedea0SLionel Sambuc 	client_nonce = malloc(cnoncelen);
387ebfedea0SLionel Sambuc 	if (client_nonce == NULL)
388ebfedea0SLionel Sambuc 	    errx(1, "client_nonce");
389ebfedea0SLionel Sambuc 
390ebfedea0SLionel Sambuc 	cnoncelen = hex_decode(opt->client_nonce_string,
391ebfedea0SLionel Sambuc 			       client_nonce, cnoncelen);
392ebfedea0SLionel Sambuc 	if (cnoncelen <= 0)
393ebfedea0SLionel Sambuc 	    errx(1, "client nonce wrong");
394ebfedea0SLionel Sambuc     }
395ebfedea0SLionel Sambuc 
396ebfedea0SLionel Sambuc     if (opt->server_identifier_string) {
397ebfedea0SLionel Sambuc 	int ret;
398ebfedea0SLionel Sambuc 
399ebfedea0SLionel Sambuc 	ret = hex_decode(opt->server_identifier_string, &server_identifier, 1);
400ebfedea0SLionel Sambuc 	if (ret != 1)
401ebfedea0SLionel Sambuc 	    errx(1, "server identifier wrong length");
402ebfedea0SLionel Sambuc     }
403ebfedea0SLionel Sambuc 
404ebfedea0SLionel Sambuc     if (strcasecmp(opt->type_string, "CHAP") == 0) {
405ebfedea0SLionel Sambuc 	if (opt->server_identifier_string == NULL)
406ebfedea0SLionel Sambuc 	    errx(1, "server identifier missing");
407ebfedea0SLionel Sambuc 
408ebfedea0SLionel Sambuc 	client_chap(server_nonce, snoncelen, server_identifier,
409ebfedea0SLionel Sambuc 		    opt->password_string);
410ebfedea0SLionel Sambuc 
411ebfedea0SLionel Sambuc     } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) {
412ebfedea0SLionel Sambuc 	if (opt->client_nonce_string == NULL)
413ebfedea0SLionel Sambuc 	    errx(1, "client nonce missing");
414ebfedea0SLionel Sambuc 	if (opt->username_string == NULL)
415ebfedea0SLionel Sambuc 	    errx(1, "client nonce missing");
416ebfedea0SLionel Sambuc 
417ebfedea0SLionel Sambuc 	client_mschapv2(server_nonce, snoncelen,
418ebfedea0SLionel Sambuc 			client_nonce, cnoncelen,
419ebfedea0SLionel Sambuc 			opt->username_string,
420ebfedea0SLionel Sambuc 			opt->password_string);
421ebfedea0SLionel Sambuc     }
422ebfedea0SLionel Sambuc     if (client_nonce)
423ebfedea0SLionel Sambuc 	free(client_nonce);
424ebfedea0SLionel Sambuc     free(server_nonce);
425ebfedea0SLionel Sambuc 
426ebfedea0SLionel Sambuc     return 0;
427ebfedea0SLionel Sambuc }
428ebfedea0SLionel Sambuc 
429ebfedea0SLionel Sambuc #include <krb5/heimntlm.h>
430ebfedea0SLionel Sambuc 
431ebfedea0SLionel Sambuc int
ntlm_server_init(struct ntlm_server_init_options * opt,int argc,char ** argv)432ebfedea0SLionel Sambuc ntlm_server_init(struct ntlm_server_init_options *opt,
433ebfedea0SLionel Sambuc 		 int argc, char ** argv)
434ebfedea0SLionel Sambuc {
435ebfedea0SLionel Sambuc     krb5_error_code ret;
436ebfedea0SLionel Sambuc     krb5_ntlm ntlm;
437ebfedea0SLionel Sambuc     struct ntlm_type2 type2;
438ebfedea0SLionel Sambuc     krb5_data challenge, opaque;
439ebfedea0SLionel Sambuc     struct ntlm_buf data;
440ebfedea0SLionel Sambuc     char *s;
441*0a6a1f1dSLionel Sambuc     static char zero2[] = "\x00\x00";
442ebfedea0SLionel Sambuc 
443ebfedea0SLionel Sambuc     memset(&type2, 0, sizeof(type2));
444ebfedea0SLionel Sambuc 
445ebfedea0SLionel Sambuc     ret = krb5_ntlm_alloc(context, &ntlm);
446ebfedea0SLionel Sambuc     if (ret)
447ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_ntlm_alloc");
448ebfedea0SLionel Sambuc 
449ebfedea0SLionel Sambuc     ret = krb5_ntlm_init_request(context,
450ebfedea0SLionel Sambuc 				 ntlm,
451ebfedea0SLionel Sambuc 				 opt->kerberos_realm_string,
452ebfedea0SLionel Sambuc 				 id,
453ebfedea0SLionel Sambuc 				 NTLM_NEG_UNICODE|NTLM_NEG_NTLM,
454ebfedea0SLionel Sambuc 				 "NUTCRACKER",
455ebfedea0SLionel Sambuc 				 "L");
456ebfedea0SLionel Sambuc     if (ret)
457ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_ntlm_init_request");
458ebfedea0SLionel Sambuc 
459ebfedea0SLionel Sambuc     /*
460ebfedea0SLionel Sambuc      *
461ebfedea0SLionel Sambuc      */
462ebfedea0SLionel Sambuc 
463ebfedea0SLionel Sambuc     ret = krb5_ntlm_init_get_challange(context, ntlm, &challenge);
464ebfedea0SLionel Sambuc     if (ret)
465ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_ntlm_init_get_challange");
466ebfedea0SLionel Sambuc 
467ebfedea0SLionel Sambuc     if (challenge.length != sizeof(type2.challenge))
468ebfedea0SLionel Sambuc 	krb5_errx(context, 1, "ntlm challenge have wrong length");
469ebfedea0SLionel Sambuc     memcpy(type2.challenge, challenge.data, sizeof(type2.challenge));
470ebfedea0SLionel Sambuc     krb5_data_free(&challenge);
471ebfedea0SLionel Sambuc 
472ebfedea0SLionel Sambuc     ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags);
473ebfedea0SLionel Sambuc     if (ret)
474ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags");
475ebfedea0SLionel Sambuc 
476ebfedea0SLionel Sambuc     krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname);
477*0a6a1f1dSLionel Sambuc     type2.targetinfo.data = zero2;
478ebfedea0SLionel Sambuc     type2.targetinfo.length = 2;
479ebfedea0SLionel Sambuc 
480ebfedea0SLionel Sambuc     ret = heim_ntlm_encode_type2(&type2, &data);
481ebfedea0SLionel Sambuc     if (ret)
482ebfedea0SLionel Sambuc 	krb5_errx(context, 1, "heim_ntlm_encode_type2");
483ebfedea0SLionel Sambuc 
484ebfedea0SLionel Sambuc     free(type2.targetname);
485ebfedea0SLionel Sambuc 
486ebfedea0SLionel Sambuc     /*
487ebfedea0SLionel Sambuc      *
488ebfedea0SLionel Sambuc      */
489ebfedea0SLionel Sambuc 
490ebfedea0SLionel Sambuc     base64_encode(data.data, data.length, &s);
491ebfedea0SLionel Sambuc     free(data.data);
492ebfedea0SLionel Sambuc     printf("type2=%s\n", s);
493ebfedea0SLionel Sambuc     free(s);
494ebfedea0SLionel Sambuc 
495ebfedea0SLionel Sambuc     /*
496ebfedea0SLionel Sambuc      *
497ebfedea0SLionel Sambuc      */
498ebfedea0SLionel Sambuc 
499ebfedea0SLionel Sambuc     ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque);
500ebfedea0SLionel Sambuc     if (ret)
501ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque");
502ebfedea0SLionel Sambuc 
503ebfedea0SLionel Sambuc     base64_encode(opaque.data, opaque.length, &s);
504ebfedea0SLionel Sambuc     krb5_data_free(&opaque);
505ebfedea0SLionel Sambuc     printf("opaque=%s\n", s);
506ebfedea0SLionel Sambuc     free(s);
507ebfedea0SLionel Sambuc 
508ebfedea0SLionel Sambuc     /*
509ebfedea0SLionel Sambuc      *
510ebfedea0SLionel Sambuc      */
511ebfedea0SLionel Sambuc 
512ebfedea0SLionel Sambuc     krb5_ntlm_free(context, ntlm);
513ebfedea0SLionel Sambuc 
514ebfedea0SLionel Sambuc     return 0;
515ebfedea0SLionel Sambuc }
516ebfedea0SLionel Sambuc 
517ebfedea0SLionel Sambuc 
518ebfedea0SLionel Sambuc /*
519ebfedea0SLionel Sambuc  *
520ebfedea0SLionel Sambuc  */
521ebfedea0SLionel Sambuc 
522ebfedea0SLionel Sambuc int
help(void * opt,int argc,char ** argv)523ebfedea0SLionel Sambuc help(void *opt, int argc, char **argv)
524ebfedea0SLionel Sambuc {
525ebfedea0SLionel Sambuc     sl_slc_help(commands, argc, argv);
526ebfedea0SLionel Sambuc     return 0;
527ebfedea0SLionel Sambuc }
528ebfedea0SLionel Sambuc 
529ebfedea0SLionel Sambuc int
main(int argc,char ** argv)530ebfedea0SLionel Sambuc main(int argc, char **argv)
531ebfedea0SLionel Sambuc {
532ebfedea0SLionel Sambuc     krb5_error_code ret;
533ebfedea0SLionel Sambuc     int optidx = 0;
534ebfedea0SLionel Sambuc 
535ebfedea0SLionel Sambuc     setprogname(argv[0]);
536ebfedea0SLionel Sambuc 
537ebfedea0SLionel Sambuc     ret = krb5_init_context (&context);
538ebfedea0SLionel Sambuc     if (ret == KRB5_CONFIG_BADFORMAT)
539ebfedea0SLionel Sambuc 	errx (1, "krb5_init_context failed to parse configuration file");
540ebfedea0SLionel Sambuc     else if (ret)
541ebfedea0SLionel Sambuc 	errx(1, "krb5_init_context failed: %d", ret);
542ebfedea0SLionel Sambuc 
543ebfedea0SLionel Sambuc     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
544ebfedea0SLionel Sambuc 	usage(1);
545ebfedea0SLionel Sambuc 
546ebfedea0SLionel Sambuc     if (help_flag)
547ebfedea0SLionel Sambuc 	usage (0);
548ebfedea0SLionel Sambuc 
549ebfedea0SLionel Sambuc     if(version_flag){
550ebfedea0SLionel Sambuc 	print_version(NULL);
551ebfedea0SLionel Sambuc 	exit(0);
552ebfedea0SLionel Sambuc     }
553ebfedea0SLionel Sambuc 
554ebfedea0SLionel Sambuc     argc -= optidx;
555ebfedea0SLionel Sambuc     argv += optidx;
556ebfedea0SLionel Sambuc 
557ebfedea0SLionel Sambuc     if (argc == 0) {
558ebfedea0SLionel Sambuc 	help(NULL, argc, argv);
559ebfedea0SLionel Sambuc 	return 1;
560ebfedea0SLionel Sambuc     }
561ebfedea0SLionel Sambuc 
562ebfedea0SLionel Sambuc     if (ccache_string) {
563ebfedea0SLionel Sambuc 	ret = krb5_cc_resolve(context, ccache_string, &id);
564ebfedea0SLionel Sambuc 	if (ret)
565ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_cc_resolve");
566ebfedea0SLionel Sambuc     }
567ebfedea0SLionel Sambuc 
568ebfedea0SLionel Sambuc     ret = sl_command (commands, argc, argv);
569ebfedea0SLionel Sambuc     if (ret == -1) {
570ebfedea0SLionel Sambuc 	help(NULL, argc, argv);
571ebfedea0SLionel Sambuc 	return 1;
572ebfedea0SLionel Sambuc     }
573ebfedea0SLionel Sambuc     return ret;
574ebfedea0SLionel Sambuc }
575