kdigest.c revision 233294
1214455Srpaulo/* 2214455Srpaulo * Copyright (c) 2006 - 2007 Kungliga Tekniska H��gskolan 3214455Srpaulo * (Royal Institute of Technology, Stockholm, Sweden). 4214455Srpaulo * All rights reserved. 5214455Srpaulo * 6214455Srpaulo * Redistribution and use in source and binary forms, with or without 7214455Srpaulo * modification, are permitted provided that the following conditions 8214455Srpaulo * are met: 9214455Srpaulo * 10214455Srpaulo * 1. Redistributions of source code must retain the above copyright 11214455Srpaulo * notice, this list of conditions and the following disclaimer. 12214455Srpaulo * 13214455Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 14214455Srpaulo * notice, this list of conditions and the following disclaimer in the 15214455Srpaulo * documentation and/or other materials provided with the distribution. 16214455Srpaulo * 17214455Srpaulo * 3. Neither the name of the Institute nor the names of its contributors 18214455Srpaulo * may be used to endorse or promote products derived from this software 19214455Srpaulo * without specific prior written permission. 20214455Srpaulo * 21214455Srpaulo * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22214455Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23214455Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24214455Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25214455Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26214455Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27214455Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28214455Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29214455Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30214455Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31214455Srpaulo * SUCH DAMAGE. 32214455Srpaulo */ 33214455Srpaulo 34214455Srpaulo#define HC_DEPRECATED_CRYPTO 35214455Srpaulo 36214455Srpaulo#include "kuser_locl.h" 37214455Srpaulo 38214455Srpaulo#include <kdigest-commands.h> 39214455Srpaulo#include <hex.h> 40214455Srpaulo#include <base64.h> 41214455Srpaulo#include <heimntlm.h> 42214455Srpaulo#include "crypto-headers.h" 43214455Srpaulo 44214455Srpaulostatic int version_flag = 0; 45214455Srpaulostatic int help_flag = 0; 46214455Srpaulostatic char *ccache_string; 47214455Srpaulostatic krb5_ccache id; 48214455Srpaulo 49214455Srpaulostatic struct getargs args[] = { 50214455Srpaulo {"ccache", 0, arg_string, &ccache_string, "credential cache", NULL }, 51214455Srpaulo {"version", 0, arg_flag, &version_flag, "print version", NULL }, 52214455Srpaulo {"help", 0, arg_flag, &help_flag, NULL, NULL } 53214455Srpaulo}; 54214455Srpaulo 55214455Srpaulostatic void 56214455Srpaulousage (int ret) 57214455Srpaulo{ 58214455Srpaulo arg_printusage (args, sizeof(args)/sizeof(*args), 59214455Srpaulo NULL, ""); 60214455Srpaulo exit (ret); 61214455Srpaulo} 62214455Srpaulo 63214455Srpaulostatic krb5_context context; 64214455Srpaulo 65214455Srpauloint 66214455Srpaulodigest_probe(struct digest_probe_options *opt, 67214455Srpaulo int argc, char ** argv) 68214455Srpaulo{ 69214455Srpaulo krb5_error_code ret; 70214455Srpaulo krb5_realm realm; 71214455Srpaulo unsigned flags; 72214455Srpaulo 73214455Srpaulo realm = opt->realm_string; 74214455Srpaulo 75214455Srpaulo if (realm == NULL) 76214455Srpaulo errx(1, "realm missing"); 77214455Srpaulo 78214455Srpaulo ret = krb5_digest_probe(context, realm, id, &flags); 79214455Srpaulo if (ret) 80214455Srpaulo krb5_err(context, 1, ret, "digest_probe"); 81214455Srpaulo 82214455Srpaulo printf("flags: %u\n", flags); 83214455Srpaulo 84214455Srpaulo return 0; 85214455Srpaulo} 86214455Srpaulo 87214455Srpauloint 88214455Srpaulodigest_server_init(struct digest_server_init_options *opt, 89214455Srpaulo int argc, char ** argv) 90214455Srpaulo{ 91214455Srpaulo krb5_error_code ret; 92214455Srpaulo krb5_digest digest; 93214455Srpaulo 94214455Srpaulo ret = krb5_digest_alloc(context, &digest); 95214455Srpaulo if (ret) 96214455Srpaulo krb5_err(context, 1, ret, "digest_alloc"); 97214455Srpaulo 98214455Srpaulo ret = krb5_digest_set_type(context, digest, opt->type_string); 99214455Srpaulo if (ret) 100214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_type"); 101214455Srpaulo 102214455Srpaulo if (opt->cb_type_string && opt->cb_value_string) { 103214455Srpaulo ret = krb5_digest_set_server_cb(context, digest, 104214455Srpaulo opt->cb_type_string, 105214455Srpaulo opt->cb_value_string); 106214455Srpaulo if (ret) 107214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_server_cb"); 108214455Srpaulo } 109214455Srpaulo ret = krb5_digest_init_request(context, 110214455Srpaulo digest, 111214455Srpaulo opt->kerberos_realm_string, 112214455Srpaulo id); 113214455Srpaulo if (ret) 114214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_init_request"); 115214455Srpaulo 116214455Srpaulo printf("type=%s\n", opt->type_string); 117214455Srpaulo printf("server-nonce=%s\n", 118214455Srpaulo krb5_digest_get_server_nonce(context, digest)); 119214455Srpaulo { 120214455Srpaulo const char *s = krb5_digest_get_identifier(context, digest); 121214455Srpaulo if (s) 122214455Srpaulo printf("identifier=%s\n", s); 123214455Srpaulo } 124214455Srpaulo printf("opaque=%s\n", krb5_digest_get_opaque(context, digest)); 125214455Srpaulo 126214455Srpaulo krb5_digest_free(digest); 127214455Srpaulo 128214455Srpaulo return 0; 129214455Srpaulo} 130214455Srpaulo 131214455Srpauloint 132214455Srpaulodigest_server_request(struct digest_server_request_options *opt, 133214455Srpaulo int argc, char **argv) 134214455Srpaulo{ 135214455Srpaulo krb5_error_code ret; 136214455Srpaulo krb5_digest digest; 137214455Srpaulo const char *status, *rsp; 138214455Srpaulo krb5_data session_key; 139214455Srpaulo 140214455Srpaulo if (opt->server_nonce_string == NULL) 141214455Srpaulo errx(1, "server nonce missing"); 142214455Srpaulo if (opt->type_string == NULL) 143214455Srpaulo errx(1, "type missing"); 144214455Srpaulo if (opt->opaque_string == NULL) 145214455Srpaulo errx(1, "opaque missing"); 146214455Srpaulo if (opt->client_response_string == NULL) 147214455Srpaulo errx(1, "client response missing"); 148214455Srpaulo 149214455Srpaulo ret = krb5_digest_alloc(context, &digest); 150214455Srpaulo if (ret) 151214455Srpaulo krb5_err(context, 1, ret, "digest_alloc"); 152214455Srpaulo 153214455Srpaulo if (strcasecmp(opt->type_string, "CHAP") == 0) { 154214455Srpaulo if (opt->server_identifier_string == NULL) 155214455Srpaulo errx(1, "server identifier missing"); 156214455Srpaulo 157214455Srpaulo ret = krb5_digest_set_identifier(context, digest, 158214455Srpaulo opt->server_identifier_string); 159214455Srpaulo if (ret) 160214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_type"); 161214455Srpaulo } 162214455Srpaulo 163214455Srpaulo ret = krb5_digest_set_type(context, digest, opt->type_string); 164214455Srpaulo if (ret) 165214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_type"); 166214455Srpaulo 167214455Srpaulo ret = krb5_digest_set_username(context, digest, opt->username_string); 168214455Srpaulo if (ret) 169214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_username"); 170214455Srpaulo 171214455Srpaulo ret = krb5_digest_set_server_nonce(context, digest, 172214455Srpaulo opt->server_nonce_string); 173214455Srpaulo if (ret) 174214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_server_nonce"); 175214455Srpaulo 176214455Srpaulo if(opt->client_nonce_string) { 177214455Srpaulo ret = krb5_digest_set_client_nonce(context, digest, 178214455Srpaulo opt->client_nonce_string); 179214455Srpaulo if (ret) 180214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_client_nonce"); 181214455Srpaulo } 182214455Srpaulo 183214455Srpaulo 184214455Srpaulo ret = krb5_digest_set_opaque(context, digest, opt->opaque_string); 185214455Srpaulo if (ret) 186214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_opaque"); 187214455Srpaulo 188214455Srpaulo ret = krb5_digest_set_responseData(context, digest, 189214455Srpaulo opt->client_response_string); 190214455Srpaulo if (ret) 191214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_set_responseData"); 192214455Srpaulo 193214455Srpaulo ret = krb5_digest_request(context, digest, 194214455Srpaulo opt->kerberos_realm_string, id); 195214455Srpaulo if (ret) 196214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_request"); 197214455Srpaulo 198214455Srpaulo status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed"; 199214455Srpaulo rsp = krb5_digest_get_rsp(context, digest); 200214455Srpaulo 201214455Srpaulo printf("status=%s\n", status); 202214455Srpaulo if (rsp) 203214455Srpaulo printf("rsp=%s\n", rsp); 204214455Srpaulo printf("tickets=no\n"); 205214455Srpaulo 206214455Srpaulo ret = krb5_digest_get_session_key(context, digest, &session_key); 207214455Srpaulo if (ret) 208214455Srpaulo krb5_err(context, 1, ret, "krb5_digest_get_session_key"); 209214455Srpaulo 210214455Srpaulo if (session_key.length) { 211214455Srpaulo char *key; 212214455Srpaulo hex_encode(session_key.data, session_key.length, &key); 213214455Srpaulo if (key == NULL) 214214455Srpaulo krb5_errx(context, 1, "hex_encode"); 215214455Srpaulo krb5_data_free(&session_key); 216214455Srpaulo printf("session-key=%s\n", key); 217214455Srpaulo free(key); 218214455Srpaulo } 219214455Srpaulo 220214455Srpaulo krb5_digest_free(digest); 221214455Srpaulo 222214455Srpaulo return 0; 223214455Srpaulo} 224214455Srpaulo 225214455Srpaulostatic void 226214455Srpauloclient_chap(const void *server_nonce, size_t snoncelen, 227214455Srpaulo unsigned char server_identifier, 228214455Srpaulo const char *password) 229214455Srpaulo{ 230214455Srpaulo EVP_MD_CTX *ctx; 231214455Srpaulo unsigned char md[MD5_DIGEST_LENGTH]; 232214455Srpaulo char *h; 233214455Srpaulo 234214455Srpaulo ctx = EVP_MD_CTX_create(); 235214455Srpaulo EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 236214455Srpaulo 237214455Srpaulo EVP_DigestUpdate(ctx, &server_identifier, 1); 238214455Srpaulo EVP_DigestUpdate(ctx, password, strlen(password)); 239214455Srpaulo EVP_DigestUpdate(ctx, server_nonce, snoncelen); 240214455Srpaulo EVP_DigestFinal_ex(ctx, md, NULL); 241214455Srpaulo 242214455Srpaulo EVP_MD_CTX_destroy(ctx); 243214455Srpaulo 244214455Srpaulo hex_encode(md, 16, &h); 245214455Srpaulo 246214455Srpaulo printf("responseData=%s\n", h); 247214455Srpaulo free(h); 248214455Srpaulo} 249214455Srpaulo 250214455Srpaulostatic const unsigned char ms_chap_v2_magic1[39] = { 251214455Srpaulo 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 252214455Srpaulo 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 253214455Srpaulo 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 254214455Srpaulo 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 255214455Srpaulo}; 256214455Srpaulostatic const unsigned char ms_chap_v2_magic2[41] = { 257214455Srpaulo 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 258214455Srpaulo 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 259214455Srpaulo 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 260214455Srpaulo 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 261214455Srpaulo 0x6E 262214455Srpaulo}; 263214455Srpaulostatic const unsigned char ms_rfc3079_magic1[27] = { 264214455Srpaulo 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 265214455Srpaulo 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 266214455Srpaulo 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 267214455Srpaulo}; 268214455Srpaulo 269214455Srpaulostatic void 270214455Srpauloclient_mschapv2(const void *server_nonce, size_t snoncelen, 271214455Srpaulo const void *client_nonce, size_t cnoncelen, 272214455Srpaulo const char *username, 273214455Srpaulo const char *password) 274214455Srpaulo{ 275214455Srpaulo EVP_MD_CTX *hctx, *ctx; 276214455Srpaulo unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH]; 277214455Srpaulo unsigned char hmd[MD4_DIGEST_LENGTH]; 278214455Srpaulo struct ntlm_buf answer; 279214455Srpaulo int i, len, ret; 280214455Srpaulo char *h; 281214455Srpaulo 282214455Srpaulo ctx = EVP_MD_CTX_create(); 283214455Srpaulo EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 284214455Srpaulo 285214455Srpaulo EVP_DigestUpdate(ctx, client_nonce, cnoncelen); 286214455Srpaulo EVP_DigestUpdate(ctx, server_nonce, snoncelen); 287214455Srpaulo EVP_DigestUpdate(ctx, username, strlen(username)); 288214455Srpaulo EVP_DigestFinal_ex(ctx, md, NULL); 289214455Srpaulo 290214455Srpaulo 291214455Srpaulo hctx = EVP_MD_CTX_create(); 292214455Srpaulo EVP_DigestInit_ex(hctx, EVP_md4(), NULL); 293214455Srpaulo len = strlen(password); 294214455Srpaulo for (i = 0; i < len; i++) { 295214455Srpaulo EVP_DigestUpdate(hctx, &password[i], 1); 296214455Srpaulo EVP_DigestUpdate(hctx, &password[len], 1); 297214455Srpaulo } 298214455Srpaulo EVP_DigestFinal_ex(hctx, hmd, NULL); 299214455Srpaulo 300214455Srpaulo 301214455Srpaulo /* ChallengeResponse */ 302214455Srpaulo ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer); 303214455Srpaulo if (ret) 304214455Srpaulo errx(1, "heim_ntlm_calculate_ntlm1"); 305214455Srpaulo 306214455Srpaulo hex_encode(answer.data, answer.length, &h); 307214455Srpaulo printf("responseData=%s\n", h); 308214455Srpaulo free(h); 309214455Srpaulo 310214455Srpaulo /* PasswordHash */ 311214455Srpaulo EVP_DigestInit_ex(hctx, EVP_md4(), NULL); 312214455Srpaulo EVP_DigestUpdate(hctx, hmd, sizeof(hmd)); 313214455Srpaulo EVP_DigestFinal_ex(hctx, hmd, NULL); 314214455Srpaulo 315214455Srpaulo 316214455Srpaulo /* GenerateAuthenticatorResponse */ 317214455Srpaulo EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 318214455Srpaulo EVP_DigestUpdate(ctx, hmd, sizeof(hmd)); 319214455Srpaulo EVP_DigestUpdate(ctx, answer.data, answer.length); 320214455Srpaulo EVP_DigestUpdate(ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1)); 321214455Srpaulo EVP_DigestFinal_ex(ctx, md, NULL); 322214455Srpaulo 323214455Srpaulo /* ChallengeHash */ 324214455Srpaulo EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 325214455Srpaulo EVP_DigestUpdate(ctx, client_nonce, cnoncelen); 326214455Srpaulo EVP_DigestUpdate(ctx, server_nonce, snoncelen); 327214455Srpaulo EVP_DigestUpdate(ctx, username, strlen(username)); 328214455Srpaulo EVP_DigestFinal_ex(ctx, challenge, NULL); 329214455Srpaulo 330214455Srpaulo EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 331214455Srpaulo EVP_DigestUpdate(ctx, md, sizeof(md)); 332214455Srpaulo EVP_DigestUpdate(ctx, challenge, 8); 333214455Srpaulo EVP_DigestUpdate(ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2)); 334214455Srpaulo EVP_DigestFinal_ex(ctx, md, NULL); 335214455Srpaulo 336214455Srpaulo hex_encode(md, sizeof(md), &h); 337214455Srpaulo printf("AuthenticatorResponse=%s\n", h); 338214455Srpaulo free(h); 339214455Srpaulo 340214455Srpaulo /* get_master, rfc 3079 3.4 */ 341214455Srpaulo EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 342214455Srpaulo EVP_DigestUpdate(ctx, hmd, sizeof(hmd)); 343214455Srpaulo EVP_DigestUpdate(ctx, answer.data, answer.length); 344214455Srpaulo EVP_DigestUpdate(ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1)); 345214455Srpaulo EVP_DigestFinal_ex(ctx, md, NULL); 346214455Srpaulo 347214455Srpaulo free(answer.data); 348214455Srpaulo 349214455Srpaulo hex_encode(md, 16, &h); 350214455Srpaulo printf("session-key=%s\n", h); 351214455Srpaulo free(h); 352214455Srpaulo 353214455Srpaulo EVP_MD_CTX_destroy(hctx); 354214455Srpaulo EVP_MD_CTX_destroy(ctx); 355214455Srpaulo} 356214455Srpaulo 357214455Srpaulo 358214455Srpauloint 359214455Srpaulodigest_client_request(struct digest_client_request_options *opt, 360214455Srpaulo int argc, char **argv) 361214455Srpaulo{ 362214455Srpaulo char *server_nonce, *client_nonce = NULL, server_identifier; 363214455Srpaulo ssize_t snoncelen, cnoncelen = 0; 364214455Srpaulo 365214455Srpaulo if (opt->server_nonce_string == NULL) 366214455Srpaulo errx(1, "server nonce missing"); 367214455Srpaulo if (opt->password_string == NULL) 368214455Srpaulo errx(1, "password missing"); 369214455Srpaulo 370214455Srpaulo if (opt->opaque_string == NULL) 371214455Srpaulo errx(1, "opaque missing"); 372214455Srpaulo 373214455Srpaulo snoncelen = strlen(opt->server_nonce_string); 374214455Srpaulo server_nonce = malloc(snoncelen); 375214455Srpaulo if (server_nonce == NULL) 376214455Srpaulo errx(1, "server_nonce"); 377214455Srpaulo 378214455Srpaulo snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen); 379214455Srpaulo if (snoncelen <= 0) 380214455Srpaulo errx(1, "server nonce wrong"); 381214455Srpaulo 382214455Srpaulo if (opt->client_nonce_string) { 383214455Srpaulo cnoncelen = strlen(opt->client_nonce_string); 384214455Srpaulo client_nonce = malloc(cnoncelen); 385214455Srpaulo if (client_nonce == NULL) 386214455Srpaulo errx(1, "client_nonce"); 387214455Srpaulo 388214455Srpaulo cnoncelen = hex_decode(opt->client_nonce_string, 389214455Srpaulo client_nonce, cnoncelen); 390214455Srpaulo if (cnoncelen <= 0) 391214455Srpaulo errx(1, "client nonce wrong"); 392214455Srpaulo } 393214455Srpaulo 394214455Srpaulo if (opt->server_identifier_string) { 395214455Srpaulo int ret; 396214455Srpaulo 397214455Srpaulo ret = hex_decode(opt->server_identifier_string, &server_identifier, 1); 398214455Srpaulo if (ret != 1) 399214455Srpaulo errx(1, "server identifier wrong length"); 400214455Srpaulo } 401214455Srpaulo 402214455Srpaulo if (strcasecmp(opt->type_string, "CHAP") == 0) { 403214455Srpaulo if (opt->server_identifier_string == NULL) 404214455Srpaulo errx(1, "server identifier missing"); 405214455Srpaulo 406214455Srpaulo client_chap(server_nonce, snoncelen, server_identifier, 407214455Srpaulo opt->password_string); 408214455Srpaulo 409214455Srpaulo } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) { 410214455Srpaulo if (opt->client_nonce_string == NULL) 411214455Srpaulo errx(1, "client nonce missing"); 412214455Srpaulo if (opt->username_string == NULL) 413214455Srpaulo errx(1, "client nonce missing"); 414214455Srpaulo 415214455Srpaulo client_mschapv2(server_nonce, snoncelen, 416214455Srpaulo client_nonce, cnoncelen, 417214455Srpaulo opt->username_string, 418214455Srpaulo opt->password_string); 419214455Srpaulo } 420214455Srpaulo if (client_nonce) 421214455Srpaulo free(client_nonce); 422214455Srpaulo free(server_nonce); 423214455Srpaulo 424214455Srpaulo return 0; 425214455Srpaulo} 426214455Srpaulo 427214455Srpaulo#include <heimntlm.h> 428214455Srpaulo 429214455Srpauloint 430214455Srpaulontlm_server_init(struct ntlm_server_init_options *opt, 431214455Srpaulo int argc, char ** argv) 432214455Srpaulo{ 433214455Srpaulo krb5_error_code ret; 434214455Srpaulo krb5_ntlm ntlm; 435214455Srpaulo struct ntlm_type2 type2; 436214455Srpaulo krb5_data challenge, opaque; 437214455Srpaulo struct ntlm_buf data; 438214455Srpaulo char *s; 439214455Srpaulo static char zero2[] = "\x00\x00"; 440214455Srpaulo 441214455Srpaulo memset(&type2, 0, sizeof(type2)); 442214455Srpaulo 443214455Srpaulo ret = krb5_ntlm_alloc(context, &ntlm); 444214455Srpaulo if (ret) 445214455Srpaulo krb5_err(context, 1, ret, "krb5_ntlm_alloc"); 446214455Srpaulo 447214455Srpaulo ret = krb5_ntlm_init_request(context, 448214455Srpaulo ntlm, 449214455Srpaulo opt->kerberos_realm_string, 450214455Srpaulo id, 451214455Srpaulo NTLM_NEG_UNICODE|NTLM_NEG_NTLM, 452214455Srpaulo "NUTCRACKER", 453214455Srpaulo "L"); 454214455Srpaulo if (ret) 455214455Srpaulo krb5_err(context, 1, ret, "krb5_ntlm_init_request"); 456214455Srpaulo 457214455Srpaulo /* 458214455Srpaulo * 459214455Srpaulo */ 460214455Srpaulo 461214455Srpaulo ret = krb5_ntlm_init_get_challange(context, ntlm, &challenge); 462214455Srpaulo if (ret) 463214455Srpaulo krb5_err(context, 1, ret, "krb5_ntlm_init_get_challange"); 464214455Srpaulo 465214455Srpaulo if (challenge.length != sizeof(type2.challenge)) 466214455Srpaulo krb5_errx(context, 1, "ntlm challenge have wrong length"); 467214455Srpaulo memcpy(type2.challenge, challenge.data, sizeof(type2.challenge)); 468214455Srpaulo krb5_data_free(&challenge); 469214455Srpaulo 470214455Srpaulo ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags); 471214455Srpaulo if (ret) 472214455Srpaulo krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags"); 473214455Srpaulo 474214455Srpaulo krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname); 475214455Srpaulo type2.targetinfo.data = zero2; 476214455Srpaulo type2.targetinfo.length = 2; 477214455Srpaulo 478214455Srpaulo ret = heim_ntlm_encode_type2(&type2, &data); 479214455Srpaulo if (ret) 480214455Srpaulo krb5_errx(context, 1, "heim_ntlm_encode_type2"); 481214455Srpaulo 482214455Srpaulo free(type2.targetname); 483214455Srpaulo 484214455Srpaulo /* 485214455Srpaulo * 486214455Srpaulo */ 487214455Srpaulo 488214455Srpaulo base64_encode(data.data, data.length, &s); 489214455Srpaulo free(data.data); 490214455Srpaulo printf("type2=%s\n", s); 491214455Srpaulo free(s); 492214455Srpaulo 493214455Srpaulo /* 494214455Srpaulo * 495214455Srpaulo */ 496214455Srpaulo 497214455Srpaulo ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque); 498214455Srpaulo if (ret) 499214455Srpaulo krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque"); 500214455Srpaulo 501214455Srpaulo base64_encode(opaque.data, opaque.length, &s); 502214455Srpaulo krb5_data_free(&opaque); 503214455Srpaulo printf("opaque=%s\n", s); 504214455Srpaulo free(s); 505214455Srpaulo 506214455Srpaulo /* 507214455Srpaulo * 508214455Srpaulo */ 509214455Srpaulo 510214455Srpaulo krb5_ntlm_free(context, ntlm); 511214455Srpaulo 512214455Srpaulo return 0; 513214455Srpaulo} 514214455Srpaulo 515214455Srpaulo 516214455Srpaulo/* 517214455Srpaulo * 518214455Srpaulo */ 519214455Srpaulo 520214455Srpauloint 521214455Srpaulohelp(void *opt, int argc, char **argv) 522214455Srpaulo{ 523214455Srpaulo sl_slc_help(commands, argc, argv); 524214455Srpaulo return 0; 525214455Srpaulo} 526214455Srpaulo 527214455Srpauloint 528214455Srpaulomain(int argc, char **argv) 529214455Srpaulo{ 530214455Srpaulo krb5_error_code ret; 531214455Srpaulo int optidx = 0; 532214455Srpaulo 533214455Srpaulo setprogname(argv[0]); 534214455Srpaulo 535214455Srpaulo ret = krb5_init_context (&context); 536214455Srpaulo if (ret == KRB5_CONFIG_BADFORMAT) 537214455Srpaulo errx (1, "krb5_init_context failed to parse configuration file"); 538214455Srpaulo else if (ret) 539214455Srpaulo errx(1, "krb5_init_context failed: %d", ret); 540214455Srpaulo 541214455Srpaulo if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 542214455Srpaulo usage(1); 543214455Srpaulo 544214455Srpaulo if (help_flag) 545214455Srpaulo usage (0); 546214455Srpaulo 547214455Srpaulo if(version_flag){ 548214455Srpaulo print_version(NULL); 549214455Srpaulo exit(0); 550214455Srpaulo } 551214455Srpaulo 552214455Srpaulo argc -= optidx; 553214455Srpaulo argv += optidx; 554214455Srpaulo 555214455Srpaulo if (argc == 0) { 556214455Srpaulo help(NULL, argc, argv); 557214455Srpaulo return 1; 558214455Srpaulo } 559214455Srpaulo 560214455Srpaulo if (ccache_string) { 561214455Srpaulo ret = krb5_cc_resolve(context, ccache_string, &id); 562214455Srpaulo if (ret) 563214455Srpaulo krb5_err(context, 1, ret, "krb5_cc_resolve"); 564214455Srpaulo } 565214455Srpaulo 566214455Srpaulo ret = sl_command (commands, argc, argv); 567214455Srpaulo if (ret == -1) { 568214455Srpaulo help(NULL, argc, argv); 569214455Srpaulo return 1; 570214455Srpaulo } 571214455Srpaulo return ret; 572214455Srpaulo} 573214455Srpaulo