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