1178825Sdfr/*
2178825Sdfr * Copyright (c) 2006 - 2007 Kungliga Tekniska H�gskolan
3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden).
4178825Sdfr * All rights reserved.
5178825Sdfr *
6178825Sdfr * Redistribution and use in source and binary forms, with or without
7178825Sdfr * modification, are permitted provided that the following conditions
8178825Sdfr * are met:
9178825Sdfr *
10178825Sdfr * 1. Redistributions of source code must retain the above copyright
11178825Sdfr *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
14178825Sdfr *    notice, this list of conditions and the following disclaimer in the
15178825Sdfr *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors
18178825Sdfr *    may be used to endorse or promote products derived from this software
19178825Sdfr *    without specific prior written permission.
20178825Sdfr *
21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31178825Sdfr * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "kuser_locl.h"
35178825SdfrRCSID("$Id: kdigest.c 22158 2007-12-04 20:04:01Z lha $");
36178825Sdfr#include <kdigest-commands.h>
37178825Sdfr#include <hex.h>
38178825Sdfr#include <base64.h>
39178825Sdfr#include <heimntlm.h>
40178825Sdfr#include "crypto-headers.h"
41178825Sdfr
42178825Sdfrstatic int version_flag = 0;
43178825Sdfrstatic int help_flag	= 0;
44178825Sdfrstatic char *ccache_string;
45178825Sdfrstatic krb5_ccache id;
46178825Sdfr
47178825Sdfrstatic struct getargs args[] = {
48178825Sdfr    {"ccache",	0,	arg_string,	&ccache_string, "credential cache", NULL },
49178825Sdfr    {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
50178825Sdfr    {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
51178825Sdfr};
52178825Sdfr
53178825Sdfrstatic void
54178825Sdfrusage (int ret)
55178825Sdfr{
56178825Sdfr    arg_printusage (args, sizeof(args)/sizeof(*args),
57178825Sdfr		    NULL, "");
58178825Sdfr    exit (ret);
59178825Sdfr}
60178825Sdfr
61178825Sdfrstatic krb5_context context;
62178825Sdfr
63178825Sdfrint
64178825Sdfrdigest_probe(struct digest_probe_options *opt,
65178825Sdfr	     int argc, char ** argv)
66178825Sdfr{
67178825Sdfr    krb5_error_code ret;
68178825Sdfr    krb5_realm realm;
69178825Sdfr    unsigned flags;
70178825Sdfr
71178825Sdfr    realm = opt->realm_string;
72178825Sdfr
73178825Sdfr    if (realm == NULL)
74178825Sdfr	errx(1, "realm missing");
75178825Sdfr
76178825Sdfr    ret = krb5_digest_probe(context, realm, id, &flags);
77178825Sdfr    if (ret)
78178825Sdfr	krb5_err(context, 1, ret, "digest_probe");
79178825Sdfr
80178825Sdfr    printf("flags: %u\n", flags);
81178825Sdfr
82178825Sdfr    return 0;
83178825Sdfr}
84178825Sdfr
85178825Sdfrint
86178825Sdfrdigest_server_init(struct digest_server_init_options *opt,
87178825Sdfr		   int argc, char ** argv)
88178825Sdfr{
89178825Sdfr    krb5_error_code ret;
90178825Sdfr    krb5_digest digest;
91178825Sdfr
92178825Sdfr    ret = krb5_digest_alloc(context, &digest);
93178825Sdfr    if (ret)
94178825Sdfr	krb5_err(context, 1, ret, "digest_alloc");
95178825Sdfr
96178825Sdfr    ret = krb5_digest_set_type(context, digest, opt->type_string);
97178825Sdfr    if (ret)
98178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_type");
99178825Sdfr
100178825Sdfr    if (opt->cb_type_string && opt->cb_value_string) {
101178825Sdfr	ret = krb5_digest_set_server_cb(context, digest,
102178825Sdfr					opt->cb_type_string,
103178825Sdfr					opt->cb_value_string);
104178825Sdfr	if (ret)
105178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_server_cb");
106178825Sdfr    }
107178825Sdfr    ret = krb5_digest_init_request(context,
108178825Sdfr				   digest,
109178825Sdfr				   opt->kerberos_realm_string,
110178825Sdfr				   id);
111178825Sdfr    if (ret)
112178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_init_request");
113178825Sdfr
114178825Sdfr    printf("type=%s\n", opt->type_string);
115178825Sdfr    printf("server-nonce=%s\n",
116178825Sdfr	   krb5_digest_get_server_nonce(context, digest));
117178825Sdfr    {
118178825Sdfr	const char *s = krb5_digest_get_identifier(context, digest);
119178825Sdfr	if (s)
120178825Sdfr	    printf("identifier=%s\n", s);
121178825Sdfr    }
122178825Sdfr    printf("opaque=%s\n", krb5_digest_get_opaque(context, digest));
123178825Sdfr
124178825Sdfr    return 0;
125178825Sdfr}
126178825Sdfr
127178825Sdfrint
128178825Sdfrdigest_server_request(struct digest_server_request_options *opt,
129178825Sdfr		      int argc, char **argv)
130178825Sdfr{
131178825Sdfr    krb5_error_code ret;
132178825Sdfr    krb5_digest digest;
133178825Sdfr    const char *status, *rsp;
134178825Sdfr    krb5_data session_key;
135178825Sdfr
136178825Sdfr    if (opt->server_nonce_string == NULL)
137178825Sdfr	errx(1, "server nonce missing");
138178825Sdfr    if (opt->type_string == NULL)
139178825Sdfr	errx(1, "type missing");
140178825Sdfr    if (opt->opaque_string == NULL)
141178825Sdfr	errx(1, "opaque missing");
142178825Sdfr    if (opt->client_response_string == NULL)
143178825Sdfr	errx(1, "client response missing");
144178825Sdfr
145178825Sdfr    ret = krb5_digest_alloc(context, &digest);
146178825Sdfr    if (ret)
147178825Sdfr	krb5_err(context, 1, ret, "digest_alloc");
148178825Sdfr
149178825Sdfr    if (strcasecmp(opt->type_string, "CHAP") == 0) {
150178825Sdfr	if (opt->server_identifier_string == NULL)
151178825Sdfr	    errx(1, "server identifier missing");
152178825Sdfr
153178825Sdfr	ret = krb5_digest_set_identifier(context, digest,
154178825Sdfr					 opt->server_identifier_string);
155178825Sdfr	if (ret)
156178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_type");
157178825Sdfr    }
158178825Sdfr
159178825Sdfr    ret = krb5_digest_set_type(context, digest, opt->type_string);
160178825Sdfr    if (ret)
161178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_type");
162178825Sdfr
163178825Sdfr    ret = krb5_digest_set_username(context, digest, opt->username_string);
164178825Sdfr    if (ret)
165178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_username");
166178825Sdfr
167178825Sdfr    ret = krb5_digest_set_server_nonce(context, digest,
168178825Sdfr				       opt->server_nonce_string);
169178825Sdfr    if (ret)
170178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_server_nonce");
171178825Sdfr
172178825Sdfr    if(opt->client_nonce_string) {
173178825Sdfr	ret = krb5_digest_set_client_nonce(context, digest,
174178825Sdfr					   opt->client_nonce_string);
175178825Sdfr	if (ret)
176178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_client_nonce");
177178825Sdfr    }
178178825Sdfr
179178825Sdfr
180178825Sdfr    ret = krb5_digest_set_opaque(context, digest, opt->opaque_string);
181178825Sdfr    if (ret)
182178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_opaque");
183178825Sdfr
184178825Sdfr    ret = krb5_digest_set_responseData(context, digest,
185178825Sdfr				       opt->client_response_string);
186178825Sdfr    if (ret)
187178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_responseData");
188178825Sdfr
189178825Sdfr    ret = krb5_digest_request(context, digest,
190178825Sdfr			      opt->kerberos_realm_string, id);
191178825Sdfr    if (ret)
192178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_request");
193178825Sdfr
194178825Sdfr    status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed";
195178825Sdfr    rsp = krb5_digest_get_rsp(context, digest);
196178825Sdfr
197178825Sdfr    printf("status=%s\n", status);
198178825Sdfr    if (rsp)
199178825Sdfr	printf("rsp=%s\n", rsp);
200178825Sdfr    printf("tickets=no\n");
201178825Sdfr
202178825Sdfr    ret = krb5_digest_get_session_key(context, digest, &session_key);
203178825Sdfr    if (ret)
204178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_get_session_key");
205178825Sdfr
206178825Sdfr    if (session_key.length) {
207178825Sdfr	char *key;
208178825Sdfr	hex_encode(session_key.data, session_key.length, &key);
209178825Sdfr	if (key == NULL)
210178825Sdfr	    krb5_errx(context, 1, "hex_encode");
211178825Sdfr	krb5_data_free(&session_key);
212178825Sdfr	printf("session-key=%s\n", key);
213178825Sdfr	free(key);
214178825Sdfr    }
215178825Sdfr
216178825Sdfr    return 0;
217178825Sdfr}
218178825Sdfr
219178825Sdfrstatic void
220178825Sdfrclient_chap(const void *server_nonce, size_t snoncelen,
221178825Sdfr	    unsigned char server_identifier,
222178825Sdfr	    const char *password)
223178825Sdfr{
224178825Sdfr    MD5_CTX ctx;
225178825Sdfr    unsigned char md[MD5_DIGEST_LENGTH];
226178825Sdfr    char *h;
227178825Sdfr
228178825Sdfr    MD5_Init(&ctx);
229178825Sdfr    MD5_Update(&ctx, &server_identifier, 1);
230178825Sdfr    MD5_Update(&ctx, password, strlen(password));
231178825Sdfr    MD5_Update(&ctx, server_nonce, snoncelen);
232178825Sdfr    MD5_Final(md, &ctx);
233178825Sdfr
234178825Sdfr    hex_encode(md, 16, &h);
235178825Sdfr
236178825Sdfr    printf("responseData=%s\n", h);
237178825Sdfr    free(h);
238178825Sdfr}
239178825Sdfr
240178825Sdfrstatic const unsigned char ms_chap_v2_magic1[39] = {
241178825Sdfr    0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
242178825Sdfr    0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
243178825Sdfr    0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
244178825Sdfr    0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
245178825Sdfr};
246178825Sdfrstatic const unsigned char ms_chap_v2_magic2[41] = {
247178825Sdfr    0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
248178825Sdfr    0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
249178825Sdfr    0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
250178825Sdfr    0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
251178825Sdfr    0x6E
252178825Sdfr};
253178825Sdfrstatic const unsigned char ms_rfc3079_magic1[27] = {
254178825Sdfr    0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
255178825Sdfr    0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
256178825Sdfr    0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
257178825Sdfr};
258178825Sdfr
259178825Sdfrstatic void
260178825Sdfrclient_mschapv2(const void *server_nonce, size_t snoncelen,
261178825Sdfr		const void *client_nonce, size_t cnoncelen,
262178825Sdfr		const char *username,
263178825Sdfr		const char *password)
264178825Sdfr{
265178825Sdfr    SHA_CTX ctx;
266178825Sdfr    MD4_CTX hctx;
267178825Sdfr    unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
268178825Sdfr    unsigned char hmd[MD4_DIGEST_LENGTH];
269178825Sdfr    struct ntlm_buf answer;
270178825Sdfr    int i, len, ret;
271178825Sdfr    char *h;
272178825Sdfr
273178825Sdfr    SHA1_Init(&ctx);
274178825Sdfr    SHA1_Update(&ctx, client_nonce, cnoncelen);
275178825Sdfr    SHA1_Update(&ctx, server_nonce, snoncelen);
276178825Sdfr    SHA1_Update(&ctx, username, strlen(username));
277178825Sdfr    SHA1_Final(md, &ctx);
278178825Sdfr
279178825Sdfr    MD4_Init(&hctx);
280178825Sdfr    len = strlen(password);
281178825Sdfr    for (i = 0; i < len; i++) {
282178825Sdfr	MD4_Update(&hctx, &password[i], 1);
283178825Sdfr	MD4_Update(&hctx, &password[len], 1);
284178825Sdfr    }
285178825Sdfr    MD4_Final(hmd, &hctx);
286178825Sdfr
287178825Sdfr    /* ChallengeResponse */
288178825Sdfr    ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer);
289178825Sdfr    if (ret)
290178825Sdfr	errx(1, "heim_ntlm_calculate_ntlm1");
291178825Sdfr
292178825Sdfr    hex_encode(answer.data, answer.length, &h);
293178825Sdfr    printf("responseData=%s\n", h);
294178825Sdfr    free(h);
295178825Sdfr
296178825Sdfr    /* PasswordHash */
297178825Sdfr    MD4_Init(&hctx);
298178825Sdfr    MD4_Update(&hctx, hmd, sizeof(hmd));
299178825Sdfr    MD4_Final(hmd, &hctx);
300178825Sdfr
301178825Sdfr    /* GenerateAuthenticatorResponse */
302178825Sdfr    SHA1_Init(&ctx);
303178825Sdfr    SHA1_Update(&ctx, hmd, sizeof(hmd));
304178825Sdfr    SHA1_Update(&ctx, answer.data, answer.length);
305178825Sdfr    SHA1_Update(&ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1));
306178825Sdfr    SHA1_Final(md, &ctx);
307178825Sdfr
308178825Sdfr    /* ChallengeHash */
309178825Sdfr    SHA1_Init(&ctx);
310178825Sdfr    SHA1_Update(&ctx, client_nonce, cnoncelen);
311178825Sdfr    SHA1_Update(&ctx, server_nonce, snoncelen);
312178825Sdfr    SHA1_Update(&ctx, username, strlen(username));
313178825Sdfr    SHA1_Final(challange, &ctx);
314178825Sdfr
315178825Sdfr    SHA1_Init(&ctx);
316178825Sdfr    SHA1_Update(&ctx, md, sizeof(md));
317178825Sdfr    SHA1_Update(&ctx, challange, 8);
318178825Sdfr    SHA1_Update(&ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));
319178825Sdfr    SHA1_Final(md, &ctx);
320178825Sdfr
321178825Sdfr    hex_encode(md, sizeof(md), &h);
322178825Sdfr    printf("AuthenticatorResponse=%s\n", h);
323178825Sdfr    free(h);
324178825Sdfr
325178825Sdfr    /* get_master, rfc 3079 3.4 */
326178825Sdfr    SHA1_Init(&ctx);
327178825Sdfr    SHA1_Update(&ctx, hmd, sizeof(hmd));
328178825Sdfr    SHA1_Update(&ctx, answer.data, answer.length);
329178825Sdfr    SHA1_Update(&ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));
330178825Sdfr    SHA1_Final(md, &ctx);
331178825Sdfr
332178825Sdfr    free(answer.data);
333178825Sdfr
334178825Sdfr    hex_encode(md, 16, &h);
335178825Sdfr    printf("session-key=%s\n", h);
336178825Sdfr    free(h);
337178825Sdfr}
338178825Sdfr
339178825Sdfr
340178825Sdfrint
341178825Sdfrdigest_client_request(struct digest_client_request_options *opt,
342178825Sdfr		      int argc, char **argv)
343178825Sdfr{
344178825Sdfr    char *server_nonce, *client_nonce = NULL, server_identifier;
345178825Sdfr    ssize_t snoncelen, cnoncelen = 0;
346178825Sdfr
347178825Sdfr    if (opt->server_nonce_string == NULL)
348178825Sdfr	errx(1, "server nonce missing");
349178825Sdfr    if (opt->password_string == NULL)
350178825Sdfr	errx(1, "password missing");
351178825Sdfr
352178825Sdfr    if (opt->opaque_string == NULL)
353178825Sdfr	errx(1, "opaque missing");
354178825Sdfr
355178825Sdfr    snoncelen = strlen(opt->server_nonce_string);
356178825Sdfr    server_nonce = malloc(snoncelen);
357178825Sdfr    if (server_nonce == NULL)
358178825Sdfr	errx(1, "server_nonce");
359178825Sdfr
360178825Sdfr    snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen);
361178825Sdfr    if (snoncelen <= 0)
362178825Sdfr	errx(1, "server nonce wrong");
363178825Sdfr
364178825Sdfr    if (opt->client_nonce_string) {
365178825Sdfr	cnoncelen = strlen(opt->client_nonce_string);
366178825Sdfr	client_nonce = malloc(cnoncelen);
367178825Sdfr	if (client_nonce == NULL)
368178825Sdfr	    errx(1, "client_nonce");
369178825Sdfr
370178825Sdfr	cnoncelen = hex_decode(opt->client_nonce_string,
371178825Sdfr			       client_nonce, cnoncelen);
372178825Sdfr	if (cnoncelen <= 0)
373178825Sdfr	    errx(1, "client nonce wrong");
374178825Sdfr    }
375178825Sdfr
376178825Sdfr    if (opt->server_identifier_string) {
377178825Sdfr	int ret;
378178825Sdfr
379178825Sdfr	ret = hex_decode(opt->server_identifier_string, &server_identifier, 1);
380178825Sdfr	if (ret != 1)
381178825Sdfr	    errx(1, "server identifier wrong length");
382178825Sdfr    }
383178825Sdfr
384178825Sdfr    if (strcasecmp(opt->type_string, "CHAP") == 0) {
385178825Sdfr	if (opt->server_identifier_string == NULL)
386178825Sdfr	    errx(1, "server identifier missing");
387178825Sdfr
388178825Sdfr	client_chap(server_nonce, snoncelen, server_identifier,
389178825Sdfr		    opt->password_string);
390178825Sdfr
391178825Sdfr    } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) {
392178825Sdfr	if (opt->client_nonce_string == NULL)
393178825Sdfr	    errx(1, "client nonce missing");
394178825Sdfr	if (opt->username_string == NULL)
395178825Sdfr	    errx(1, "client nonce missing");
396178825Sdfr
397178825Sdfr	client_mschapv2(server_nonce, snoncelen,
398178825Sdfr			client_nonce, cnoncelen,
399178825Sdfr			opt->username_string,
400178825Sdfr			opt->password_string);
401178825Sdfr    }
402178825Sdfr
403178825Sdfr
404178825Sdfr    return 0;
405178825Sdfr}
406178825Sdfr
407178825Sdfr#include <heimntlm.h>
408178825Sdfr
409178825Sdfrint
410178825Sdfrntlm_server_init(struct ntlm_server_init_options *opt,
411178825Sdfr		 int argc, char ** argv)
412178825Sdfr{
413178825Sdfr    krb5_error_code ret;
414178825Sdfr    krb5_ntlm ntlm;
415178825Sdfr    struct ntlm_type2 type2;
416178825Sdfr    krb5_data challange, opaque;
417178825Sdfr    struct ntlm_buf data;
418178825Sdfr    char *s;
419178825Sdfr
420178825Sdfr    memset(&type2, 0, sizeof(type2));
421178825Sdfr
422178825Sdfr    ret = krb5_ntlm_alloc(context, &ntlm);
423178825Sdfr    if (ret)
424178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_alloc");
425178825Sdfr
426178825Sdfr    ret = krb5_ntlm_init_request(context,
427178825Sdfr				 ntlm,
428178825Sdfr				 opt->kerberos_realm_string,
429178825Sdfr				 id,
430178825Sdfr				 NTLM_NEG_UNICODE|NTLM_NEG_NTLM,
431178825Sdfr				 "NUTCRACKER",
432178825Sdfr				 "L");
433178825Sdfr    if (ret)
434178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_request");
435178825Sdfr
436178825Sdfr    /*
437178825Sdfr     *
438178825Sdfr     */
439178825Sdfr
440178825Sdfr    ret = krb5_ntlm_init_get_challange(context, ntlm, &challange);
441178825Sdfr    if (ret)
442178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_challange");
443178825Sdfr
444178825Sdfr    if (challange.length != sizeof(type2.challange))
445178825Sdfr	krb5_errx(context, 1, "ntlm challange have wrong length");
446178825Sdfr    memcpy(type2.challange, challange.data, sizeof(type2.challange));
447178825Sdfr    krb5_data_free(&challange);
448178825Sdfr
449178825Sdfr    ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags);
450178825Sdfr    if (ret)
451178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags");
452178825Sdfr
453178825Sdfr    krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname);
454178825Sdfr    type2.targetinfo.data = "\x00\x00";
455178825Sdfr    type2.targetinfo.length = 2;
456178825Sdfr
457178825Sdfr    ret = heim_ntlm_encode_type2(&type2, &data);
458178825Sdfr    if (ret)
459178825Sdfr	krb5_errx(context, 1, "heim_ntlm_encode_type2");
460178825Sdfr
461178825Sdfr    free(type2.targetname);
462178825Sdfr
463178825Sdfr    /*
464178825Sdfr     *
465178825Sdfr     */
466178825Sdfr
467178825Sdfr    base64_encode(data.data, data.length, &s);
468178825Sdfr    free(data.data);
469178825Sdfr    printf("type2=%s\n", s);
470178825Sdfr    free(s);
471178825Sdfr
472178825Sdfr    /*
473178825Sdfr     *
474178825Sdfr     */
475178825Sdfr
476178825Sdfr    ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque);
477178825Sdfr    if (ret)
478178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque");
479178825Sdfr
480178825Sdfr    base64_encode(opaque.data, opaque.length, &s);
481178825Sdfr    krb5_data_free(&opaque);
482178825Sdfr    printf("opaque=%s\n", s);
483178825Sdfr    free(s);
484178825Sdfr
485178825Sdfr    /*
486178825Sdfr     *
487178825Sdfr     */
488178825Sdfr
489178825Sdfr    krb5_ntlm_free(context, ntlm);
490178825Sdfr
491178825Sdfr    return 0;
492178825Sdfr}
493178825Sdfr
494178825Sdfr
495178825Sdfr/*
496178825Sdfr *
497178825Sdfr */
498178825Sdfr
499178825Sdfrint
500178825Sdfrhelp(void *opt, int argc, char **argv)
501178825Sdfr{
502178825Sdfr    sl_slc_help(commands, argc, argv);
503178825Sdfr    return 0;
504178825Sdfr}
505178825Sdfr
506178825Sdfrint
507178825Sdfrmain(int argc, char **argv)
508178825Sdfr{
509178825Sdfr    krb5_error_code ret;
510178825Sdfr    int optidx = 0;
511178825Sdfr
512178825Sdfr    setprogname(argv[0]);
513178825Sdfr
514178825Sdfr    ret = krb5_init_context (&context);
515178825Sdfr    if (ret == KRB5_CONFIG_BADFORMAT)
516178825Sdfr	errx (1, "krb5_init_context failed to parse configuration file");
517178825Sdfr    else if (ret)
518178825Sdfr	errx(1, "krb5_init_context failed: %d", ret);
519178825Sdfr
520178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
521178825Sdfr	usage(1);
522178825Sdfr
523178825Sdfr    if (help_flag)
524178825Sdfr	usage (0);
525178825Sdfr
526178825Sdfr    if(version_flag){
527178825Sdfr	print_version(NULL);
528178825Sdfr	exit(0);
529178825Sdfr    }
530178825Sdfr
531178825Sdfr    argc -= optidx;
532178825Sdfr    argv += optidx;
533178825Sdfr
534178825Sdfr    if (argc == 0) {
535178825Sdfr	help(NULL, argc, argv);
536178825Sdfr	return 1;
537178825Sdfr    }
538178825Sdfr
539178825Sdfr    if (ccache_string) {
540178825Sdfr	ret = krb5_cc_resolve(context, ccache_string, &id);
541178825Sdfr	if (ret)
542178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_resolve");
543178825Sdfr    }
544178825Sdfr
545178825Sdfr    ret = sl_command (commands, argc, argv);
546178825Sdfr    if (ret == -1) {
547178825Sdfr	help(NULL, argc, argv);
548178825Sdfr	return 1;
549178825Sdfr    }
550178825Sdfr    return ret;
551178825Sdfr}
552