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