1/* 2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. 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 the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "ntlm.h" 37 38gss_name_t 39_gss_ntlm_create_name(OM_uint32 *minor_status, 40 const char *user, const char *domain, int flags) 41{ 42 ntlm_name n; 43 n = calloc(1, sizeof(*n)); 44 if (n == NULL) { 45 *minor_status = ENOMEM; 46 return NULL; 47 } 48 49 n->user = strdup(user); 50 n->domain = strdup(domain); 51 n->flags = flags; 52 53 if (n->user == NULL || n->domain == NULL) { 54 free(n->user); 55 free(n->domain); 56 free(n); 57 *minor_status = ENOMEM; 58 return NULL; 59 } 60 61 return (gss_name_t)n; 62} 63 64static OM_uint32 65anon_name(OM_uint32 *minor_status, 66 gss_const_OID mech, 67 const gss_buffer_t input_name_buffer, 68 gss_const_OID input_name_type, 69 gss_name_t *output_name) 70{ 71 *output_name = _gss_ntlm_create_name(minor_status, "", "", NTLM_ANON_NAME); 72 if (*output_name == NULL) 73 return GSS_S_FAILURE; 74 return GSS_S_COMPLETE; 75} 76 77static OM_uint32 78hostbased_name(OM_uint32 *minor_status, 79 gss_const_OID mech, 80 const gss_buffer_t input_name_buffer, 81 gss_const_OID input_name_type, 82 gss_name_t *output_name) 83{ 84 char *name, *p; 85 86 name = malloc(input_name_buffer->length + 1); 87 if (name == NULL) { 88 *minor_status = ENOMEM; 89 return GSS_S_FAILURE; 90 } 91 memcpy(name, input_name_buffer->value, input_name_buffer->length); 92 name[input_name_buffer->length] = '\0'; 93 94 /* find "domain" part of the name and uppercase it */ 95 p = strchr(name, '@'); 96 if (p) { 97 p[0] = '\0'; 98 p++; 99 } else { 100 p = ""; 101 } 102 103 *output_name = _gss_ntlm_create_name(minor_status, name, p, 0); 104 free(name); 105 if (*output_name == NULL) 106 return GSS_S_FAILURE; 107 108 return GSS_S_COMPLETE; 109} 110 111static OM_uint32 112parse_name(OM_uint32 *minor_status, 113 gss_const_OID mech, 114 int domain_required, 115 const gss_buffer_t input_name_buffer, 116 gss_const_OID input_name_type, 117 gss_name_t *output_name) 118{ 119 char *name, *p, *user, *domain; 120 121 if (memchr(input_name_buffer->value, '@', input_name_buffer->length) != NULL) 122 return hostbased_name(minor_status, mech, input_name_buffer, 123 input_name_type, output_name); 124 125 name = malloc(input_name_buffer->length + 1); 126 if (name == NULL) { 127 *minor_status = ENOMEM; 128 return GSS_S_FAILURE; 129 } 130 memcpy(name, input_name_buffer->value, input_name_buffer->length); 131 name[input_name_buffer->length] = '\0'; 132 133 /* find "domain" part of the name and uppercase it */ 134 p = strchr(name, '\\'); 135 if (p) { 136 p[0] = '\0'; 137 user = p + 1; 138 domain = name; 139 strupr(domain); 140 } else if (!domain_required) { 141 user = name; 142 domain = ""; /* no domain */ 143 } else { 144 free(name); 145 *minor_status = HNTLM_ERR_MISSING_NAME_SEPARATOR; 146 return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_BAD_NAME, 147 HNTLM_ERR_MISSING_NAME_SEPARATOR, 148 "domain requested but missing name"); 149 } 150 151 *output_name = _gss_ntlm_create_name(minor_status, user, domain, 0); 152 free(name); 153 if (*output_name == NULL) 154 return GSS_S_FAILURE; 155 156 return GSS_S_COMPLETE; 157} 158 159static OM_uint32 160user_name(OM_uint32 *minor_status, 161 gss_const_OID mech, 162 const gss_buffer_t input_name_buffer, 163 gss_const_OID input_name_type, 164 gss_name_t *output_name) 165{ 166 return parse_name(minor_status, mech, 0, input_name_buffer, input_name_type, output_name); 167} 168 169static OM_uint32 170parse_ntlm_name(OM_uint32 *minor_status, 171 gss_const_OID mech, 172 const gss_buffer_t input_name_buffer, 173 gss_const_OID input_name_type, 174 gss_name_t *output_name) 175{ 176 return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name); 177} 178 179static OM_uint32 180export_name(OM_uint32 *minor_status, 181 gss_const_OID mech, 182 const gss_buffer_t input_name_buffer, 183 gss_const_OID input_name_type, 184 gss_name_t *output_name) 185{ 186 return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name); 187} 188 189static struct _gss_name_type ntlm_names[] = { 190 { GSS_C_NT_ANONYMOUS, anon_name}, 191 { GSS_C_NT_HOSTBASED_SERVICE, hostbased_name}, 192 { GSS_C_NT_USER_NAME, user_name }, 193 { GSS_C_NT_NTLM, parse_ntlm_name }, 194 { GSS_C_NT_EXPORT_NAME, export_name }, 195 { NULL } 196}; 197 198 199OM_uint32 _gss_ntlm_import_name 200 (OM_uint32 * minor_status, 201 const gss_buffer_t input_name_buffer, 202 gss_const_OID input_name_type, 203 gss_name_t * output_name 204 ) 205{ 206 return _gss_mech_import_name(minor_status, GSS_NTLM_MECHANISM, 207 ntlm_names, input_name_buffer, 208 input_name_type, output_name); 209} 210 211OM_uint32 _gss_ntlm_inquire_names_for_mech ( 212 OM_uint32 * minor_status, 213 gss_const_OID mechanism, 214 gss_OID_set * name_types 215 ) 216{ 217 return _gss_mech_inquire_names_for_mech(minor_status, ntlm_names, 218 name_types); 219} 220