1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/krb5/os/ccdefname.c - Return default credential cache name */ 3 /* 4 * Copyright 1990, 2007 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #define NEED_WINDOWS 28 #include "k5-int.h" 29 #include "../ccache/cc-int.h" 30 #include "os-proto.h" 31 #include <stdio.h> 32 33 #if defined(_WIN32) 34 static int get_from_registry_indirect(char *name_buf, int name_size) 35 { 36 /* If the RegKRB5CCNAME variable is set, it will point to 37 * the registry key that has the name of the cache to use. 38 * The Gradient PC-DCE sets the registry key 39 * [HKEY_CURRENT_USER\Software\Gradient\DCE\Default\KRB5CCNAME] 40 * to point at the cache file name (including the FILE: prefix). 41 * By indirecting with the RegKRB5CCNAME entry in kerberos.ini, 42 * we can accommodate other versions that might set a registry 43 * variable. 44 */ 45 char newkey[256]; 46 47 LONG name_buf_size; 48 HKEY hkey; 49 int found = 0; 50 char *cp; 51 52 newkey[0] = 0; 53 GetPrivateProfileString(INI_FILES, "RegKRB5CCNAME", "", 54 newkey, sizeof(newkey), KERBEROS_INI); 55 if (!newkey[0]) 56 return 0; 57 58 newkey[sizeof(newkey)-1] = 0; 59 cp = strrchr(newkey,'\\'); 60 if (cp) { 61 *cp = '\0'; /* split the string */ 62 cp++; 63 } else 64 cp = ""; 65 66 if (RegOpenKeyEx(HKEY_CURRENT_USER, newkey, 0, 67 KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) 68 return 0; 69 70 name_buf_size = name_size; 71 if (RegQueryValueEx(hkey, cp, 0, 0, 72 name_buf, &name_buf_size) != ERROR_SUCCESS) 73 { 74 RegCloseKey(hkey); 75 return 0; 76 } 77 78 RegCloseKey(hkey); 79 return 1; 80 } 81 82 static const char *key_path = "Software\\MIT\\Kerberos5"; 83 static const char *value_name = "ccname"; 84 static int 85 set_to_registry( 86 HKEY hBaseKey, 87 const char *name_buf 88 ) 89 { 90 HRESULT result; 91 HKEY hKey; 92 93 if ((result = RegCreateKeyEx(hBaseKey, key_path, 0, NULL, 94 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, 95 &hKey, NULL)) != ERROR_SUCCESS) { 96 return 0; 97 } 98 if (RegSetValueEx(hKey, value_name, 0, REG_SZ, name_buf, 99 strlen(name_buf)+1) != ERROR_SUCCESS) { 100 RegCloseKey(hKey); 101 return 0; 102 } 103 RegCloseKey(hKey); 104 return 1; 105 } 106 107 108 /* 109 * get_from_registry 110 * 111 * This will find the ccname in the registry. Returns 0 on error, non-zero 112 * on success. 113 */ 114 115 static int 116 get_from_registry( 117 HKEY hBaseKey, 118 char *name_buf, 119 int name_size 120 ) 121 { 122 HKEY hKey; 123 DWORD name_buf_size = (DWORD)name_size; 124 125 if (RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, 126 &hKey) != ERROR_SUCCESS) 127 return 0; 128 if (RegQueryValueEx(hKey, value_name, 0, 0, 129 name_buf, &name_buf_size) != ERROR_SUCCESS) 130 { 131 RegCloseKey(hKey); 132 return 0; 133 } 134 RegCloseKey(hKey); 135 return 1; 136 } 137 138 #define APPEND_KRB5CC "\\krb5cc" 139 140 static int 141 try_dir( 142 char* dir, 143 char* buffer, 144 int buf_len 145 ) 146 { 147 struct _stat s; 148 if (!dir) 149 return 0; 150 if (_stat(dir, &s)) 151 return 0; 152 if (!(s.st_mode & _S_IFDIR)) 153 return 0; 154 if (buffer != dir) { 155 strncpy(buffer, dir, buf_len); 156 buffer[buf_len-1]='\0'; 157 } 158 strncat(buffer, APPEND_KRB5CC, buf_len-strlen(buffer)); 159 buffer[buf_len-1] = '\0'; 160 return 1; 161 } 162 163 static krb5_error_code 164 get_from_os_buffer(char *name_buf, unsigned int name_size) 165 { 166 char *prefix = krb5_cc_dfl_ops->prefix; 167 unsigned int size; 168 char *p; 169 DWORD gle; 170 171 SetLastError(0); 172 GetEnvironmentVariable(KRB5_ENV_CCNAME, name_buf, name_size); 173 gle = GetLastError(); 174 if (gle == 0) 175 return 0; 176 else if (gle != ERROR_ENVVAR_NOT_FOUND) 177 return ENOMEM; 178 179 if (get_from_registry(HKEY_CURRENT_USER, 180 name_buf, name_size) != 0) 181 return 0; 182 183 if (get_from_registry(HKEY_LOCAL_MACHINE, 184 name_buf, name_size) != 0) 185 return 0; 186 187 if (get_from_registry_indirect(name_buf, name_size) != 0) 188 return 0; 189 190 strncpy(name_buf, prefix, name_size - 1); 191 name_buf[name_size - 1] = 0; 192 size = name_size - strlen(prefix); 193 if (size > 0) 194 strcat(name_buf, ":"); 195 size--; 196 p = name_buf + name_size - size; 197 if (!strcmp(prefix, "API")) { 198 strncpy(p, "krb5cc", size); 199 } else if (!strcmp(prefix, "FILE") || !strcmp(prefix, "STDIO")) { 200 if (!try_dir(getenv("TEMP"), p, size) && 201 !try_dir(getenv("TMP"), p, size)) 202 { 203 unsigned int len = GetWindowsDirectory(p, size); 204 name_buf[name_size - 1] = 0; 205 if (len < size - sizeof(APPEND_KRB5CC)) 206 strcat(p, APPEND_KRB5CC); 207 } 208 } else { 209 strncpy(p, "default_cache_name", size); 210 } 211 name_buf[name_size - 1] = 0; 212 return 0; 213 } 214 215 static void 216 get_from_os(krb5_context context) 217 { 218 krb5_error_code err; 219 char buf[1024]; 220 221 if (get_from_os_buffer(buf, sizeof(buf)) == 0) 222 context->os_context.default_ccname = strdup(buf); 223 } 224 225 #else /* not _WIN32 */ 226 227 static void 228 get_from_os(krb5_context context) 229 { 230 (void)k5_expand_path_tokens(context, DEFCCNAME, 231 &context->os_context.default_ccname); 232 } 233 234 #endif /* not _WIN32 */ 235 236 #if defined(_WIN32) 237 static void 238 set_for_os(const char *name) 239 { 240 set_to_registry(HKEY_CURRENT_USER, name); 241 } 242 #else 243 static void 244 set_for_os(const char *name) 245 { 246 /* No implementation at present. */ 247 } 248 #endif 249 250 /* 251 * Set the default ccache name for all processes for the current user 252 * (and the current context) 253 */ 254 krb5_error_code KRB5_CALLCONV 255 krb5int_cc_user_set_default_name(krb5_context context, const char *name) 256 { 257 krb5_error_code err; 258 259 err = krb5_cc_set_default_name(context, name); 260 if (err) 261 return err; 262 set_for_os(name); 263 return 0; 264 } 265 266 krb5_error_code KRB5_CALLCONV 267 krb5_cc_set_default_name(krb5_context context, const char *name) 268 { 269 krb5_os_context os_ctx; 270 char *new_ccname = NULL; 271 272 if (!context || context->magic != KV5M_CONTEXT) 273 return KV5M_CONTEXT; 274 275 if (name != NULL) { 276 new_ccname = strdup(name); 277 if (new_ccname == NULL) 278 return ENOMEM; 279 } 280 281 /* Free the old ccname and store the new one. */ 282 os_ctx = &context->os_context; 283 free(os_ctx->default_ccname); 284 os_ctx->default_ccname = new_ccname; 285 return 0; 286 } 287 288 289 const char * KRB5_CALLCONV 290 krb5_cc_default_name(krb5_context context) 291 { 292 krb5_os_context os_ctx; 293 char *profstr, *envstr; 294 295 if (!context || context->magic != KV5M_CONTEXT) 296 return NULL; 297 298 os_ctx = &context->os_context; 299 if (os_ctx->default_ccname != NULL) 300 return os_ctx->default_ccname; 301 302 /* Try the environment variable first. */ 303 envstr = secure_getenv(KRB5_ENV_CCNAME); 304 if (envstr != NULL) { 305 os_ctx->default_ccname = strdup(envstr); 306 return os_ctx->default_ccname; 307 } 308 309 if (profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, 310 KRB5_CONF_DEFAULT_CCACHE_NAME, NULL, NULL, 311 &profstr) == 0 && profstr != NULL) { 312 (void)k5_expand_path_tokens(context, profstr, &os_ctx->default_ccname); 313 profile_release_string(profstr); 314 return os_ctx->default_ccname; 315 } 316 317 /* Fall back on the default ccache name for the OS. */ 318 get_from_os(context); 319 return os_ctx->default_ccname; 320 } 321