* ccdefname.c (get_from_registry_indirect, try_dir, get_from_os):
authorDanilo Almeida <dalmeida@mit.edu>
Thu, 17 Jun 1999 10:01:28 +0000 (10:01 +0000)
committerDanilo Almeida <dalmeida@mit.edu>
Thu, 17 Jun 1999 10:01:28 +0000 (10:01 +0000)
        Extra robustness to win32 code.
* init_os_ctx.c (krb5_get_config_files, krb5_free_config_files):
        Add function to get config files being used for current
        context with corresponding free function.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11520 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/ccdefname.c
src/lib/krb5/os/init_os_ctx.c

index fa8e7f03b1a79ae1f94dfb5832c8c032b9d35e7e..c493db665a726127334d743190abfb3722de1f4c 100644 (file)
@@ -1,3 +1,12 @@
+1999-06-16  Danilo Almeida  <dalmeida@mit.edu>
+
+       * ccdefname.c (get_from_registry_indirect, try_dir, get_from_os): 
+               Extra robustness to win32 code.
+
+       * init_os_ctx.c (krb5_get_config_files, krb5_free_config_files):
+               Add function to get config files being used for current 
+               context with corresponding free function.
+
 1999-06-16  Danilo Almeida  <dalmeida@mit.edu>
 
        * init_os_ctx.c (os_init_paths): Enhance win32 heuristics to use 
index 9cae686e1cac5f80a628bc83ad41bdbfc28cd998..11713e724787bc371d798b4a20a44e32aba782a7 100644 (file)
@@ -51,11 +51,13 @@ static int get_from_registry_indirect(char *name_buf, int name_size)
        int found = 0;
        char *cp;
 
+        newkey[0] = 0;
        GetPrivateProfileString(INI_FILES, "RegKRB5CCNAME", "", 
                                newkey, sizeof(newkey), KERBEROS_INI);
        if (!newkey[0])
                return 0;
        
