No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / kuser / kdigest.c
bloba4572b218140c7b369f7d2bc84a99638c5c9a042
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "kuser_locl.h"
35 __RCSID("$Heimdal: kdigest.c 22158 2007-12-04 20:04:01Z lha $"
36 "$NetBSD$");
37 #include <kdigest-commands.h>
38 #include <hex.h>
39 #include <base64.h>
40 #include <heimntlm.h>
41 #include "crypto-headers.h"
43 static int version_flag = 0;
44 static int help_flag = 0;
45 static char *ccache_string;
46 static krb5_ccache id;
48 static struct getargs args[] = {
49 {"ccache", 0, arg_string, &ccache_string, "credential cache", NULL },
50 {"version", 0, arg_flag, &version_flag, "print version", NULL },
51 {"help", 0, arg_flag, &help_flag, NULL, NULL }
54 static void
55 usage (int ret)
57 arg_printusage (args, sizeof(args)/sizeof(*args),
58 NULL, "");
59 exit (ret);
62 static krb5_context context;
64 int
65 digest_probe(struct digest_probe_options *opt,
66 int argc, char ** argv)
68 krb5_error_code ret;
69 krb5_realm realm;
70 unsigned flags;
72 realm = opt->realm_string;
74 if (realm == NULL)
75 errx(1, "realm missing");
77 ret = krb5_digest_probe(context, realm, id, &flags);
78 if (ret)
79 krb5_err(context, 1, ret, "digest_probe");
81 printf("flags: %u\n", flags);
83 return 0;
86 int
87 digest_server_init(struct digest_server_init_options *opt,
88 int argc, char ** argv)
90 krb5_error_code ret;
91 krb5_digest digest;
93 ret = krb5_digest_alloc(context, &digest);
94 if (ret)
95 krb5_err(context, 1, ret, "digest_alloc");
97 ret = krb5_digest_set_type(context, digest, opt->type_string);
98 if (ret)
99 krb5_err(context, 1, ret, "krb5_digest_set_type");
101 if (opt->cb_type_string && opt->cb_value_string) {
102 ret = krb5_digest_set_server_cb(context, digest,
103 opt->cb_type_string,
104 opt->cb_value_string);
105 if (ret)
106 krb5_err(context, 1, ret, "krb5_digest_set_server_cb");
108 ret = krb5_digest_init_request(context,
109 digest,
110 opt->kerberos_realm_string,
111 id);
112 if (ret)
113 krb5_err(context, 1, ret, "krb5_digest_init_request");
115 printf("type=%s\n", opt->type_string);
116 printf("server-nonce=%s\n",
117 krb5_digest_get_server_nonce(context, digest));
119 const char *s = krb5_digest_get_identifier(context, digest);
120 if (s)
121 printf("identifier=%s\n", s);
123 printf("opaque=%s\n", krb5_digest_get_opaque(context, digest));
125 return 0;
129 digest_server_request(struct digest_server_request_options *opt,
130 int argc, char **argv)
132 krb5_error_code ret;
133 krb5_digest digest;
134 const char *status, *rsp;
135 krb5_data session_key;
137 if (opt->server_nonce_string == NULL)
138 errx(1, "server nonce missing");
139 if (opt->type_string == NULL)
140 errx(1, "type missing");
141 if (opt->opaque_string == NULL)
142 errx(1, "opaque missing");
143 if (opt->client_response_string == NULL)
144 errx(1, "client response missing");
146 ret = krb5_digest_alloc(context, &digest);
147 if (ret)
148 krb5_err(context, 1, ret, "digest_alloc");
150 if (strcasecmp(opt->type_string, "CHAP") == 0) {
151 if (opt->server_identifier_string == NULL)
152 errx(1, "server identifier missing");
154 ret = krb5_digest_set_identifier(context, digest,
155 opt->server_identifier_string);
156 if (ret)
157 krb5_err(context, 1, ret, "krb5_digest_set_type");
160 ret = krb5_digest_set_type(context, digest, opt->type_string);
161 if (ret)
162 krb5_err(context, 1, ret, "krb5_digest_set_type");
164 ret = krb5_digest_set_username(context, digest, opt->username_string);
165 if (ret)
166 krb5_err(context, 1, ret, "krb5_digest_set_username");
168 ret = krb5_digest_set_server_nonce(context, digest,
169 opt->server_nonce_string);
170 if (ret)
171 krb5_err(context, 1, ret, "krb5_digest_set_server_nonce");
173 if(opt->client_nonce_string) {
174 ret = krb5_digest_set_client_nonce(context, digest,
175 opt->client_nonce_string);
176 if (ret)
177 krb5_err(context, 1, ret, "krb5_digest_set_client_nonce");
181 ret = krb5_digest_set_opaque(context, digest, opt->opaque_string);
182 if (ret)
183 krb5_err(context, 1, ret, "krb5_digest_set_opaque");
185 ret = krb5_digest_set_responseData(context, digest,
186 opt->client_response_string);
187 if (ret)
188 krb5_err(context, 1, ret, "krb5_digest_set_responseData");
190 ret = krb5_digest_request(context, digest,
191 opt->kerberos_realm_string, id);
192 if (ret)
193 krb5_err(context, 1, ret, "krb5_digest_request");
195 status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed";
196 rsp = krb5_digest_get_rsp(context, digest);
198 printf("status=%s\n", status);
199 if (rsp)
200 printf("rsp=%s\n", rsp);
201 printf("tickets=no\n");
203 ret = krb5_digest_get_session_key(context, digest, &session_key);
204 if (ret)
205 krb5_err(context, 1, ret, "krb5_digest_get_session_key");
207 if (session_key.length) {
208 char *key;
209 hex_encode(session_key.data, session_key.length, &key);
210 if (key == NULL)
211 krb5_errx(context, 1, "hex_encode");
212 krb5_data_free(&session_key);
213 printf("session-key=%s\n", key);
214 free(key);
217 return 0;
220 static void
221 client_chap(const void *server_nonce, size_t snoncelen,
222 unsigned char server_identifier,
223 const char *password)
225 MD5_CTX ctx;
226 unsigned char md[MD5_DIGEST_LENGTH];
227 char *h;
229 MD5_Init(&ctx);
230 MD5_Update(&ctx, &server_identifier, 1);
231 MD5_Update(&ctx, password, strlen(password));
232 MD5_Update(&ctx, server_nonce, snoncelen);
233 MD5_Final(md, &ctx);
235 hex_encode(md, 16, &h);
237 printf("responseData=%s\n", h);
238 free(h);
241 static const unsigned char ms_chap_v2_magic1[39] = {
242 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
243 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
244 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
245 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
247 static const unsigned char ms_chap_v2_magic2[41] = {
248 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
249 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
250 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
251 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
252 0x6E
254 static const unsigned char ms_rfc3079_magic1[27] = {
255 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
256 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
257 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
260 static void
261 client_mschapv2(const void *server_nonce, size_t snoncelen,
262 const void *client_nonce, size_t cnoncelen,
263 const char *username,
264 const char *password)
266 SHA_CTX ctx;
267 MD4_CTX hctx;
268 unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
269 unsigned char hmd[MD4_DIGEST_LENGTH];
270 struct ntlm_buf answer;
271 int i, len, ret;
272 char *h;
274 SHA1_Init(&ctx);
275 SHA1_Update(&ctx, client_nonce, cnoncelen);
276 SHA1_Update(&ctx, server_nonce, snoncelen);
277 SHA1_Update(&ctx, username, strlen(username));
278 SHA1_Final(md, &ctx);
280 MD4_Init(&hctx);
281 len = strlen(password);
282 for (i = 0; i < len; i++) {
283 MD4_Update(&hctx, &password[i], 1);
284 MD4_Update(&hctx, &password[len], 1);
286 MD4_Final(hmd, &hctx);
288 /* ChallengeResponse */
289 ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer);
290 if (ret)
291 errx(1, "heim_ntlm_calculate_ntlm1");
293 hex_encode(answer.data, answer.length, &h);
294 printf("responseData=%s\n", h);
295 free(h);
297 /* PasswordHash */
298 MD4_Init(&hctx);
299 MD4_Update(&hctx, hmd, sizeof(hmd));
300 MD4_Final(hmd, &hctx);
302 /* GenerateAuthenticatorResponse */
303 SHA1_Init(&ctx);
304 SHA1_Update(&ctx, hmd, sizeof(hmd));
305 SHA1_Update(&ctx, answer.data, answer.length);
306 SHA1_Update(&ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1));
307 SHA1_Final(md, &ctx);
309 /* ChallengeHash */
310 SHA1_Init(&ctx);
311 SHA1_Update(&ctx, client_nonce, cnoncelen);
312 SHA1_Update(&ctx, server_nonce, snoncelen);
313 SHA1_Update(&ctx, username, strlen(username));
314 SHA1_Final(challange, &ctx);
316 SHA1_Init(&ctx);
317 SHA1_Update(&ctx, md, sizeof(md));
318 SHA1_Update(&ctx, challange, 8);
319 SHA1_Update(&ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));
320 SHA1_Final(md, &ctx);
322 hex_encode(md, sizeof(md), &h);
323 printf("AuthenticatorResponse=%s\n", h);
324 free(h);
326 /* get_master, rfc 3079 3.4 */
327 SHA1_Init(&ctx);
328 SHA1_Update(&ctx, hmd, sizeof(hmd));
329 SHA1_Update(&ctx, answer.data, answer.length);
330 SHA1_Update(&ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));
331 SHA1_Final(md, &ctx);
333 free(answer.data);
335 hex_encode(md, 16, &h);
336 printf("session-key=%s\n", h);
337 free(h);
342 digest_client_request(struct digest_client_request_options *opt,
343 int argc, char **argv)
345 char *server_nonce, *client_nonce = NULL, server_identifier;
346 ssize_t snoncelen, cnoncelen = 0;
348 if (opt->server_nonce_string == NULL)
349 errx(1, "server nonce missing");
350 if (opt->password_string == NULL)
351 errx(1, "password missing");
353 if (opt->opaque_string == NULL)
354 errx(1, "opaque missing");
356 snoncelen = strlen(opt->server_nonce_string);
357 server_nonce = malloc(snoncelen);
358 if (server_nonce == NULL)
359 errx(1, "server_nonce");
361 snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen);
362 if (snoncelen <= 0)
363 errx(1, "server nonce wrong");
365 if (opt->client_nonce_string) {
366 cnoncelen = strlen(opt->client_nonce_string);
367 client_nonce = malloc(cnoncelen);
368 if (client_nonce == NULL)
369 errx(1, "client_nonce");
371 cnoncelen = hex_decode(opt->client_nonce_string,
372 client_nonce, cnoncelen);
373 if (cnoncelen <= 0)
374 errx(1, "client nonce wrong");
377 if (opt->server_identifier_string) {
378 int ret;
380 ret = hex_decode(opt->server_identifier_string, &server_identifier, 1);
381 if (ret != 1)
382 errx(1, "server identifier wrong length");
385 if (strcasecmp(opt->type_string, "CHAP") == 0) {
386 if (opt->server_identifier_string == NULL)
387 errx(1, "server identifier missing");
389 client_chap(server_nonce, snoncelen, server_identifier,
390 opt->password_string);
392 } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) {
393 if (opt->client_nonce_string == NULL)
394 errx(1, "client nonce missing");
395 if (opt->username_string == NULL)
396 errx(1, "client nonce missing");
398 client_mschapv2(server_nonce, snoncelen,
399 client_nonce, cnoncelen,
400 opt->username_string,
401 opt->password_string);
405 return 0;
408 #include <heimntlm.h>
411 ntlm_server_init(struct ntlm_server_init_options *opt,
412 int argc, char ** argv)
414 krb5_error_code ret;
415 krb5_ntlm ntlm;
416 struct ntlm_type2 type2;
417 krb5_data challange, opaque;
418 struct ntlm_buf data;
419 char *s;
421 memset(&type2, 0, sizeof(type2));
423 ret = krb5_ntlm_alloc(context, &ntlm);
424 if (ret)
425 krb5_err(context, 1, ret, "krb5_ntlm_alloc");
427 ret = krb5_ntlm_init_request(context,
428 ntlm,
429 opt->kerberos_realm_string,
431 NTLM_NEG_UNICODE|NTLM_NEG_NTLM,
432 "NUTCRACKER",
433 "L");
434 if (ret)
435 krb5_err(context, 1, ret, "krb5_ntlm_init_request");
441 ret = krb5_ntlm_init_get_challange(context, ntlm, &challange);
442 if (ret)
443 krb5_err(context, 1, ret, "krb5_ntlm_init_get_challange");
445 if (challange.length != sizeof(type2.challange))
446 krb5_errx(context, 1, "ntlm challange have wrong length");
447 memcpy(type2.challange, challange.data, sizeof(type2.challange));
448 krb5_data_free(&challange);
450 ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags);
451 if (ret)
452 krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags");
454 krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname);
455 type2.targetinfo.data = "\x00\x00";
456 type2.targetinfo.length = 2;
458 ret = heim_ntlm_encode_type2(&type2, &data);
459 if (ret)
460 krb5_errx(context, 1, "heim_ntlm_encode_type2");
462 free(type2.targetname);
468 base64_encode(data.data, data.length, &s);
469 free(data.data);
470 printf("type2=%s\n", s);
471 free(s);
477 ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque);
478 if (ret)
479 krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque");
481 base64_encode(opaque.data, opaque.length, &s);
482 krb5_data_free(&opaque);
483 printf("opaque=%s\n", s);
484 free(s);
490 krb5_ntlm_free(context, ntlm);
492 return 0;
501 help(void *opt, int argc, char **argv)
503 sl_slc_help(commands, argc, argv);
504 return 0;
508 main(int argc, char **argv)
510 krb5_error_code ret;
511 int optidx = 0;
513 setprogname(argv[0]);
515 ret = krb5_init_context (&context);
516 if (ret == KRB5_CONFIG_BADFORMAT)
517 errx (1, "krb5_init_context failed to parse configuration file");
518 else if (ret)
519 errx(1, "krb5_init_context failed: %d", ret);
521 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
522 usage(1);
524 if (help_flag)
525 usage (0);
527 if(version_flag){
528 print_version(NULL);
529 exit(0);
532 argc -= optidx;
533 argv += optidx;
535 if (argc == 0) {
536 help(NULL, argc, argv);
537 return 1;
540 if (ccache_string) {
541 ret = krb5_cc_resolve(context, ccache_string, &id);
542 if (ret)
543 krb5_err(context, 1, ret, "krb5_cc_resolve");
546 ret = sl_command (commands, argc, argv);
547 if (ret == -1) {
548 help(NULL, argc, argv);
549 return 1;
551 return ret;