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