+        newkey[sizeof(newkey)-1] = 0;
        cp = strrchr(newkey,'\\');
        if (cp) {
                *cp = '\0'; /* split the string */
@@ -111,6 +113,8 @@ get_from_registry(
     return 1;
 }
 
+#define APPEND_KRB5CC "\\krb5cc"
+
 static int
 try_dir(
     char* dir,
@@ -119,16 +123,18 @@ try_dir(
     )
 {
     struct _stat s;
-    static const char APPEND_KRB5CC[] = "\\krb5cc";
     if (!dir)
         return 0;
     if (_stat(dir, &s))
         return 0;
     if (!(s.st_mode & _S_IFDIR))
         return 0;
-    if (buffer != dir)
+    if (buffer != dir) {
         strncpy(buffer, dir, buf_len);
-    strncat(buffer, APPEND_KRB5CC, buf_len);
+        buffer[buf_len-1]='\0';
+    }
+    strncat(buffer, APPEND_KRB5CC, buf_len-strlen(buffer));
+    buffer[buf_len-1] = '\0';
     return 1;
 }
 #endif
@@ -137,7 +143,7 @@ try_dir(
 static krb5_error_code get_from_os(char *name_buf, int name_size)
 {
        char *prefix = krb5_cc_dfl_ops->prefix;
-       int len;
+        int size;
         char *p;
 
        if (get_from_registry(HKEY_CURRENT_USER,
@@ -151,23 +157,26 @@ static krb5_error_code get_from_os(char *name_buf, int name_size)
        if (get_from_registry_indirect(name_buf, name_size) != 0)
                return 0;
 
-        strncpy(name_buf, prefix, name_size);
-        strncat(name_buf, ":", name_size);
+        strncpy(name_buf, prefix, name_size);       
         name_buf[name_size - 1] = 0;
-        len = strlen(name_buf);
-        p = name_buf + len;
-        len = name_size - len;
+        size = name_size - strlen(prefix);
+        if (size > 0)
+            strcat(name_buf, ":");
+        size--;
+        p = name_buf + name_size - size;
        if (!strcmp(prefix, "API")) {
-               strncpy(p, "krb5cc", len);
+               strncpy(p, "krb5cc", size);
        } else if (!strcmp(prefix, "FILE") || !strcmp(prefix, "STDIO")) {
-               if (!try_dir(getenv("TEMP"), p, len) &&
-                   !try_dir(getenv("TMP"), p, len))
+               if (!try_dir(getenv("TEMP"), p, size) &&
+                   !try_dir(getenv("TMP"), p, size))
                {
-                       GetWindowsDirectory(p, len);
-                       strncat(p, "\\krb5cc", len);
+                    int len = GetWindowsDirectory(p, size);
+                    name_buf[name_size - 1] = 0;
+                    if (len < size - sizeof(APPEND_KRB5CC))
+                       strcat(p, APPEND_KRB5CC);
                }
        } else {
-               strncpy(p, "default_cache_name", len);
+               strncpy(p, "default_cache_name", size);
        }
        name_buf[name_size - 1] = 0;
        return 0;
index fa185838fd8970ac70590b92b63479e6cd829302..d513cba5c973dcb70ebbc40ec25ac33fd2118dab 100644 (file)
 #define NEED_WINDOWS
 #include "k5-int.h"
 
-static krb5_error_code
-fixup_os_init_paths_retval(retval)
-    krb5_error_code retval;
-{
-    if (retval == ENOENT)
-        return KRB5_CONFIG_CANTOPEN;
-
-    if ((retval == PROF_SECTION_NOTOP) ||
-        (retval == PROF_SECTION_SYNTAX) ||
-        (retval == PROF_RELATION_SYNTAX) ||
-        (retval == PROF_EXTRA_CBRACE) ||
-        (retval == PROF_MISSING_OBRACE))
-        return KRB5_CONFIG_BADFORMAT;
-
-    return retval;
-}
-
 #ifdef macintosh
 static CInfoPBRec      theCatInfo;
 static char            *FileBuffer;
@@ -114,6 +97,62 @@ char        pathbuf[255];
 
 #if defined(_MSDOS) || defined(_WIN32)
 
+static krb5_error_code
+get_from_windows_dir(
+    char **pname
+    )
+{
+    UINT size = GetWindowsDirectory(0, 0);
+    *pname = malloc(size + 1 +
+                    strlen(DEFAULT_PROFILE_FILENAME) + 1);
+    if (*pname)
+    {
+        GetWindowsDirectory(*pname, size);
+        strcat(*pname, "\\");
+        strcat(*pname, DEFAULT_PROFILE_FILENAME);
+        return 0;
+    } else {
+        return KRB5_CONFIG_CANTOPEN;
+    }
+}
+
+static krb5_error_code
+get_from_module_dir(
+    char **pname
+    )
+{
+    const DWORD size = 1024; /* fixed buffer */
+    int found = 0;
+    char *p;
+    char *name;
+    struct _stat s;
+
+    *pname = 0;
+
+    name = malloc(size);
+    if (!name)
+        return ENOMEM;
+
+    if (!GetModuleFileName(GetModuleHandle("krb5_32"), name, size))
+        goto cleanup;
+
+    p = name + strlen(name);
+    while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
+    if (p < name)
+        goto cleanup;
+    p++;
+    strncpy(p, DEFAULT_PROFILE_FILENAME, size - (p - name));
+    name[size - 1] = 0;
+    found = !_stat(name, &s);
+
+ cleanup:
+    if (found)
+        *pname = name;
+    else
+        if (name) free(name);
+    return 0;
+}
+
 /*
  * get_from_registry
  *
@@ -123,7 +162,6 @@ char        pathbuf[255];
  * about.  We maintain the invariant: return value != 0 => 
  * *pbuffer == 0.
  */
-
 static krb5_error_code
 get_from_registry(
     char** pbuffer,
@@ -131,6 +169,7 @@ get_from_registry(
     )
 {
     HKEY hKey = 0;
+    LONG rc = 0;
     DWORD size = 0;
     krb5_error_code retval = 0;
     const char *key_path = "Software\\MIT\\Kerberos5";
@@ -146,13 +185,14 @@ get_from_registry(
     }
     *pbuffer = 0;
 
-    if (RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, 
-                     &hKey) != ERROR_SUCCESS)
+    if ((rc = RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, 
+                           &hKey)) != ERROR_SUCCESS)
     {
         /* not a real error */
         goto cleanup;
     }
-    if (RegQueryValueEx(hKey, value_name, 0, 0, 0, &size) != ERROR_MORE_DATA)
+    rc = RegQueryValueEx(hKey, value_name, 0, 0, 0, &size);
+    if ((rc != ERROR_SUCCESS) &&  (rc != ERROR_MORE_DATA))
     {
         /* not a real error */
         goto cleanup;
@@ -163,7 +203,7 @@ get_from_registry(
         retval = ENOMEM;
         goto cleanup;
     }
-    if (RegQueryValueEx(hKey, value_name, 0, 0, *pbuffer, &size) != 
+    if ((rc = RegQueryValueEx(hKey, value_name, 0, 0, *pbuffer, &size)) != 
         ERROR_SUCCESS)
     {
         /*
@@ -186,93 +226,126 @@ get_from_registry(
     return retval;
 }
 
+#endif /* _MSDOS || _WIN32 */
+
+static void
+free_filenames(filenames)
+       char **filenames;
+{
+    char **cp;
+
+    if (filenames == 0)
+        return;
+    
+    for (cp = filenames; *cp; cp++)
+       free(*cp);
+    free(filenames);
+}
+
 static krb5_error_code
-os_init_paths(ctx, secure)
-       krb5_context ctx;
+os_get_default_config_files(pfilenames, secure)
+       char ***pfilenames;
        krb5_boolean secure;
 {
+    char **filenames;
+#ifdef macintosh
+    filenames = malloc(3 * sizeof(char *));
+    filenames[0] = GetMacProfilePathName("\pkrb Configuration");
+    filenames[1] = GetMacProfilePathName("\pkrb5.ini");
+    filenames[2] = 0;
+#else /* !macintosh */
+#if defined(_MSDOS) || defined(_WIN32)
     krb5_error_code retval = 0;
     char *name = 0;
 
-    ctx->profile_secure = secure;
-
-    if (!secure) name = getenv("KRB5_CONFIG");
+    if (!secure)
+    {
+        char *env = getenv("KRB5_CONFIG");
+        if (env)
+        {
+            name = malloc(strlen(env) + 1);
+            if (!name) return ENOMEM;
+            strcpy(name, env);
+        }
+    }
     if (!name && !secure)
     {
         /* HKCU */
         retval = get_from_registry(&name, HKEY_CURRENT_USER);
-        if (retval)
-            goto cleanup;
+        if (retval) return retval;
     }
     if (!name)
     {
         /* HKLM */
         retval = get_from_registry(&name, HKEY_LOCAL_MACHINE);
-        if (retval)
-            goto cleanup;
+        if (retval) return retval;
     }
     if (!name && !secure)
     {
         /* module dir */
-        const DWORD size = 1024; /* fixed buffer */
-        int found = 0;
-        name = malloc(size);
-        if (!name) {
-            retval = ENOMEM;
-            goto cleanup;
-        }
-        if (GetModuleFileName(0, name, size))
-        {
-            char *p = name + strlen(name);
-            while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
-            if (p >= name)
-            {
-                struct _stat s;
-                p++;
-                strncpy(p, DEFAULT_PROFILE_FILENAME, size - (p - name));
-                name[size - 1] = 0;
-                found = !_stat(name, &s);
-            }
-        } else {
-            /* Module name too long.  Oh well.  Keep trucking. */
-        }
-        if (!found && name)
-        {
-            free(name);
-            name = 0;
-        }
+        retval = get_from_module_dir(&name);
+        if (retval) return retval;
     }
     if (!name)
     {
         /* windows dir */
-        UINT size = GetWindowsDirectory(0, 0);
-        name = malloc(size + 1 +
-                      strlen(DEFAULT_PROFILE_FILENAME) + 1);
-        if (name)
-        {
-            GetWindowsDirectory(name, size);
-            strcat(name, "\\");
-            strcat(name, DEFAULT_PROFILE_FILENAME);
-        } else {
-            retval = KRB5_CONFIG_CANTOPEN;
-        }
+        retval = get_from_windows_dir(&name);
     }
-    /* Invariant: name || retval */
-    if (!retval)
-    {
-        const char *filenames[2];
-        filenames[0] = name;
-        filenames[1] = 0;
-        retval = profile_init(filenames, &ctx->profile);
+    if (retval)
+        return retval;
+    if (!name)
+        return KRB5_CONFIG_CANTOPEN; /* should never happen */
+    
+    filenames = malloc(2 * sizeof(char *));
+    filenames[0] = name;
+    filenames[1] = 0;
+#else /* !_MSDOS && !_WIN32 */
+    char* filepath = 0;
+    int n_entries, i;
+    int ent_len;
+    const char *s, *t;
+    errcode_t retval;
+
+    if (!secure) filepath = getenv("KRB5_CONFIG");
+    if (!filepath) filepath = DEFAULT_PROFILE_PATH;
+
+    /* count the distinct filename components */
+    for(s = filepath, n_entries = 1; *s; s++) {
+        if (*s == ':')
+            n_entries++;
     }
- cleanup:
-    if (name)
-        free(name);
 
-    return fixup_os_init_paths_retval(retval);
+    /* the array is NULL terminated */
+    filenames = (char**) malloc((n_entries+1) * sizeof(char*));
+    if (filenames == 0)
+        return ENOMEM;
+
+    /* measure, copy, and skip each one */
+    for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++)
+    {
+        ent_len = t-s;
+        filenames[i] = (char*) malloc(ent_len + 1);
+        if (filenames[i] == 0) {
+            /* if malloc fails, free the ones that worked */
+            while(--i >= 0) free(filenames[i]);
+            free(filenames);
+            return ENOMEM;
+        }
+        strncpy(filenames[i], s, ent_len);
+        filenames[i][ent_len] = 0;
+        if (*t == 0) {
+            i++;
+            break;
+        }
+    }
+    /* cap the array */
+    filenames[i] = 0;
+#endif /* !_MSDOS && !_WIN32 */
+#endif /* !macintosh */
+    *pfilenames = filenames;
+    return 0;
 }
 
-#else
 
 /* Set the profile paths in the context. If secure is set to TRUE then 
    do not include user paths (from environment variables, etc.)
@@ -282,36 +355,34 @@ os_init_paths(ctx, secure)
        krb5_context ctx;
        krb5_boolean secure;
 {
-       krb5_error_code retval = 0;
-       char *name = 0;
+    krb5_error_code    retval = 0;
+    char **filenames = 0;
 
-#if defined(macintosh)
-       const char *filenames[3];
-#endif
-       ctx->profile_secure = secure;
+    ctx->profile_secure = secure;
 
-#ifdef macintosh
-       filenames[0] = GetMacProfilePathName("\pkrb Configuration");
-       filenames[1] = GetMacProfilePathName("\pkrb5.ini");
-       filenames[2] = 0;
-       retval = profile_init(filenames, &ctx->profile);
-#else
-       /*
-        * When the profile routines are later enhanced, we will try
-        * including a config file from user's home directory here.
-        */
-        if (!secure) name = getenv("KRB5_CONFIG");
-       if(!name) name = DEFAULT_PROFILE_PATH;
+    retval = os_get_default_config_files(&filenames, secure);
 
-       retval = profile_init_path(name, &ctx->profile);
-#endif /* macintosh */
+    if (!retval)
+        retval = profile_init(filenames, &ctx->profile);
 
-       if (retval)
-           ctx->profile = 0;
+    if (filenames)
+        free_filenames(filenames);
+
+    if (retval)
+        ctx->profile = 0;
+
+    if (retval == ENOENT)
+        return KRB5_CONFIG_CANTOPEN;
+
+    if ((retval == PROF_SECTION_NOTOP) ||
+        (retval == PROF_SECTION_SYNTAX) ||
+        (retval == PROF_RELATION_SYNTAX) ||
+        (retval == PROF_EXTRA_CBRACE) ||
+        (retval == PROF_MISSING_OBRACE))
+        return KRB5_CONFIG_BADFORMAT;
 
-        return fixup_os_init_paths_retval(retval);
+    return retval;
 }
-#endif /* _MSDOS || _WIN32 */
 
 krb5_error_code
 krb5_os_init_context(ctx)
@@ -367,6 +438,22 @@ krb5_set_config_files(ctx, filenames)
        return 0;
 }
 
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_get_default_config_files(pfilenames)
+       char ***pfilenames;
+{
+    if (!pfilenames)
+        return EINVAL;
+    return os_get_default_config_files(pfilenames, FALSE);
+}
+
+KRB5_DLLIMP void KRB5_CALLCONV
+krb5_free_config_files(filenames)
+       char **filenames;
+{
+    free_filenames(filenames);
+}
+
 krb5_error_code
 krb5_secure_config_files(ctx)
        krb5_context ctx;