xref: /freebsd/crypto/krb5/src/lib/krb5/os/init_os_ctx.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/krb5/os/init_os_ctx.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 1994, 2007, 2008, 2009 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert #define NEED_WINDOWS
28*7f2fe78bSCy Schubert 
29*7f2fe78bSCy Schubert #include "k5-int.h"
30*7f2fe78bSCy Schubert #include "os-proto.h"
31*7f2fe78bSCy Schubert #include "../krb/int-proto.h"
32*7f2fe78bSCy Schubert #include "prof_int.h"        /* XXX for profile_copy, not public yet */
33*7f2fe78bSCy Schubert 
34*7f2fe78bSCy Schubert #if defined(_WIN32)
35*7f2fe78bSCy Schubert #include <winsock.h>
36*7f2fe78bSCy Schubert #include <Shlobj.h>
37*7f2fe78bSCy Schubert 
38*7f2fe78bSCy Schubert static krb5_error_code
get_from_windows_dir(char ** pname)39*7f2fe78bSCy Schubert get_from_windows_dir(
40*7f2fe78bSCy Schubert     char **pname
41*7f2fe78bSCy Schubert )
42*7f2fe78bSCy Schubert {
43*7f2fe78bSCy Schubert     UINT size = GetWindowsDirectory(0, 0);
44*7f2fe78bSCy Schubert     *pname = malloc(size + strlen(DEFAULT_PROFILE_FILENAME) + 2);
45*7f2fe78bSCy Schubert     if (*pname) {
46*7f2fe78bSCy Schubert         GetWindowsDirectory(*pname, size);
47*7f2fe78bSCy Schubert         strcat(*pname, "\\");
48*7f2fe78bSCy Schubert         strcat(*pname, DEFAULT_PROFILE_FILENAME);
49*7f2fe78bSCy Schubert         return 0;
50*7f2fe78bSCy Schubert     } else {
51*7f2fe78bSCy Schubert         return KRB5_CONFIG_CANTOPEN;
52*7f2fe78bSCy Schubert     }
53*7f2fe78bSCy Schubert }
54*7f2fe78bSCy Schubert 
55*7f2fe78bSCy Schubert static krb5_error_code
get_from_module_dir(char ** pname)56*7f2fe78bSCy Schubert get_from_module_dir(
57*7f2fe78bSCy Schubert     char **pname
58*7f2fe78bSCy Schubert )
59*7f2fe78bSCy Schubert {
60*7f2fe78bSCy Schubert     const DWORD size = 1024; /* fixed buffer */
61*7f2fe78bSCy Schubert     int found = 0;
62*7f2fe78bSCy Schubert     char *p = NULL;
63*7f2fe78bSCy Schubert     char *name = NULL;
64*7f2fe78bSCy Schubert     struct _stat s;
65*7f2fe78bSCy Schubert 
66*7f2fe78bSCy Schubert     *pname = 0;
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert     name = malloc(size);
69*7f2fe78bSCy Schubert     if (!name)
70*7f2fe78bSCy Schubert         return ENOMEM;
71*7f2fe78bSCy Schubert 
72*7f2fe78bSCy Schubert #ifdef _WIN64
73*7f2fe78bSCy Schubert     if (!GetModuleFileName(GetModuleHandle("krb5_64"), name, size))
74*7f2fe78bSCy Schubert #else
75*7f2fe78bSCy Schubert     if (!GetModuleFileName(GetModuleHandle("krb5_32"), name, size))
76*7f2fe78bSCy Schubert #endif
77*7f2fe78bSCy Schubert         goto cleanup;
78*7f2fe78bSCy Schubert 
79*7f2fe78bSCy Schubert     p = name + strlen(name);
80*7f2fe78bSCy Schubert     while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
81*7f2fe78bSCy Schubert     if (p < name)
82*7f2fe78bSCy Schubert         goto cleanup;
83*7f2fe78bSCy Schubert     p++;
84*7f2fe78bSCy Schubert     strncpy(p, DEFAULT_PROFILE_FILENAME, size - (p - name));
85*7f2fe78bSCy Schubert     name[size - 1] = 0;
86*7f2fe78bSCy Schubert     found = !_stat(name, &s);
87*7f2fe78bSCy Schubert 
88*7f2fe78bSCy Schubert cleanup:
89*7f2fe78bSCy Schubert     if (found)
90*7f2fe78bSCy Schubert         *pname = name;
91*7f2fe78bSCy Schubert     else
92*7f2fe78bSCy Schubert         free(name);
93*7f2fe78bSCy Schubert     return 0;
94*7f2fe78bSCy Schubert }
95*7f2fe78bSCy Schubert 
96*7f2fe78bSCy Schubert /*
97*7f2fe78bSCy Schubert  * get_from_registry
98*7f2fe78bSCy Schubert  *
99*7f2fe78bSCy Schubert  * This will find a profile in the registry.  *pbuffer != 0 if we
100*7f2fe78bSCy Schubert  * found something.  Make sure to free(*pbuffer) when done.  It will
101*7f2fe78bSCy Schubert  * return an error code if there is an error the user should know
102*7f2fe78bSCy Schubert  * about.  We maintain the invariant: return value != 0 =>
103*7f2fe78bSCy Schubert  * *pbuffer == 0.
104*7f2fe78bSCy Schubert  */
105*7f2fe78bSCy Schubert static krb5_error_code
get_from_registry(char ** pbuffer,HKEY hBaseKey)106*7f2fe78bSCy Schubert get_from_registry(
107*7f2fe78bSCy Schubert     char** pbuffer,
108*7f2fe78bSCy Schubert     HKEY hBaseKey
109*7f2fe78bSCy Schubert )
110*7f2fe78bSCy Schubert {
111*7f2fe78bSCy Schubert     HKEY hKey = 0;
112*7f2fe78bSCy Schubert     LONG rc = 0;
113*7f2fe78bSCy Schubert     DWORD size = 0;
114*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
115*7f2fe78bSCy Schubert     const char *key_path = "Software\\MIT\\Kerberos5";
116*7f2fe78bSCy Schubert     const char *value_name = "config";
117*7f2fe78bSCy Schubert 
118*7f2fe78bSCy Schubert     assert(pbuffer != NULL);
119*7f2fe78bSCy Schubert     *pbuffer = NULL;
120*7f2fe78bSCy Schubert 
121*7f2fe78bSCy Schubert     if ((rc = RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE,
122*7f2fe78bSCy Schubert                            &hKey)) != ERROR_SUCCESS) {
123*7f2fe78bSCy Schubert         /* not a real error */
124*7f2fe78bSCy Schubert         goto cleanup;
125*7f2fe78bSCy Schubert     }
126*7f2fe78bSCy Schubert     rc = RegQueryValueEx(hKey, value_name, 0, 0, 0, &size);
127*7f2fe78bSCy Schubert     if ((rc != ERROR_SUCCESS) &&  (rc != ERROR_MORE_DATA)) {
128*7f2fe78bSCy Schubert         /* not a real error */
129*7f2fe78bSCy Schubert         goto cleanup;
130*7f2fe78bSCy Schubert     }
131*7f2fe78bSCy Schubert     *pbuffer = malloc(size);
132*7f2fe78bSCy Schubert     if (!*pbuffer) {
133*7f2fe78bSCy Schubert         retval = ENOMEM;
134*7f2fe78bSCy Schubert         goto cleanup;
135*7f2fe78bSCy Schubert     }
136*7f2fe78bSCy Schubert     if ((rc = RegQueryValueEx(hKey, value_name, 0, 0, *pbuffer, &size)) !=
137*7f2fe78bSCy Schubert         ERROR_SUCCESS) {
138*7f2fe78bSCy Schubert         /*
139*7f2fe78bSCy Schubert          * Let's not call it a real error in case it disappears, but
140*7f2fe78bSCy Schubert          * we need to free so that we say we did not find anything.
141*7f2fe78bSCy Schubert          */
142*7f2fe78bSCy Schubert         free(*pbuffer);
143*7f2fe78bSCy Schubert         *pbuffer = 0;
144*7f2fe78bSCy Schubert         goto cleanup;
145*7f2fe78bSCy Schubert     }
146*7f2fe78bSCy Schubert cleanup:
147*7f2fe78bSCy Schubert     if (hKey)
148*7f2fe78bSCy Schubert         RegCloseKey(hKey);
149*7f2fe78bSCy Schubert     if (retval && *pbuffer) {
150*7f2fe78bSCy Schubert         free(*pbuffer);
151*7f2fe78bSCy Schubert         /* Let's say we did not find anything: */
152*7f2fe78bSCy Schubert         *pbuffer = 0;
153*7f2fe78bSCy Schubert     }
154*7f2fe78bSCy Schubert     return retval;
155*7f2fe78bSCy Schubert }
156*7f2fe78bSCy Schubert 
157*7f2fe78bSCy Schubert /*
158*7f2fe78bSCy Schubert  * get_from_known_folder
159*7f2fe78bSCy Schubert  *
160*7f2fe78bSCy Schubert  * This will find a profile in the specified known folder (e.g. CSIDL_APPDATA).
161*7f2fe78bSCy Schubert  * *pbuffer != 0 if we found something.  Make sure to free(*pbuffer) when done.
162*7f2fe78bSCy Schubert  * It will return an error code if there is an error the user should know
163*7f2fe78bSCy Schubert  * about.  We maintain the invariant: return value != 0 =>
164*7f2fe78bSCy Schubert  * *pbuffer == 0.
165*7f2fe78bSCy Schubert  */
166*7f2fe78bSCy Schubert static krb5_error_code
get_from_known_folder(int folderId,char ** pbuffer)167*7f2fe78bSCy Schubert get_from_known_folder(
168*7f2fe78bSCy Schubert     int folderId,
169*7f2fe78bSCy Schubert     char** pbuffer
170*7f2fe78bSCy Schubert )
171*7f2fe78bSCy Schubert {
172*7f2fe78bSCy Schubert     char szPath[MAX_PATH];
173*7f2fe78bSCy Schubert     const char * software_suffix = "\\MIT\\Kerberos5";
174*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
175*7f2fe78bSCy Schubert     size_t size;
176*7f2fe78bSCy Schubert     struct _stat s;
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert     assert(pbuffer);
179*7f2fe78bSCy Schubert     *pbuffer = NULL;
180*7f2fe78bSCy Schubert 
181*7f2fe78bSCy Schubert     if (SUCCEEDED(SHGetFolderPath(NULL,
182*7f2fe78bSCy Schubert                                   folderId /*|CSIDL_FLAG_CREATE*/,
183*7f2fe78bSCy Schubert                                   NULL,
184*7f2fe78bSCy Schubert                                   SHGFP_TYPE_CURRENT,
185*7f2fe78bSCy Schubert                                   szPath))) {
186*7f2fe78bSCy Schubert         size = strlen(software_suffix) + strlen("\\" DEFAULT_PROFILE_FILENAME) + strlen(szPath);
187*7f2fe78bSCy Schubert         if ((size + 1) >= sizeof(szPath)) {
188*7f2fe78bSCy Schubert             goto cleanup;
189*7f2fe78bSCy Schubert         }
190*7f2fe78bSCy Schubert         strlcat(szPath, software_suffix, sizeof(szPath));
191*7f2fe78bSCy Schubert         strlcat(szPath, "\\", sizeof(szPath));
192*7f2fe78bSCy Schubert         strlcat(szPath, DEFAULT_PROFILE_FILENAME, sizeof(szPath));
193*7f2fe78bSCy Schubert     } else {
194*7f2fe78bSCy Schubert         /* Might want to deliberate a bit better why we failed.
195*7f2fe78bSCy Schubert             But for the time being this is not an error */
196*7f2fe78bSCy Schubert         goto cleanup;
197*7f2fe78bSCy Schubert     }
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert     if (_stat(szPath, &s)) {
200*7f2fe78bSCy Schubert         goto cleanup;
201*7f2fe78bSCy Schubert     }
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert     *pbuffer = malloc(size + 1);
204*7f2fe78bSCy Schubert     if (!*pbuffer) {
205*7f2fe78bSCy Schubert         retval = ENOMEM;
206*7f2fe78bSCy Schubert         goto cleanup;
207*7f2fe78bSCy Schubert     }
208*7f2fe78bSCy Schubert 
209*7f2fe78bSCy Schubert     strlcpy (*pbuffer, szPath, size + 1);
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert cleanup:
212*7f2fe78bSCy Schubert     if (retval && *pbuffer) {
213*7f2fe78bSCy Schubert         free(*pbuffer);
214*7f2fe78bSCy Schubert         /* Let's say we did not find anything: */
215*7f2fe78bSCy Schubert         *pbuffer = 0;
216*7f2fe78bSCy Schubert     }
217*7f2fe78bSCy Schubert     return retval;
218*7f2fe78bSCy Schubert }
219*7f2fe78bSCy Schubert 
220*7f2fe78bSCy Schubert #endif /* _WIN32 */
221*7f2fe78bSCy Schubert 
222*7f2fe78bSCy Schubert static void
free_filespecs(profile_filespec_t * files)223*7f2fe78bSCy Schubert free_filespecs(profile_filespec_t *files)
224*7f2fe78bSCy Schubert {
225*7f2fe78bSCy Schubert     char **cp;
226*7f2fe78bSCy Schubert 
227*7f2fe78bSCy Schubert     if (files == 0)
228*7f2fe78bSCy Schubert         return;
229*7f2fe78bSCy Schubert 
230*7f2fe78bSCy Schubert     for (cp = files; *cp; cp++)
231*7f2fe78bSCy Schubert         free(*cp);
232*7f2fe78bSCy Schubert     free(files);
233*7f2fe78bSCy Schubert }
234*7f2fe78bSCy Schubert 
235*7f2fe78bSCy Schubert /* This function is needed by KfM's KerberosPreferences API
236*7f2fe78bSCy Schubert  * because it needs to be able to specify "secure" */
237*7f2fe78bSCy Schubert static krb5_error_code
os_get_default_config_files(profile_filespec_t ** pfiles,krb5_boolean secure)238*7f2fe78bSCy Schubert os_get_default_config_files(profile_filespec_t **pfiles, krb5_boolean secure)
239*7f2fe78bSCy Schubert {
240*7f2fe78bSCy Schubert     profile_filespec_t* files;
241*7f2fe78bSCy Schubert #if defined(_WIN32)
242*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
243*7f2fe78bSCy Schubert     char *name = 0;
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert     if (!secure) {
246*7f2fe78bSCy Schubert         char *env = secure_getenv("KRB5_CONFIG");
247*7f2fe78bSCy Schubert         if (env) {
248*7f2fe78bSCy Schubert             name = strdup(env);
249*7f2fe78bSCy Schubert             if (!name) return ENOMEM;
250*7f2fe78bSCy Schubert         }
251*7f2fe78bSCy Schubert     }
252*7f2fe78bSCy Schubert     if (!name && !secure) {
253*7f2fe78bSCy Schubert         /* HKCU */
254*7f2fe78bSCy Schubert         retval = get_from_registry(&name, HKEY_CURRENT_USER);
255*7f2fe78bSCy Schubert         if (retval) return retval;
256*7f2fe78bSCy Schubert     }
257*7f2fe78bSCy Schubert     if (!name) {
258*7f2fe78bSCy Schubert         /* HKLM */
259*7f2fe78bSCy Schubert         retval = get_from_registry(&name, HKEY_LOCAL_MACHINE);
260*7f2fe78bSCy Schubert         if (retval) return retval;
261*7f2fe78bSCy Schubert     }
262*7f2fe78bSCy Schubert 
263*7f2fe78bSCy Schubert     if (!name && !secure) {
264*7f2fe78bSCy Schubert         retval = get_from_known_folder(CSIDL_APPDATA, &name);
265*7f2fe78bSCy Schubert         if (retval) return retval;
266*7f2fe78bSCy Schubert     }
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert     if (!name) {
269*7f2fe78bSCy Schubert         retval = get_from_known_folder(CSIDL_COMMON_APPDATA, &name);
270*7f2fe78bSCy Schubert         if (retval) return retval;
271*7f2fe78bSCy Schubert     }
272*7f2fe78bSCy Schubert 
273*7f2fe78bSCy Schubert     if (!name && !secure) {
274*7f2fe78bSCy Schubert         /* module dir */
275*7f2fe78bSCy Schubert         retval = get_from_module_dir(&name);
276*7f2fe78bSCy Schubert         if (retval) return retval;
277*7f2fe78bSCy Schubert     }
278*7f2fe78bSCy Schubert     if (!name) {
279*7f2fe78bSCy Schubert         /* windows dir */
280*7f2fe78bSCy Schubert         retval = get_from_windows_dir(&name);
281*7f2fe78bSCy Schubert     }
282*7f2fe78bSCy Schubert     if (retval)
283*7f2fe78bSCy Schubert         return retval;
284*7f2fe78bSCy Schubert     if (!name)
285*7f2fe78bSCy Schubert         return KRB5_CONFIG_CANTOPEN; /* should never happen */
286*7f2fe78bSCy Schubert 
287*7f2fe78bSCy Schubert     files = malloc(2 * sizeof(char *));
288*7f2fe78bSCy Schubert     if (!files)
289*7f2fe78bSCy Schubert         return ENOMEM;
290*7f2fe78bSCy Schubert     files[0] = name;
291*7f2fe78bSCy Schubert     files[1] = 0;
292*7f2fe78bSCy Schubert #else /* !_WIN32 */
293*7f2fe78bSCy Schubert     char* filepath = 0;
294*7f2fe78bSCy Schubert     int n_entries, i;
295*7f2fe78bSCy Schubert     unsigned int ent_len;
296*7f2fe78bSCy Schubert     const char *s, *t;
297*7f2fe78bSCy Schubert 
298*7f2fe78bSCy Schubert     if (secure) {
299*7f2fe78bSCy Schubert         filepath = DEFAULT_SECURE_PROFILE_PATH;
300*7f2fe78bSCy Schubert     } else {
301*7f2fe78bSCy Schubert         filepath = secure_getenv("KRB5_CONFIG");
302*7f2fe78bSCy Schubert         if (!filepath) filepath = DEFAULT_PROFILE_PATH;
303*7f2fe78bSCy Schubert     }
304*7f2fe78bSCy Schubert 
305*7f2fe78bSCy Schubert     /* count the distinct filename components */
306*7f2fe78bSCy Schubert     for(s = filepath, n_entries = 1; *s; s++) {
307*7f2fe78bSCy Schubert         if (*s == ':')
308*7f2fe78bSCy Schubert             n_entries++;
309*7f2fe78bSCy Schubert     }
310*7f2fe78bSCy Schubert 
311*7f2fe78bSCy Schubert     /* the array is NULL terminated */
312*7f2fe78bSCy Schubert     files = (char**) malloc((n_entries+1) * sizeof(char*));
313*7f2fe78bSCy Schubert     if (files == 0)
314*7f2fe78bSCy Schubert         return ENOMEM;
315*7f2fe78bSCy Schubert 
316*7f2fe78bSCy Schubert     /* measure, copy, and skip each one */
317*7f2fe78bSCy Schubert     for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
318*7f2fe78bSCy Schubert         ent_len = t-s;
319*7f2fe78bSCy Schubert         files[i] = (char*) malloc(ent_len + 1);
320*7f2fe78bSCy Schubert         if (files[i] == 0) {
321*7f2fe78bSCy Schubert             /* if malloc fails, free the ones that worked */
322*7f2fe78bSCy Schubert             while(--i >= 0) free(files[i]);
323*7f2fe78bSCy Schubert             free(files);
324*7f2fe78bSCy Schubert             return ENOMEM;
325*7f2fe78bSCy Schubert         }
326*7f2fe78bSCy Schubert         strncpy(files[i], s, ent_len);
327*7f2fe78bSCy Schubert         files[i][ent_len] = 0;
328*7f2fe78bSCy Schubert         if (*t == 0) {
329*7f2fe78bSCy Schubert             i++;
330*7f2fe78bSCy Schubert             break;
331*7f2fe78bSCy Schubert         }
332*7f2fe78bSCy Schubert     }
333*7f2fe78bSCy Schubert     /* cap the array */
334*7f2fe78bSCy Schubert     files[i] = 0;
335*7f2fe78bSCy Schubert #endif /* !_WIN32 */
336*7f2fe78bSCy Schubert     *pfiles = (profile_filespec_t *)files;
337*7f2fe78bSCy Schubert     return 0;
338*7f2fe78bSCy Schubert }
339*7f2fe78bSCy Schubert 
340*7f2fe78bSCy Schubert static krb5_error_code
add_kdc_config_file(profile_filespec_t ** pfiles)341*7f2fe78bSCy Schubert add_kdc_config_file(profile_filespec_t **pfiles)
342*7f2fe78bSCy Schubert {
343*7f2fe78bSCy Schubert     char *file = NULL;
344*7f2fe78bSCy Schubert     size_t count = 0;
345*7f2fe78bSCy Schubert     profile_filespec_t *newfiles;
346*7f2fe78bSCy Schubert 
347*7f2fe78bSCy Schubert     file = secure_getenv(KDC_PROFILE_ENV);
348*7f2fe78bSCy Schubert     if (file == NULL)
349*7f2fe78bSCy Schubert         file = DEFAULT_KDC_PROFILE;
350*7f2fe78bSCy Schubert 
351*7f2fe78bSCy Schubert     for (count = 0; (*pfiles)[count]; count++)
352*7f2fe78bSCy Schubert         ;
353*7f2fe78bSCy Schubert     count += 2;
354*7f2fe78bSCy Schubert     newfiles = malloc(count * sizeof(*newfiles));
355*7f2fe78bSCy Schubert     if (newfiles == NULL)
356*7f2fe78bSCy Schubert         return ENOMEM;
357*7f2fe78bSCy Schubert     memcpy(newfiles + 1, *pfiles, (count-1) * sizeof(*newfiles));
358*7f2fe78bSCy Schubert     newfiles[0] = strdup(file);
359*7f2fe78bSCy Schubert     if (newfiles[0] == NULL) {
360*7f2fe78bSCy Schubert         int e = ENOMEM;
361*7f2fe78bSCy Schubert         free(newfiles);
362*7f2fe78bSCy Schubert         return e;
363*7f2fe78bSCy Schubert     }
364*7f2fe78bSCy Schubert     free(*pfiles);
365*7f2fe78bSCy Schubert     *pfiles = newfiles;
366*7f2fe78bSCy Schubert     return 0;
367*7f2fe78bSCy Schubert }
368*7f2fe78bSCy Schubert 
369*7f2fe78bSCy Schubert 
370*7f2fe78bSCy Schubert /* Set the profile paths in the context.  If secure is set to TRUE
371*7f2fe78bSCy Schubert    then do not include user paths (from environment variables, etc).
372*7f2fe78bSCy Schubert    If kdc is TRUE, include kdc.conf from wherever we expect to find
373*7f2fe78bSCy Schubert    it.  */
374*7f2fe78bSCy Schubert static krb5_error_code
os_init_paths(krb5_context ctx,krb5_boolean kdc)375*7f2fe78bSCy Schubert os_init_paths(krb5_context ctx, krb5_boolean kdc)
376*7f2fe78bSCy Schubert {
377*7f2fe78bSCy Schubert     krb5_error_code    retval = 0;
378*7f2fe78bSCy Schubert     profile_filespec_t *files = 0;
379*7f2fe78bSCy Schubert     krb5_boolean secure = ctx->profile_secure;
380*7f2fe78bSCy Schubert 
381*7f2fe78bSCy Schubert     retval = os_get_default_config_files(&files, secure);
382*7f2fe78bSCy Schubert 
383*7f2fe78bSCy Schubert     if (retval == 0 && kdc)
384*7f2fe78bSCy Schubert         retval = add_kdc_config_file(&files);
385*7f2fe78bSCy Schubert 
386*7f2fe78bSCy Schubert     if (!retval) {
387*7f2fe78bSCy Schubert         retval = profile_init_flags((const_profile_filespec_t *) files,
388*7f2fe78bSCy Schubert                                     PROFILE_INIT_ALLOW_MODULE, &ctx->profile);
389*7f2fe78bSCy Schubert 
390*7f2fe78bSCy Schubert         /* If none of the filenames can be opened, use an empty profile. */
391*7f2fe78bSCy Schubert         if (retval == ENOENT)
392*7f2fe78bSCy Schubert             retval = profile_init(NULL, &ctx->profile);
393*7f2fe78bSCy Schubert     }
394*7f2fe78bSCy Schubert 
395*7f2fe78bSCy Schubert     if (files)
396*7f2fe78bSCy Schubert         free_filespecs(files);
397*7f2fe78bSCy Schubert 
398*7f2fe78bSCy Schubert     if (retval)
399*7f2fe78bSCy Schubert         ctx->profile = 0;
400*7f2fe78bSCy Schubert 
401*7f2fe78bSCy Schubert     if (retval == ENOENT)
402*7f2fe78bSCy Schubert         return KRB5_CONFIG_CANTOPEN;
403*7f2fe78bSCy Schubert 
404*7f2fe78bSCy Schubert     if ((retval == PROF_SECTION_NOTOP) ||
405*7f2fe78bSCy Schubert         (retval == PROF_SECTION_SYNTAX) ||
406*7f2fe78bSCy Schubert         (retval == PROF_RELATION_SYNTAX) ||
407*7f2fe78bSCy Schubert         (retval == PROF_EXTRA_CBRACE) ||
408*7f2fe78bSCy Schubert         (retval == PROF_MISSING_OBRACE))
409*7f2fe78bSCy Schubert         return KRB5_CONFIG_BADFORMAT;
410*7f2fe78bSCy Schubert 
411*7f2fe78bSCy Schubert     return retval;
412*7f2fe78bSCy Schubert }
413*7f2fe78bSCy Schubert 
414*7f2fe78bSCy Schubert krb5_error_code
k5_os_init_context(krb5_context ctx,profile_t profile,krb5_flags flags)415*7f2fe78bSCy Schubert k5_os_init_context(krb5_context ctx, profile_t profile, krb5_flags flags)
416*7f2fe78bSCy Schubert {
417*7f2fe78bSCy Schubert     krb5_os_context os_ctx;
418*7f2fe78bSCy Schubert     krb5_error_code    retval = 0;
419*7f2fe78bSCy Schubert #ifdef _WIN32
420*7f2fe78bSCy Schubert     WORD wVersionRequested;
421*7f2fe78bSCy Schubert     WSADATA wsaData;
422*7f2fe78bSCy Schubert #endif /* _WIN32 */
423*7f2fe78bSCy Schubert 
424*7f2fe78bSCy Schubert     os_ctx = &ctx->os_context;
425*7f2fe78bSCy Schubert     os_ctx->magic = KV5M_OS_CONTEXT;
426*7f2fe78bSCy Schubert     os_ctx->time_offset = 0;
427*7f2fe78bSCy Schubert     os_ctx->usec_offset = 0;
428*7f2fe78bSCy Schubert     os_ctx->os_flags = 0;
429*7f2fe78bSCy Schubert     os_ctx->default_ccname = 0;
430*7f2fe78bSCy Schubert 
431*7f2fe78bSCy Schubert     PLUGIN_DIR_INIT(&ctx->libkrb5_plugins);
432*7f2fe78bSCy Schubert     ctx->preauth_context = NULL;
433*7f2fe78bSCy Schubert 
434*7f2fe78bSCy Schubert     /* Use the profile we were handed, or create one from config files. */
435*7f2fe78bSCy Schubert     if (profile)
436*7f2fe78bSCy Schubert         retval = profile_copy(profile, &ctx->profile);
437*7f2fe78bSCy Schubert     else
438*7f2fe78bSCy Schubert         retval = os_init_paths(ctx, (flags & KRB5_INIT_CONTEXT_KDC) != 0);
439*7f2fe78bSCy Schubert     if (retval)
440*7f2fe78bSCy Schubert         return retval;
441*7f2fe78bSCy Schubert 
442*7f2fe78bSCy Schubert #ifdef _WIN32
443*7f2fe78bSCy Schubert     /* We initialize winsock to version 1.1 but
444*7f2fe78bSCy Schubert      * we do not care if we succeed or fail.
445*7f2fe78bSCy Schubert      */
446*7f2fe78bSCy Schubert     wVersionRequested = 0x0101;
447*7f2fe78bSCy Schubert     WSAStartup (wVersionRequested, &wsaData);
448*7f2fe78bSCy Schubert #endif /* _WIN32 */
449*7f2fe78bSCy Schubert 
450*7f2fe78bSCy Schubert     return 0;
451*7f2fe78bSCy Schubert }
452*7f2fe78bSCy Schubert 
453*7f2fe78bSCy Schubert krb5_error_code KRB5_CALLCONV
krb5_get_profile(krb5_context ctx,profile_t * profile)454*7f2fe78bSCy Schubert krb5_get_profile (krb5_context ctx, profile_t *profile)
455*7f2fe78bSCy Schubert {
456*7f2fe78bSCy Schubert     return profile_copy (ctx->profile, profile);
457*7f2fe78bSCy Schubert }
458*7f2fe78bSCy Schubert 
459*7f2fe78bSCy Schubert krb5_error_code
krb5_set_config_files(krb5_context ctx,const char ** filenames)460*7f2fe78bSCy Schubert krb5_set_config_files(krb5_context ctx, const char **filenames)
461*7f2fe78bSCy Schubert {
462*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
463*7f2fe78bSCy Schubert     profile_t    profile;
464*7f2fe78bSCy Schubert 
465*7f2fe78bSCy Schubert     retval = profile_init_flags(filenames, PROFILE_INIT_ALLOW_MODULE,
466*7f2fe78bSCy Schubert                                 &profile);
467*7f2fe78bSCy Schubert     if (retval)
468*7f2fe78bSCy Schubert         return retval;
469*7f2fe78bSCy Schubert 
470*7f2fe78bSCy Schubert     if (ctx->profile)
471*7f2fe78bSCy Schubert         profile_release(ctx->profile);
472*7f2fe78bSCy Schubert     ctx->profile = profile;
473*7f2fe78bSCy Schubert 
474*7f2fe78bSCy Schubert     return 0;
475*7f2fe78bSCy Schubert }
476*7f2fe78bSCy Schubert 
477*7f2fe78bSCy Schubert krb5_error_code KRB5_CALLCONV
krb5_get_default_config_files(char *** pfilenames)478*7f2fe78bSCy Schubert krb5_get_default_config_files(char ***pfilenames)
479*7f2fe78bSCy Schubert {
480*7f2fe78bSCy Schubert     if (!pfilenames)
481*7f2fe78bSCy Schubert         return EINVAL;
482*7f2fe78bSCy Schubert     return os_get_default_config_files(pfilenames, FALSE);
483*7f2fe78bSCy Schubert }
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert void KRB5_CALLCONV
krb5_free_config_files(char ** filenames)486*7f2fe78bSCy Schubert krb5_free_config_files(char **filenames)
487*7f2fe78bSCy Schubert {
488*7f2fe78bSCy Schubert     free_filespecs(filenames);
489*7f2fe78bSCy Schubert }
490*7f2fe78bSCy Schubert 
491*7f2fe78bSCy Schubert void
k5_os_free_context(krb5_context ctx)492*7f2fe78bSCy Schubert k5_os_free_context(krb5_context ctx)
493*7f2fe78bSCy Schubert {
494*7f2fe78bSCy Schubert     krb5_os_context os_ctx;
495*7f2fe78bSCy Schubert 
496*7f2fe78bSCy Schubert     os_ctx = &ctx->os_context;
497*7f2fe78bSCy Schubert 
498*7f2fe78bSCy Schubert     if (os_ctx->default_ccname) {
499*7f2fe78bSCy Schubert         free(os_ctx->default_ccname);
500*7f2fe78bSCy Schubert         os_ctx->default_ccname = 0;
501*7f2fe78bSCy Schubert     }
502*7f2fe78bSCy Schubert 
503*7f2fe78bSCy Schubert     os_ctx->magic = 0;
504*7f2fe78bSCy Schubert 
505*7f2fe78bSCy Schubert     if (ctx->profile) {
506*7f2fe78bSCy Schubert         profile_release(ctx->profile);
507*7f2fe78bSCy Schubert         ctx->profile = 0;
508*7f2fe78bSCy Schubert     }
509*7f2fe78bSCy Schubert 
510*7f2fe78bSCy Schubert     if (ctx->preauth_context) {
511*7f2fe78bSCy Schubert         k5_free_preauth_context(ctx);
512*7f2fe78bSCy Schubert         ctx->preauth_context = NULL;
513*7f2fe78bSCy Schubert     }
514*7f2fe78bSCy Schubert     krb5int_close_plugin_dirs (&ctx->libkrb5_plugins);
515*7f2fe78bSCy Schubert 
516*7f2fe78bSCy Schubert #ifdef _WIN32
517*7f2fe78bSCy Schubert     WSACleanup();
518*7f2fe78bSCy Schubert #endif /* _WIN32 */
519*7f2fe78bSCy Schubert }
520