1178825Sdfr/* 2233294Sstas * Copyright (c) 2006 - 2008 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of KTH nor the names of its contributors may be 18178825Sdfr * used to endorse or promote products derived from this software without 19178825Sdfr * specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22178825Sdfr * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24178825Sdfr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25178825Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26178825Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27178825Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28178825Sdfr * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29178825Sdfr * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30178825Sdfr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31178825Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "config.h" 35178825Sdfr 36233294Sstas#include <roken.h> 37178825Sdfr#include <stdio.h> 38178825Sdfr#include <gssapi.h> 39178825Sdfr#include <err.h> 40178825Sdfr#include <getarg.h> 41178825Sdfr#include "test_common.h" 42178825Sdfr 43178825Sdfr#include <krb5.h> 44178825Sdfr#include <heimntlm.h> 45178825Sdfr 46178825Sdfrstatic int 47178825Sdfrtest_libntlm_v1(int flags) 48178825Sdfr{ 49233294Sstas const char *user = "foo", 50178825Sdfr *domain = "mydomain", 51178825Sdfr *password = "digestpassword"; 52178825Sdfr OM_uint32 maj_stat, min_stat; 53178825Sdfr gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 54178825Sdfr gss_buffer_desc input, output; 55178825Sdfr struct ntlm_type1 type1; 56178825Sdfr struct ntlm_type2 type2; 57178825Sdfr struct ntlm_type3 type3; 58178825Sdfr struct ntlm_buf data; 59178825Sdfr krb5_error_code ret; 60178825Sdfr gss_name_t src_name = GSS_C_NO_NAME; 61233294Sstas 62178825Sdfr memset(&type1, 0, sizeof(type1)); 63178825Sdfr memset(&type2, 0, sizeof(type2)); 64178825Sdfr memset(&type3, 0, sizeof(type3)); 65178825Sdfr 66178825Sdfr type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags; 67178825Sdfr type1.domain = strdup(domain); 68178825Sdfr type1.hostname = NULL; 69178825Sdfr type1.os[0] = 0; 70178825Sdfr type1.os[1] = 0; 71178825Sdfr 72178825Sdfr ret = heim_ntlm_encode_type1(&type1, &data); 73178825Sdfr if (ret) 74178825Sdfr errx(1, "heim_ntlm_encode_type1"); 75178825Sdfr 76178825Sdfr input.value = data.data; 77178825Sdfr input.length = data.length; 78178825Sdfr 79178825Sdfr output.length = 0; 80178825Sdfr output.value = NULL; 81178825Sdfr 82178825Sdfr maj_stat = gss_accept_sec_context(&min_stat, 83178825Sdfr &ctx, 84178825Sdfr GSS_C_NO_CREDENTIAL, 85178825Sdfr &input, 86178825Sdfr GSS_C_NO_CHANNEL_BINDINGS, 87178825Sdfr NULL, 88178825Sdfr NULL, 89178825Sdfr &output, 90178825Sdfr NULL, 91178825Sdfr NULL, 92178825Sdfr NULL); 93178825Sdfr free(data.data); 94178825Sdfr if (GSS_ERROR(maj_stat)) 95178825Sdfr errx(1, "accept_sec_context v1: %s", 96178825Sdfr gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 97178825Sdfr 98178825Sdfr if (output.length == 0) 99178825Sdfr errx(1, "output.length == 0"); 100178825Sdfr 101178825Sdfr data.data = output.value; 102178825Sdfr data.length = output.length; 103178825Sdfr 104178825Sdfr ret = heim_ntlm_decode_type2(&data, &type2); 105178825Sdfr if (ret) 106178825Sdfr errx(1, "heim_ntlm_decode_type2"); 107178825Sdfr 108178825Sdfr gss_release_buffer(&min_stat, &output); 109178825Sdfr 110178825Sdfr type3.flags = type2.flags; 111178825Sdfr type3.username = rk_UNCONST(user); 112178825Sdfr type3.targetname = type2.targetname; 113178825Sdfr type3.ws = rk_UNCONST("workstation"); 114178825Sdfr 115178825Sdfr { 116178825Sdfr struct ntlm_buf key; 117178825Sdfr 118178825Sdfr heim_ntlm_nt_key(password, &key); 119178825Sdfr 120178825Sdfr heim_ntlm_calculate_ntlm1(key.data, key.length, 121233294Sstas type2.challenge, 122178825Sdfr &type3.ntlm); 123178825Sdfr 124178825Sdfr if (flags & NTLM_NEG_KEYEX) { 125178825Sdfr struct ntlm_buf sessionkey; 126178825Sdfr heim_ntlm_build_ntlm1_master(key.data, key.length, 127178825Sdfr &sessionkey, 128178825Sdfr &type3.sessionkey); 129178825Sdfr free(sessionkey.data); 130178825Sdfr } 131178825Sdfr free(key.data); 132178825Sdfr } 133178825Sdfr 134178825Sdfr ret = heim_ntlm_encode_type3(&type3, &data); 135178825Sdfr if (ret) 136178825Sdfr errx(1, "heim_ntlm_encode_type3"); 137178825Sdfr 138178825Sdfr input.length = data.length; 139178825Sdfr input.value = data.data; 140178825Sdfr 141178825Sdfr maj_stat = gss_accept_sec_context(&min_stat, 142178825Sdfr &ctx, 143178825Sdfr GSS_C_NO_CREDENTIAL, 144178825Sdfr &input, 145178825Sdfr GSS_C_NO_CHANNEL_BINDINGS, 146178825Sdfr &src_name, 147178825Sdfr NULL, 148178825Sdfr &output, 149178825Sdfr NULL, 150178825Sdfr NULL, 151178825Sdfr NULL); 152178825Sdfr free(input.value); 153178825Sdfr if (maj_stat != GSS_S_COMPLETE) 154178825Sdfr errx(1, "accept_sec_context v1 2 %s", 155178825Sdfr gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 156178825Sdfr 157178825Sdfr gss_release_buffer(&min_stat, &output); 158178825Sdfr gss_delete_sec_context(&min_stat, &ctx, NULL); 159178825Sdfr 160178825Sdfr if (src_name == GSS_C_NO_NAME) 161178825Sdfr errx(1, "no source name!"); 162178825Sdfr 163178825Sdfr gss_display_name(&min_stat, src_name, &output, NULL); 164178825Sdfr 165178825Sdfr printf("src_name: %.*s\n", (int)output.length, (char*)output.value); 166178825Sdfr 167178825Sdfr gss_release_name(&min_stat, &src_name); 168178825Sdfr gss_release_buffer(&min_stat, &output); 169178825Sdfr 170178825Sdfr return 0; 171178825Sdfr} 172178825Sdfr 173178825Sdfrstatic int 174178825Sdfrtest_libntlm_v2(int flags) 175178825Sdfr{ 176233294Sstas const char *user = "foo", 177178825Sdfr *domain = "mydomain", 178178825Sdfr *password = "digestpassword"; 179178825Sdfr OM_uint32 maj_stat, min_stat; 180178825Sdfr gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 181178825Sdfr gss_buffer_desc input, output; 182178825Sdfr struct ntlm_type1 type1; 183178825Sdfr struct ntlm_type2 type2; 184178825Sdfr struct ntlm_type3 type3; 185178825Sdfr struct ntlm_buf data; 186178825Sdfr krb5_error_code ret; 187233294Sstas 188178825Sdfr memset(&type1, 0, sizeof(type1)); 189178825Sdfr memset(&type2, 0, sizeof(type2)); 190178825Sdfr memset(&type3, 0, sizeof(type3)); 191178825Sdfr 192178825Sdfr type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_NTLM|flags; 193178825Sdfr type1.domain = strdup(domain); 194178825Sdfr type1.hostname = NULL; 195178825Sdfr type1.os[0] = 0; 196178825Sdfr type1.os[1] = 0; 197178825Sdfr 198178825Sdfr ret = heim_ntlm_encode_type1(&type1, &data); 199178825Sdfr if (ret) 200178825Sdfr errx(1, "heim_ntlm_encode_type1"); 201178825Sdfr 202178825Sdfr input.value = data.data; 203178825Sdfr input.length = data.length; 204178825Sdfr 205178825Sdfr output.length = 0; 206178825Sdfr output.value = NULL; 207178825Sdfr 208178825Sdfr maj_stat = gss_accept_sec_context(&min_stat, 209178825Sdfr &ctx, 210178825Sdfr GSS_C_NO_CREDENTIAL, 211178825Sdfr &input, 212178825Sdfr GSS_C_NO_CHANNEL_BINDINGS, 213178825Sdfr NULL, 214178825Sdfr NULL, 215178825Sdfr &output, 216178825Sdfr NULL, 217178825Sdfr NULL, 218178825Sdfr NULL); 219178825Sdfr free(data.data); 220178825Sdfr if (GSS_ERROR(maj_stat)) 221178825Sdfr errx(1, "accept_sec_context v2 %s", 222178825Sdfr gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 223178825Sdfr 224178825Sdfr if (output.length == 0) 225178825Sdfr errx(1, "output.length == 0"); 226178825Sdfr 227178825Sdfr data.data = output.value; 228178825Sdfr data.length = output.length; 229178825Sdfr 230178825Sdfr ret = heim_ntlm_decode_type2(&data, &type2); 231178825Sdfr if (ret) 232178825Sdfr errx(1, "heim_ntlm_decode_type2"); 233178825Sdfr 234178825Sdfr type3.flags = type2.flags; 235178825Sdfr type3.username = rk_UNCONST(user); 236178825Sdfr type3.targetname = type2.targetname; 237178825Sdfr type3.ws = rk_UNCONST("workstation"); 238178825Sdfr 239178825Sdfr { 240178825Sdfr struct ntlm_buf key; 241178825Sdfr unsigned char ntlmv2[16]; 242178825Sdfr 243178825Sdfr heim_ntlm_nt_key(password, &key); 244178825Sdfr 245178825Sdfr heim_ntlm_calculate_ntlm2(key.data, key.length, 246178825Sdfr user, 247178825Sdfr type2.targetname, 248233294Sstas type2.challenge, 249178825Sdfr &type2.targetinfo, 250178825Sdfr ntlmv2, 251178825Sdfr &type3.ntlm); 252178825Sdfr free(key.data); 253178825Sdfr 254178825Sdfr if (flags & NTLM_NEG_KEYEX) { 255178825Sdfr struct ntlm_buf sessionkey; 256178825Sdfr heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), 257178825Sdfr &sessionkey, 258178825Sdfr &type3.sessionkey); 259178825Sdfr free(sessionkey.data); 260178825Sdfr } 261178825Sdfr } 262178825Sdfr 263178825Sdfr ret = heim_ntlm_encode_type3(&type3, &data); 264178825Sdfr if (ret) 265178825Sdfr errx(1, "heim_ntlm_encode_type3"); 266178825Sdfr 267178825Sdfr input.length = data.length; 268178825Sdfr input.value = data.data; 269178825Sdfr 270178825Sdfr maj_stat = gss_accept_sec_context(&min_stat, 271178825Sdfr &ctx, 272178825Sdfr GSS_C_NO_CREDENTIAL, 273178825Sdfr &input, 274178825Sdfr GSS_C_NO_CHANNEL_BINDINGS, 275178825Sdfr NULL, 276178825Sdfr NULL, 277178825Sdfr &output, 278178825Sdfr NULL, 279178825Sdfr NULL, 280178825Sdfr NULL); 281178825Sdfr free(input.value); 282178825Sdfr if (maj_stat != GSS_S_COMPLETE) 283178825Sdfr errx(1, "accept_sec_context v2 2 %s", 284178825Sdfr gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 285178825Sdfr 286178825Sdfr gss_delete_sec_context(&min_stat, &ctx, NULL); 287178825Sdfr 288178825Sdfr return 0; 289178825Sdfr} 290178825Sdfr 291178825Sdfr 292178825Sdfr 293178825Sdfrstatic int version_flag = 0; 294178825Sdfrstatic int help_flag = 0; 295178825Sdfr 296178825Sdfrstatic struct getargs args[] = { 297178825Sdfr {"version", 0, arg_flag, &version_flag, "print version", NULL }, 298178825Sdfr {"help", 0, arg_flag, &help_flag, NULL, NULL } 299178825Sdfr}; 300178825Sdfr 301178825Sdfrstatic void 302178825Sdfrusage (int ret) 303178825Sdfr{ 304178825Sdfr arg_printusage (args, sizeof(args)/sizeof(*args), 305178825Sdfr NULL, ""); 306178825Sdfr exit (ret); 307178825Sdfr} 308178825Sdfr 309178825Sdfrint 310178825Sdfrmain(int argc, char **argv) 311178825Sdfr{ 312178825Sdfr int ret = 0, optind = 0; 313178825Sdfr 314178825Sdfr setprogname(argv[0]); 315178825Sdfr 316178825Sdfr if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) 317178825Sdfr usage(1); 318233294Sstas 319178825Sdfr if (help_flag) 320178825Sdfr usage (0); 321178825Sdfr 322178825Sdfr if(version_flag){ 323178825Sdfr print_version(NULL); 324178825Sdfr exit(0); 325178825Sdfr } 326178825Sdfr 327178825Sdfr argc -= optind; 328178825Sdfr argv += optind; 329178825Sdfr 330178825Sdfr ret += test_libntlm_v1(0); 331178825Sdfr ret += test_libntlm_v1(NTLM_NEG_KEYEX); 332178825Sdfr 333178825Sdfr ret += test_libntlm_v2(0); 334178825Sdfr ret += test_libntlm_v2(NTLM_NEG_KEYEX); 335178825Sdfr 336178825Sdfr return 0; 337178825Sdfr} 338