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