1178825Sdfr/*
2233294Sstas * Copyright (c) 2006 - 2007 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34233294Sstas#define HC_DEPRECATED_CRYPTO
35233294Sstas
36178825Sdfr#include "kuser_locl.h"
37233294Sstas
38178825Sdfr#include <kdigest-commands.h>
39178825Sdfr#include <hex.h>
40178825Sdfr#include <base64.h>
41178825Sdfr#include <heimntlm.h>
42178825Sdfr#include "crypto-headers.h"
43178825Sdfr
44178825Sdfrstatic int version_flag = 0;
45178825Sdfrstatic int help_flag	= 0;
46178825Sdfrstatic char *ccache_string;
47178825Sdfrstatic krb5_ccache id;
48178825Sdfr
49178825Sdfrstatic struct getargs args[] = {
50178825Sdfr    {"ccache",	0,	arg_string,	&ccache_string, "credential cache", NULL },
51178825Sdfr    {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
52178825Sdfr    {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
53178825Sdfr};
54178825Sdfr
55178825Sdfrstatic void
56178825Sdfrusage (int ret)
57178825Sdfr{
58178825Sdfr    arg_printusage (args, sizeof(args)/sizeof(*args),
59178825Sdfr		    NULL, "");
60178825Sdfr    exit (ret);
61178825Sdfr}
62178825Sdfr
63178825Sdfrstatic krb5_context context;
64178825Sdfr
65178825Sdfrint
66178825Sdfrdigest_probe(struct digest_probe_options *opt,
67178825Sdfr	     int argc, char ** argv)
68178825Sdfr{
69178825Sdfr    krb5_error_code ret;
70178825Sdfr    krb5_realm realm;
71178825Sdfr    unsigned flags;
72178825Sdfr
73178825Sdfr    realm = opt->realm_string;
74178825Sdfr
75178825Sdfr    if (realm == NULL)
76178825Sdfr	errx(1, "realm missing");
77178825Sdfr
78178825Sdfr    ret = krb5_digest_probe(context, realm, id, &flags);
79178825Sdfr    if (ret)
80178825Sdfr	krb5_err(context, 1, ret, "digest_probe");
81178825Sdfr
82178825Sdfr    printf("flags: %u\n", flags);
83178825Sdfr
84178825Sdfr    return 0;
85178825Sdfr}
86178825Sdfr
87178825Sdfrint
88178825Sdfrdigest_server_init(struct digest_server_init_options *opt,
89178825Sdfr		   int argc, char ** argv)
90178825Sdfr{
91178825Sdfr    krb5_error_code ret;
92178825Sdfr    krb5_digest digest;
93178825Sdfr
94178825Sdfr    ret = krb5_digest_alloc(context, &digest);
95178825Sdfr    if (ret)
96178825Sdfr	krb5_err(context, 1, ret, "digest_alloc");
97178825Sdfr
98178825Sdfr    ret = krb5_digest_set_type(context, digest, opt->type_string);
99178825Sdfr    if (ret)
100178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_type");
101178825Sdfr
102178825Sdfr    if (opt->cb_type_string && opt->cb_value_string) {
103233294Sstas	ret = krb5_digest_set_server_cb(context, digest,
104178825Sdfr					opt->cb_type_string,
105178825Sdfr					opt->cb_value_string);
106178825Sdfr	if (ret)
107178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_server_cb");
108178825Sdfr    }
109178825Sdfr    ret = krb5_digest_init_request(context,
110178825Sdfr				   digest,
111178825Sdfr				   opt->kerberos_realm_string,
112178825Sdfr				   id);
113178825Sdfr    if (ret)
114178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_init_request");
115178825Sdfr
116178825Sdfr    printf("type=%s\n", opt->type_string);
117233294Sstas    printf("server-nonce=%s\n",
118178825Sdfr	   krb5_digest_get_server_nonce(context, digest));
119178825Sdfr    {
120178825Sdfr	const char *s = krb5_digest_get_identifier(context, digest);
121178825Sdfr	if (s)
122178825Sdfr	    printf("identifier=%s\n", s);
123178825Sdfr    }
124178825Sdfr    printf("opaque=%s\n", krb5_digest_get_opaque(context, digest));
125178825Sdfr
126233294Sstas    krb5_digest_free(digest);
127233294Sstas
128178825Sdfr    return 0;
129178825Sdfr}
130178825Sdfr
131178825Sdfrint
132233294Sstasdigest_server_request(struct digest_server_request_options *opt,
133178825Sdfr		      int argc, char **argv)
134178825Sdfr{
135178825Sdfr    krb5_error_code ret;
136178825Sdfr    krb5_digest digest;
137178825Sdfr    const char *status, *rsp;
138178825Sdfr    krb5_data session_key;
139178825Sdfr
140178825Sdfr    if (opt->server_nonce_string == NULL)
141178825Sdfr	errx(1, "server nonce missing");
142178825Sdfr    if (opt->type_string == NULL)
143178825Sdfr	errx(1, "type missing");
144178825Sdfr    if (opt->opaque_string == NULL)
145178825Sdfr	errx(1, "opaque missing");
146178825Sdfr    if (opt->client_response_string == NULL)
147178825Sdfr	errx(1, "client response missing");
148178825Sdfr
149178825Sdfr    ret = krb5_digest_alloc(context, &digest);
150178825Sdfr    if (ret)
151178825Sdfr	krb5_err(context, 1, ret, "digest_alloc");
152178825Sdfr
153178825Sdfr    if (strcasecmp(opt->type_string, "CHAP") == 0) {
154178825Sdfr	if (opt->server_identifier_string == NULL)
155178825Sdfr	    errx(1, "server identifier missing");
156178825Sdfr
157233294Sstas	ret = krb5_digest_set_identifier(context, digest,
158178825Sdfr					 opt->server_identifier_string);
159178825Sdfr	if (ret)
160178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_type");
161178825Sdfr    }
162178825Sdfr
163178825Sdfr    ret = krb5_digest_set_type(context, digest, opt->type_string);
164178825Sdfr    if (ret)
165178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_type");
166178825Sdfr
167178825Sdfr    ret = krb5_digest_set_username(context, digest, opt->username_string);
168178825Sdfr    if (ret)
169178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_username");
170178825Sdfr
171233294Sstas    ret = krb5_digest_set_server_nonce(context, digest,
172178825Sdfr				       opt->server_nonce_string);
173178825Sdfr    if (ret)
174178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_server_nonce");
175178825Sdfr
176178825Sdfr    if(opt->client_nonce_string) {
177233294Sstas	ret = krb5_digest_set_client_nonce(context, digest,
178178825Sdfr					   opt->client_nonce_string);
179178825Sdfr	if (ret)
180178825Sdfr	    krb5_err(context, 1, ret, "krb5_digest_set_client_nonce");
181178825Sdfr    }
182178825Sdfr
183178825Sdfr
184178825Sdfr    ret = krb5_digest_set_opaque(context, digest, opt->opaque_string);
185178825Sdfr    if (ret)
186178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_opaque");
187178825Sdfr
188233294Sstas    ret = krb5_digest_set_responseData(context, digest,
189178825Sdfr				       opt->client_response_string);
190178825Sdfr    if (ret)
191178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_set_responseData");
192178825Sdfr
193178825Sdfr    ret = krb5_digest_request(context, digest,
194178825Sdfr			      opt->kerberos_realm_string, id);
195178825Sdfr    if (ret)
196178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_request");
197178825Sdfr
198178825Sdfr    status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed";
199178825Sdfr    rsp = krb5_digest_get_rsp(context, digest);
200178825Sdfr
201178825Sdfr    printf("status=%s\n", status);
202178825Sdfr    if (rsp)
203178825Sdfr	printf("rsp=%s\n", rsp);
204178825Sdfr    printf("tickets=no\n");
205178825Sdfr
206178825Sdfr    ret = krb5_digest_get_session_key(context, digest, &session_key);
207178825Sdfr    if (ret)
208178825Sdfr	krb5_err(context, 1, ret, "krb5_digest_get_session_key");
209178825Sdfr
210178825Sdfr    if (session_key.length) {
211178825Sdfr	char *key;
212178825Sdfr	hex_encode(session_key.data, session_key.length, &key);
213178825Sdfr	if (key == NULL)
214178825Sdfr	    krb5_errx(context, 1, "hex_encode");
215178825Sdfr	krb5_data_free(&session_key);
216178825Sdfr	printf("session-key=%s\n", key);
217178825Sdfr	free(key);
218178825Sdfr    }
219178825Sdfr
220233294Sstas    krb5_digest_free(digest);
221233294Sstas
222178825Sdfr    return 0;
223178825Sdfr}
224178825Sdfr
225178825Sdfrstatic void
226178825Sdfrclient_chap(const void *server_nonce, size_t snoncelen,
227178825Sdfr	    unsigned char server_identifier,
228178825Sdfr	    const char *password)
229178825Sdfr{
230233294Sstas    EVP_MD_CTX *ctx;
231178825Sdfr    unsigned char md[MD5_DIGEST_LENGTH];
232178825Sdfr    char *h;
233178825Sdfr
234233294Sstas    ctx = EVP_MD_CTX_create();
235233294Sstas    EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
236178825Sdfr
237233294Sstas    EVP_DigestUpdate(ctx, &server_identifier, 1);
238233294Sstas    EVP_DigestUpdate(ctx, password, strlen(password));
239233294Sstas    EVP_DigestUpdate(ctx, server_nonce, snoncelen);
240233294Sstas    EVP_DigestFinal_ex(ctx, md, NULL);
241233294Sstas
242233294Sstas    EVP_MD_CTX_destroy(ctx);
243233294Sstas
244178825Sdfr    hex_encode(md, 16, &h);
245178825Sdfr
246178825Sdfr    printf("responseData=%s\n", h);
247178825Sdfr    free(h);
248178825Sdfr}
249178825Sdfr
250178825Sdfrstatic const unsigned char ms_chap_v2_magic1[39] = {
251178825Sdfr    0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
252178825Sdfr    0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
253178825Sdfr    0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
254178825Sdfr    0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
255178825Sdfr};
256178825Sdfrstatic const unsigned char ms_chap_v2_magic2[41] = {
257178825Sdfr    0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
258178825Sdfr    0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
259178825Sdfr    0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
260178825Sdfr    0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
261178825Sdfr    0x6E
262178825Sdfr};
263178825Sdfrstatic const unsigned char ms_rfc3079_magic1[27] = {
264178825Sdfr    0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
265178825Sdfr    0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
266178825Sdfr    0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
267178825Sdfr};
268178825Sdfr
269178825Sdfrstatic void
270178825Sdfrclient_mschapv2(const void *server_nonce, size_t snoncelen,
271178825Sdfr		const void *client_nonce, size_t cnoncelen,
272178825Sdfr		const char *username,
273178825Sdfr		const char *password)
274178825Sdfr{
275233294Sstas    EVP_MD_CTX *hctx, *ctx;
276233294Sstas    unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH];
277178825Sdfr    unsigned char hmd[MD4_DIGEST_LENGTH];
278178825Sdfr    struct ntlm_buf answer;
279178825Sdfr    int i, len, ret;
280178825Sdfr    char *h;
281178825Sdfr
282233294Sstas    ctx = EVP_MD_CTX_create();
283233294Sstas    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
284178825Sdfr
285233294Sstas    EVP_DigestUpdate(ctx, client_nonce, cnoncelen);
286233294Sstas    EVP_DigestUpdate(ctx, server_nonce, snoncelen);
287233294Sstas    EVP_DigestUpdate(ctx, username, strlen(username));
288233294Sstas    EVP_DigestFinal_ex(ctx, md, NULL);
289233294Sstas
290233294Sstas
291233294Sstas    hctx = EVP_MD_CTX_create();
292233294Sstas    EVP_DigestInit_ex(hctx, EVP_md4(), NULL);
293178825Sdfr    len = strlen(password);
294178825Sdfr    for (i = 0; i < len; i++) {
295233294Sstas	EVP_DigestUpdate(hctx, &password[i], 1);
296233294Sstas	EVP_DigestUpdate(hctx, &password[len], 1);
297233294Sstas    }
298233294Sstas    EVP_DigestFinal_ex(hctx, hmd, NULL);
299178825Sdfr
300233294Sstas
301178825Sdfr    /* ChallengeResponse */
302178825Sdfr    ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer);
303178825Sdfr    if (ret)
304178825Sdfr	errx(1, "heim_ntlm_calculate_ntlm1");
305178825Sdfr
306178825Sdfr    hex_encode(answer.data, answer.length, &h);
307178825Sdfr    printf("responseData=%s\n", h);
308178825Sdfr    free(h);
309178825Sdfr
310178825Sdfr    /* PasswordHash */
311233294Sstas    EVP_DigestInit_ex(hctx, EVP_md4(), NULL);
312233294Sstas    EVP_DigestUpdate(hctx, hmd, sizeof(hmd));
313233294Sstas    EVP_DigestFinal_ex(hctx, hmd, NULL);
314178825Sdfr
315233294Sstas
316178825Sdfr    /* GenerateAuthenticatorResponse */
317233294Sstas    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
318233294Sstas    EVP_DigestUpdate(ctx, hmd, sizeof(hmd));
319233294Sstas    EVP_DigestUpdate(ctx, answer.data, answer.length);
320233294Sstas    EVP_DigestUpdate(ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1));
321233294Sstas    EVP_DigestFinal_ex(ctx, md, NULL);
322233294Sstas
323178825Sdfr    /* ChallengeHash */
324233294Sstas    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
325233294Sstas    EVP_DigestUpdate(ctx, client_nonce, cnoncelen);
326233294Sstas    EVP_DigestUpdate(ctx, server_nonce, snoncelen);
327233294Sstas    EVP_DigestUpdate(ctx, username, strlen(username));
328233294Sstas    EVP_DigestFinal_ex(ctx, challenge, NULL);
329178825Sdfr
330233294Sstas    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
331233294Sstas    EVP_DigestUpdate(ctx, md, sizeof(md));
332233294Sstas    EVP_DigestUpdate(ctx, challenge, 8);
333233294Sstas    EVP_DigestUpdate(ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));
334233294Sstas    EVP_DigestFinal_ex(ctx, md, NULL);
335178825Sdfr
336178825Sdfr    hex_encode(md, sizeof(md), &h);
337178825Sdfr    printf("AuthenticatorResponse=%s\n", h);
338178825Sdfr    free(h);
339178825Sdfr
340178825Sdfr    /* get_master, rfc 3079 3.4 */
341233294Sstas    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
342233294Sstas    EVP_DigestUpdate(ctx, hmd, sizeof(hmd));
343233294Sstas    EVP_DigestUpdate(ctx, answer.data, answer.length);
344233294Sstas    EVP_DigestUpdate(ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));
345233294Sstas    EVP_DigestFinal_ex(ctx, md, NULL);
346178825Sdfr
347178825Sdfr    free(answer.data);
348178825Sdfr
349178825Sdfr    hex_encode(md, 16, &h);
350178825Sdfr    printf("session-key=%s\n", h);
351178825Sdfr    free(h);
352233294Sstas
353233294Sstas    EVP_MD_CTX_destroy(hctx);
354233294Sstas    EVP_MD_CTX_destroy(ctx);
355178825Sdfr}
356178825Sdfr
357178825Sdfr
358178825Sdfrint
359233294Sstasdigest_client_request(struct digest_client_request_options *opt,
360178825Sdfr		      int argc, char **argv)
361178825Sdfr{
362178825Sdfr    char *server_nonce, *client_nonce = NULL, server_identifier;
363178825Sdfr    ssize_t snoncelen, cnoncelen = 0;
364178825Sdfr
365178825Sdfr    if (opt->server_nonce_string == NULL)
366178825Sdfr	errx(1, "server nonce missing");
367178825Sdfr    if (opt->password_string == NULL)
368178825Sdfr	errx(1, "password missing");
369178825Sdfr
370178825Sdfr    if (opt->opaque_string == NULL)
371178825Sdfr	errx(1, "opaque missing");
372178825Sdfr
373178825Sdfr    snoncelen = strlen(opt->server_nonce_string);
374178825Sdfr    server_nonce = malloc(snoncelen);
375178825Sdfr    if (server_nonce == NULL)
376178825Sdfr	errx(1, "server_nonce");
377178825Sdfr
378178825Sdfr    snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen);
379233294Sstas    if (snoncelen <= 0)
380178825Sdfr	errx(1, "server nonce wrong");
381178825Sdfr
382178825Sdfr    if (opt->client_nonce_string) {
383178825Sdfr	cnoncelen = strlen(opt->client_nonce_string);
384178825Sdfr	client_nonce = malloc(cnoncelen);
385178825Sdfr	if (client_nonce == NULL)
386178825Sdfr	    errx(1, "client_nonce");
387233294Sstas
388233294Sstas	cnoncelen = hex_decode(opt->client_nonce_string,
389178825Sdfr			       client_nonce, cnoncelen);
390233294Sstas	if (cnoncelen <= 0)
391178825Sdfr	    errx(1, "client nonce wrong");
392178825Sdfr    }
393178825Sdfr
394178825Sdfr    if (opt->server_identifier_string) {
395178825Sdfr	int ret;
396178825Sdfr
397178825Sdfr	ret = hex_decode(opt->server_identifier_string, &server_identifier, 1);
398178825Sdfr	if (ret != 1)
399178825Sdfr	    errx(1, "server identifier wrong length");
400178825Sdfr    }
401178825Sdfr
402178825Sdfr    if (strcasecmp(opt->type_string, "CHAP") == 0) {
403178825Sdfr	if (opt->server_identifier_string == NULL)
404178825Sdfr	    errx(1, "server identifier missing");
405178825Sdfr
406233294Sstas	client_chap(server_nonce, snoncelen, server_identifier,
407178825Sdfr		    opt->password_string);
408178825Sdfr
409178825Sdfr    } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) {
410178825Sdfr	if (opt->client_nonce_string == NULL)
411178825Sdfr	    errx(1, "client nonce missing");
412178825Sdfr	if (opt->username_string == NULL)
413178825Sdfr	    errx(1, "client nonce missing");
414178825Sdfr
415178825Sdfr	client_mschapv2(server_nonce, snoncelen,
416233294Sstas			client_nonce, cnoncelen,
417178825Sdfr			opt->username_string,
418178825Sdfr			opt->password_string);
419178825Sdfr    }
420233294Sstas    if (client_nonce)
421233294Sstas	free(client_nonce);
422233294Sstas    free(server_nonce);
423178825Sdfr
424178825Sdfr    return 0;
425178825Sdfr}
426178825Sdfr
427178825Sdfr#include <heimntlm.h>
428178825Sdfr
429178825Sdfrint
430178825Sdfrntlm_server_init(struct ntlm_server_init_options *opt,
431178825Sdfr		 int argc, char ** argv)
432178825Sdfr{
433178825Sdfr    krb5_error_code ret;
434178825Sdfr    krb5_ntlm ntlm;
435178825Sdfr    struct ntlm_type2 type2;
436233294Sstas    krb5_data challenge, opaque;
437178825Sdfr    struct ntlm_buf data;
438178825Sdfr    char *s;
439233294Sstas    static char zero2[] = "\x00\x00";
440178825Sdfr
441178825Sdfr    memset(&type2, 0, sizeof(type2));
442178825Sdfr
443178825Sdfr    ret = krb5_ntlm_alloc(context, &ntlm);
444178825Sdfr    if (ret)
445178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_alloc");
446178825Sdfr
447233294Sstas    ret = krb5_ntlm_init_request(context,
448178825Sdfr				 ntlm,
449178825Sdfr				 opt->kerberos_realm_string,
450178825Sdfr				 id,
451178825Sdfr				 NTLM_NEG_UNICODE|NTLM_NEG_NTLM,
452178825Sdfr				 "NUTCRACKER",
453178825Sdfr				 "L");
454178825Sdfr    if (ret)
455178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_request");
456178825Sdfr
457178825Sdfr    /*
458178825Sdfr     *
459178825Sdfr     */
460178825Sdfr
461233294Sstas    ret = krb5_ntlm_init_get_challange(context, ntlm, &challenge);
462178825Sdfr    if (ret)
463178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_challange");
464178825Sdfr
465233294Sstas    if (challenge.length != sizeof(type2.challenge))
466233294Sstas	krb5_errx(context, 1, "ntlm challenge have wrong length");
467233294Sstas    memcpy(type2.challenge, challenge.data, sizeof(type2.challenge));
468233294Sstas    krb5_data_free(&challenge);
469178825Sdfr
470178825Sdfr    ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags);
471178825Sdfr    if (ret)
472178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags");
473178825Sdfr
474178825Sdfr    krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname);
475233294Sstas    type2.targetinfo.data = zero2;
476178825Sdfr    type2.targetinfo.length = 2;
477233294Sstas
478178825Sdfr    ret = heim_ntlm_encode_type2(&type2, &data);
479178825Sdfr    if (ret)
480178825Sdfr	krb5_errx(context, 1, "heim_ntlm_encode_type2");
481178825Sdfr
482178825Sdfr    free(type2.targetname);
483233294Sstas
484178825Sdfr    /*
485178825Sdfr     *
486178825Sdfr     */
487178825Sdfr
488178825Sdfr    base64_encode(data.data, data.length, &s);
489178825Sdfr    free(data.data);
490178825Sdfr    printf("type2=%s\n", s);
491178825Sdfr    free(s);
492178825Sdfr
493178825Sdfr    /*
494178825Sdfr     *
495178825Sdfr     */
496178825Sdfr
497178825Sdfr    ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque);
498178825Sdfr    if (ret)
499178825Sdfr	krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque");
500178825Sdfr
501178825Sdfr    base64_encode(opaque.data, opaque.length, &s);
502178825Sdfr    krb5_data_free(&opaque);
503178825Sdfr    printf("opaque=%s\n", s);
504178825Sdfr    free(s);
505178825Sdfr
506178825Sdfr    /*
507178825Sdfr     *
508178825Sdfr     */
509178825Sdfr
510178825Sdfr    krb5_ntlm_free(context, ntlm);
511178825Sdfr
512178825Sdfr    return 0;
513178825Sdfr}
514178825Sdfr
515178825Sdfr
516178825Sdfr/*
517178825Sdfr *
518178825Sdfr */
519178825Sdfr
520178825Sdfrint
521178825Sdfrhelp(void *opt, int argc, char **argv)
522178825Sdfr{
523178825Sdfr    sl_slc_help(commands, argc, argv);
524178825Sdfr    return 0;
525178825Sdfr}
526178825Sdfr
527178825Sdfrint
528178825Sdfrmain(int argc, char **argv)
529178825Sdfr{
530178825Sdfr    krb5_error_code ret;
531178825Sdfr    int optidx = 0;
532178825Sdfr
533178825Sdfr    setprogname(argv[0]);
534178825Sdfr
535178825Sdfr    ret = krb5_init_context (&context);
536178825Sdfr    if (ret == KRB5_CONFIG_BADFORMAT)
537178825Sdfr	errx (1, "krb5_init_context failed to parse configuration file");
538178825Sdfr    else if (ret)
539178825Sdfr	errx(1, "krb5_init_context failed: %d", ret);
540178825Sdfr
541178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
542178825Sdfr	usage(1);
543233294Sstas
544178825Sdfr    if (help_flag)
545178825Sdfr	usage (0);
546178825Sdfr
547178825Sdfr    if(version_flag){
548178825Sdfr	print_version(NULL);
549178825Sdfr	exit(0);
550178825Sdfr    }
551178825Sdfr
552178825Sdfr    argc -= optidx;
553178825Sdfr    argv += optidx;
554178825Sdfr
555178825Sdfr    if (argc == 0) {
556178825Sdfr	help(NULL, argc, argv);
557178825Sdfr	return 1;
558178825Sdfr    }
559178825Sdfr
560178825Sdfr    if (ccache_string) {
561178825Sdfr	ret = krb5_cc_resolve(context, ccache_string, &id);
562178825Sdfr	if (ret)
563178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_resolve");
564178825Sdfr    }
565178825Sdfr
566178825Sdfr    ret = sl_command (commands, argc, argv);
567178825Sdfr    if (ret == -1) {
568178825Sdfr	help(NULL, argc, argv);
569178825Sdfr	return 1;
570178825Sdfr    }
571178825Sdfr    return ret;
572178825Sdfr}
573