Merge pull request #2720 from mono/fix-39325
[mono.git] / mono / metadata / mono-security.c
index 61057c0097f0c11e102041a4afcdd2f0a5ab1ef3..d59d624782a8d781bacbf49472ca26a457a185b8 100644 (file)
@@ -5,6 +5,7 @@
  *     Sebastien Pouliot  <sebastien@ximian.com>
  *
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -153,7 +154,7 @@ GetTokenName (uid_t uid)
 #else
        fbufsize = MONO_SYSCONF_DEFAULT_SIZE;
 #endif
-       fbuf = g_malloc0 (fbufsize);
+       fbuf = (gchar *)g_malloc0 (fbufsize);
        retval = getpwuid_r (uid, &pwd, fbuf, fbufsize, &p);
        result = ((retval == 0) && (p == &pwd));
 #else
@@ -220,7 +221,7 @@ IsDefaultGroup (uid_t user, gid_t group)
        fbufsize = MONO_SYSCONF_DEFAULT_SIZE;
 #endif
 
-       fbuf = g_malloc0 (fbufsize);
+       fbuf = (gchar *)g_malloc0 (fbufsize);
        retval = getpwuid_r (user, &pwd, fbuf, fbufsize, &p);
        result = ((retval == 0) && (p == &pwd));
 #else
