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