1 /* 2 * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 16 * 17 * 3. Neither the name of KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "config.h" 35 36 #include <roken.h> 37 #include <stdio.h> 38 #include <gssapi.h> 39 #include <err.h> 40 #include <getarg.h> 41 #include "test_common.h" 42 43 #include <krb5.h> 44 #include <heimntlm.h> 45 46 static int 47 test_libntlm_v1(int flags) 48 { 49 const char *user = "foo", 50 *domain = "mydomain", 51 *password = "digestpassword"; 52 OM_uint32 maj_stat, min_stat; 53 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 54 gss_buffer_desc input, output; 55 struct ntlm_type1 type1; 56 struct ntlm_type2 type2; 57 struct ntlm_type3 type3; 58 struct ntlm_buf data; 59 krb5_error_code ret; 60 gss_name_t src_name = GSS_C_NO_NAME; 61 62 memset(&type1, 0, sizeof(type1)); 63 memset(&type2, 0, sizeof(type2)); 64 memset(&type3, 0, sizeof(type3)); 65 66 type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags; 67 type1.domain = strdup(domain); 68 type1.hostname = NULL; 69 type1.os[0] = 0; 70 type1.os[1] = 0; 71 72 ret = heim_ntlm_encode_type1(&type1, &data); 73 if (ret) 74 errx(1, "heim_ntlm_encode_type1"); 75 76 input.value = data.data; 77 input.length = data.length; 78 79 output.length = 0; 80 output.value = NULL; 81 82 maj_stat = gss_accept_sec_context(&min_stat, 83 &ctx, 84 GSS_C_NO_CREDENTIAL, 85 &input, 86 GSS_C_NO_CHANNEL_BINDINGS, 87 NULL, 88 NULL, 89 &output, 90 NULL, 91 NULL, 92 NULL); 93 free(data.data); 94 if (GSS_ERROR(maj_stat)) 95 errx(1, "accept_sec_context v1: %s", 96 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 97 98 if (output.length == 0) 99 errx(1, "output.length == 0"); 100 101 data.data = output.value; 102 data.length = output.length; 103 104 ret = heim_ntlm_decode_type2(&data, &type2); 105 if (ret) 106 errx(1, "heim_ntlm_decode_type2"); 107 108 gss_release_buffer(&min_stat, &output); 109 110 type3.flags = type2.flags; 111 type3.username = rk_UNCONST(user); 112 type3.targetname = type2.targetname; 113 type3.ws = rk_UNCONST("workstation"); 114 115 { 116 struct ntlm_buf key; 117 118 heim_ntlm_nt_key(password, &key); 119 120 heim_ntlm_calculate_ntlm1(key.data, key.length, 121 type2.challenge, 122 &type3.ntlm); 123 124 if (flags & NTLM_NEG_KEYEX) { 125 struct ntlm_buf sessionkey; 126 heim_ntlm_build_ntlm1_master(key.data, key.length, 127 &sessionkey, 128 &type3.sessionkey); 129 free(sessionkey.data); 130 } 131 free(key.data); 132 } 133 134 ret = heim_ntlm_encode_type3(&type3, &data); 135 if (ret) 136 errx(1, "heim_ntlm_encode_type3"); 137 138 input.length = data.length; 139 input.value = data.data; 140 141 maj_stat = gss_accept_sec_context(&min_stat, 142 &ctx, 143 GSS_C_NO_CREDENTIAL, 144 &input, 145 GSS_C_NO_CHANNEL_BINDINGS, 146 &src_name, 147 NULL, 148 &output, 149 NULL, 150 NULL, 151 NULL); 152 free(input.value); 153 if (maj_stat != GSS_S_COMPLETE) 154 errx(1, "accept_sec_context v1 2 %s", 155 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 156 157 gss_release_buffer(&min_stat, &output); 158 gss_delete_sec_context(&min_stat, &ctx, NULL); 159 160 if (src_name == GSS_C_NO_NAME) 161 errx(1, "no source name!"); 162 163 gss_display_name(&min_stat, src_name, &output, NULL); 164 165 printf("src_name: %.*s\n", (int)output.length, (char*)output.value); 166 167 gss_release_name(&min_stat, &src_name); 168 gss_release_buffer(&min_stat, &output); 169 170 return 0; 171 } 172 173 static int 174 test_libntlm_v2(int flags) 175 { 176 const char *user = "foo", 177 *domain = "mydomain", 178 *password = "digestpassword"; 179 OM_uint32 maj_stat, min_stat; 180 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 181 gss_buffer_desc input, output; 182 struct ntlm_type1 type1; 183 struct ntlm_type2 type2; 184 struct ntlm_type3 type3; 185 struct ntlm_buf data; 186 krb5_error_code ret; 187 188 memset(&type1, 0, sizeof(type1)); 189 memset(&type2, 0, sizeof(type2)); 190 memset(&type3, 0, sizeof(type3)); 191 192 type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_NTLM|flags; 193 type1.domain = strdup(domain); 194 type1.hostname = NULL; 195 type1.os[0] = 0; 196 type1.os[1] = 0; 197 198 ret = heim_ntlm_encode_type1(&type1, &data); 199 if (ret) 200 errx(1, "heim_ntlm_encode_type1"); 201 202 input.value = data.data; 203 input.length = data.length; 204 205 output.length = 0; 206 output.value = NULL; 207 208 maj_stat = gss_accept_sec_context(&min_stat, 209 &ctx, 210 GSS_C_NO_CREDENTIAL, 211 &input, 212 GSS_C_NO_CHANNEL_BINDINGS, 213 NULL, 214 NULL, 215 &output, 216 NULL, 217 NULL, 218 NULL); 219 free(data.data); 220 if (GSS_ERROR(maj_stat)) 221 errx(1, "accept_sec_context v2 %s", 222 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 223 224 if (output.length == 0) 225 errx(1, "output.length == 0"); 226 227 data.data = output.value; 228 data.length = output.length; 229 230 ret = heim_ntlm_decode_type2(&data, &type2); 231 if (ret) 232 errx(1, "heim_ntlm_decode_type2"); 233 234 type3.flags = type2.flags; 235 type3.username = rk_UNCONST(user); 236 type3.targetname = type2.targetname; 237 type3.ws = rk_UNCONST("workstation"); 238 239 { 240 struct ntlm_buf key; 241 unsigned char ntlmv2[16]; 242 243 heim_ntlm_nt_key(password, &key); 244 245 heim_ntlm_calculate_ntlm2(key.data, key.length, 246 user, 247 type2.targetname, 248 type2.challenge, 249 &type2.targetinfo, 250 ntlmv2, 251 &type3.ntlm); 252 free(key.data); 253 254 if (flags & NTLM_NEG_KEYEX) { 255 struct ntlm_buf sessionkey; 256 heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), 257 &sessionkey, 258 &type3.sessionkey); 259 free(sessionkey.data); 260 } 261 } 262 263 ret = heim_ntlm_encode_type3(&type3, &data); 264 if (ret) 265 errx(1, "heim_ntlm_encode_type3"); 266 267 input.length = data.length; 268 input.value = data.data; 269 270 maj_stat = gss_accept_sec_context(&min_stat, 271 &ctx, 272 GSS_C_NO_CREDENTIAL, 273 &input, 274 GSS_C_NO_CHANNEL_BINDINGS, 275 NULL, 276 NULL, 277 &output, 278 NULL, 279 NULL, 280 NULL); 281 free(input.value); 282 if (maj_stat != GSS_S_COMPLETE) 283 errx(1, "accept_sec_context v2 2 %s", 284 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 285 286 gss_delete_sec_context(&min_stat, &ctx, NULL); 287 288 return 0; 289 } 290 291 292 293 static int version_flag = 0; 294 static int help_flag = 0; 295 296 static struct getargs args[] = { 297 {"version", 0, arg_flag, &version_flag, "print version", NULL }, 298 {"help", 0, arg_flag, &help_flag, NULL, NULL } 299 }; 300 301 static void 302 usage (int ret) 303 { 304 arg_printusage (args, sizeof(args)/sizeof(*args), 305 NULL, ""); 306 exit (ret); 307 } 308 309 int 310 main(int argc, char **argv) 311 { 312 int ret = 0, optind = 0; 313 314 setprogname(argv[0]); 315 316 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) 317 usage(1); 318 319 if (help_flag) 320 usage (0); 321 322 if(version_flag){ 323 print_version(NULL); 324 exit(0); 325 } 326 327 argc -= optind; 328 argv += optind; 329 330 ret += test_libntlm_v1(0); 331 ret += test_libntlm_v1(NTLM_NEG_KEYEX); 332 333 ret += test_libntlm_v2(0); 334 ret += test_libntlm_v2(NTLM_NEG_KEYEX); 335 336 return 0; 337 } 338