@@ -269,8 +270,6 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetCurrentToken (void)
 {
        gpointer token = NULL;
 
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HOST_WIN32
        /* Note: This isn't a copy of the Token - we must not close it!!!
         * http://www.develop.com/kbrown/book/html/whatis_windowsprincipal.html
@@ -291,13 +290,13 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetCurrentToken (void)
 MonoString*
 ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName (gpointer token)
 {
+       MonoError error;
        MonoString *result = NULL;
        gunichar2 *uniname = NULL;
        gint32 size = 0;
 
+       mono_error_init (&error);
 #ifdef HOST_WIN32
-       MONO_ARCH_SAVE_REGS;
-
        GetTokenInformation (token, TokenUser, NULL, size, (PDWORD)&size);
        if (size > 0) {
                TOKEN_USER *tu = g_malloc0 (size);
@@ -309,8 +308,6 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName (gpointer token
 #else 
        gchar *uname = GetTokenName ((uid_t) GPOINTER_TO_INT (token));
 
-       MONO_ARCH_SAVE_REGS;
-
        if (uname) {
                size = strlen (uname);
                uniname = g_utf8_to_utf16 (uname, size, NULL, NULL, NULL);
@@ -319,7 +316,7 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName (gpointer token
 #endif /* HOST_WIN32 */
 
        if (size > 0) {
-               result = mono_string_new_utf16 (mono_domain_get (), uniname, size);
+               result = mono_string_new_utf16_checked (mono_domain_get (), uniname, size, &error);
        }
        else
                result = mono_string_new (mono_domain_get (), "");
@@ -327,6 +324,7 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName (gpointer token
        if (uniname)
                g_free (uniname);
 
+       mono_error_set_pending_exception (&error);
        return result;
 }
 
@@ -337,8 +335,6 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken (MonoString *us
 #ifdef HOST_WIN32
        gpointer token = NULL;
 
-       MONO_ARCH_SAVE_REGS;
-
        /* TODO: MS has something like this working in Windows 2003 (client and
         * server) but works only for domain accounts (so it's quite limiting).
         * http://www.develop.com/kbrown/book/html/howto_logonuser.html
@@ -358,8 +354,6 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken (MonoString *us
        gchar *utf8_name;
        gboolean result;
 
-       MONO_ARCH_SAVE_REGS;
-
        utf8_name = mono_unicode_to_external (mono_string_chars (username));
 
 #ifdef HAVE_GETPWNAM_R
@@ -369,7 +363,7 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken (MonoString *us
        fbufsize = MONO_SYSCONF_DEFAULT_SIZE;
 #endif
 
-       fbuf = g_malloc0 (fbufsize);
+       fbuf = (gchar *)g_malloc0 (fbufsize);
        retval = getpwnam_r (utf8_name, &pwd, fbuf, fbufsize, &p);
        result = ((retval == 0) && (p == &pwd));
 #else
@@ -400,10 +394,9 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetRoles (gpointer token)
        MonoArray *array = NULL;
        MonoDomain *domain = mono_domain_get (); 
 #ifdef HOST_WIN32
+       MonoError error;
        gint32 size = 0;
 
-       MONO_ARCH_SAVE_REGS;
-
        GetTokenInformation (token, TokenGroups, NULL, size, (PDWORD)&size);
        if (size > 0) {
                TOKEN_GROUPS *tg = g_malloc0 (size);
@@ -418,7 +411,13 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetRoles (gpointer token)
                                gunichar2 *uniname = GetSidName (NULL, tg->Groups [i].Sid, &size);
 
                                if (uniname) {
-                                       MonoString *str = mono_string_new_utf16 (domain, uniname, size);
+                                       MonoString *str = mono_string_new_utf16_checked (domain, uniname, size, &error);
+                                       if (!is_ok (&error)) {
+                                               g_free (uniname);
+                                               g_free (tg);
+                                               mono_error_set_pending_exception (&error);
+                                               return NULL;
+                                       }
                                        mono_array_setref (array, i, str);
                                        g_free (uniname);
                                }
@@ -446,8 +445,6 @@ ves_icall_System_Security_Principal_WindowsImpersonationContext_CloseToken (gpoi
 {
        gboolean result = TRUE;
 
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HOST_WIN32
        result = (CloseHandle (token) != 0);
 #endif
@@ -460,8 +457,6 @@ ves_icall_System_Security_Principal_WindowsImpersonationContext_DuplicateToken (
 {
        gpointer dupe = NULL;
 
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HOST_WIN32
        if (DuplicateToken (token, SecurityImpersonation, &dupe) == 0) {
                dupe = NULL;
@@ -476,8 +471,6 @@ ves_icall_System_Security_Principal_WindowsImpersonationContext_DuplicateToken (
 gboolean
 ves_icall_System_Security_Principal_WindowsImpersonationContext_SetCurrentToken (gpointer token)
 {
-       MONO_ARCH_SAVE_REGS;
-
        /* Posix version implemented in /mono/mono/io-layer/security.c */
        return (ImpersonateLoggedOnUser (token) != 0);
 }
@@ -486,8 +479,6 @@ ves_icall_System_Security_Principal_WindowsImpersonationContext_SetCurrentToken
 gboolean
 ves_icall_System_Security_Principal_WindowsImpersonationContext_RevertToSelf (void)
 {
-       MONO_ARCH_SAVE_REGS;
-
        /* Posix version implemented in /mono/mono/io-layer/security.c */
        return (RevertToSelf () != 0);
 }
@@ -501,8 +492,6 @@ ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupId (gpointer
        gboolean result = FALSE;
 
 #ifdef HOST_WIN32
-       MONO_ARCH_SAVE_REGS;
-
        /* The convertion from an ID to a string is done in managed code for Windows */
        g_warning ("IsMemberOfGroupId should never be called on Win32");
 
@@ -516,15 +505,13 @@ ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupId (gpointer
 #endif
        struct group *g = NULL;
 
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef HAVE_GETGRGID_R
 #ifdef _SC_GETGR_R_SIZE_MAX
        fbufsize = mono_sysconf (_SC_GETGR_R_SIZE_MAX);
 #else
        fbufsize = MONO_SYSCONF_DEFAULT_SIZE;
 #endif
-       fbuf = g_malloc0 (fbufsize);
+       fbuf = (gchar *)g_malloc0 (fbufsize);
        retval = getgrgid_r ((gid_t) GPOINTER_TO_INT (group), &grp, fbuf, fbufsize, &g);
        result = ((retval == 0) && (g == &grp));
 #else
@@ -553,17 +540,12 @@ ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupName (gpoint
        gboolean result = FALSE;
 
 #ifdef HOST_WIN32
-
-       MONO_ARCH_SAVE_REGS;
-
        /* Windows version use a cache built using WindowsIdentity._GetRoles */
        g_warning ("IsMemberOfGroupName should never be called on Win32");
 
 #else /* HOST_WIN32 */
        gchar *utf8_groupname;
 
-       MONO_ARCH_SAVE_REGS;
-
        utf8_groupname = mono_unicode_to_external (mono_string_chars (group));
        if (utf8_groupname) {
                struct group *g = NULL;
@@ -576,7 +558,7 @@ ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupName (gpoint
 #else
                size_t fbufsize = MONO_SYSCONF_DEFAULT_SIZE;
 #endif
-               fbuf = g_malloc0 (fbufsize);
+               fbuf = (gchar *)g_malloc0 (fbufsize);
                retval = getgrnam_r (utf8_groupname, &grp, fbuf, fbufsize, &g);
                result = ((retval == 0) && (g == &grp));
 #else
@@ -861,14 +843,11 @@ ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure (MonoString *r
 #if HOST_WIN32
        gint32 flags;
 
-       MONO_ARCH_SAVE_REGS;
-
        /* ACL are nice... unless you have FAT or other uncivilized filesystem */
        if (!GetVolumeInformation (mono_string_chars (root), NULL, 0, NULL, NULL, (LPDWORD)&flags, NULL, 0))
                return FALSE;
        return ((flags & FS_PERSISTENT_ACLS) == FS_PERSISTENT_ACLS);
 #else
-       MONO_ARCH_SAVE_REGS;
        /* we assume some kind of security is applicable outside Windows */
        return TRUE;
 #endif
@@ -880,8 +859,6 @@ ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsMachineProtected (Mono
 {
        gboolean ret = FALSE;
 
-       MONO_ARCH_SAVE_REGS;
-
        /* no one, but the owner, should have write access to the directory */
 #ifdef HOST_WIN32
        ret = IsMachineProtected (mono_string_chars (path));
@@ -897,8 +874,6 @@ ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsUserProtected (MonoStr
 {
        gboolean ret = FALSE;
 
-       MONO_ARCH_SAVE_REGS;
-
        /* no one, but the user, should have access to the directory */
 #ifdef HOST_WIN32
        ret = IsUserProtected (mono_string_chars (path));
@@ -914,8 +889,6 @@ ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (MonoStri
 {
        gboolean ret = FALSE;
 
-       MONO_ARCH_SAVE_REGS;
-
        /* read/write to owner, read to everyone else */
 #ifdef HOST_WIN32
        ret = ProtectMachine (mono_string_chars (path));
@@ -931,8 +904,6 @@ ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (MonoString
 {
        gboolean ret = FALSE;
        
-       MONO_ARCH_SAVE_REGS;
-
        /* read/write to user, no access to everyone else */
 #ifdef HOST_WIN32
        ret = ProtectUser (mono_string_chars (path));
@@ -966,22 +937,26 @@ static MonoImage *system_security_assembly = NULL;
 void
 ves_icall_System_Security_SecureString_DecryptInternal (MonoArray *data, MonoObject *scope)
 {
-       invoke_protected_memory_method (data, scope, FALSE);
+       MonoError error;
+       invoke_protected_memory_method (data, scope, FALSE, &error);
+       mono_error_set_pending_exception (&error);
 }
 void
 ves_icall_System_Security_SecureString_EncryptInternal (MonoArray* data, MonoObject *scope)
 {
-       invoke_protected_memory_method (data, scope, TRUE);
+       MonoError error;
+       invoke_protected_memory_method (data, scope, TRUE, &error);
+       mono_error_set_pending_exception (&error);
 }
 
-void invoke_protected_memory_method (MonoArray *data, MonoObject *scope, gboolean encrypt)
+void invoke_protected_memory_method (MonoArray *data, MonoObject *scope, gboolean encrypt, MonoError *error)
 {
        MonoClass *klass;
        MonoMethod *method;
        void *params [2];
 
-       MONO_ARCH_SAVE_REGS;
-
+       mono_error_init (error);
+       
        if (system_security_assembly == NULL) {
                system_security_assembly = mono_image_loaded ("System.Security");
                if (!system_security_assembly) {
@@ -992,10 +967,11 @@ void invoke_protected_memory_method (MonoArray *data, MonoObject *scope, gboolea
                }
        }
 
-       klass = mono_class_from_name (system_security_assembly,
+       klass = mono_class_load_from_name (system_security_assembly,
                                                                  "System.Security.Cryptography", "ProtectedMemory");
        method = mono_class_get_method_from_name (klass, encrypt ? "Protect" : "Unprotect", 2);
        params [0] = data;
        params [1] = scope; /* MemoryProtectionScope.SameProcess */
-       mono_runtime_invoke (method, NULL, params, NULL);
+
+       mono_runtime_invoke_checked (method, NULL, params, error);
 }