Home
Manage Your Code
Snippet: Sample Event Handler to set Permissions (not using RunWithElevatedPrivilages) (C#)
Title: Sample Event Handler to set Permissions (not using RunWithElevatedPrivilages) Language: C#
Description: A request is often made to have an event handler that automagically sets the permissions on a list item so that only the author of the item can edit it, while other people can only read it. (http://www.sharepoint-tips.com/2007_03_01_archive.html) Views: 1696
Author: T D Date Added: 2/6/2009
Copy Code  
1using System;
2
3using System.Globalization;
4
5using System.ComponentModel;
6
7using System.IO;
8
9using System.Data;
10
11using System.Text;
12
13using System.Xml;
14
15using System.Collections;
16
17using System.Configuration;
18
19using System.Diagnostics;
20
21using System.Web;
22
23using System.Security;
24
25using System.Security.Policy;
26
27using System.Security.Principal;
28
29using System.Security.Permissions;
30
31using System.Runtime.InteropServices;
32
33using Microsoft.SharePoint;
34
35namespace SharePointTips.SharePoint.Samples.EventHandlers
36
37{
38
39    /// <summary>
40
41    /// This is the event receiver that traps the item added event of the sharepoint list it is attached to.
42
43    /// </summary>
44
45    class ListItemSecuritySetter:SPItemEventReceiver
46
47    {
48        #region constants   ...        #endregion
99        #region class properties   ...        #endregion
124        #region local variables   ...        #endregion
131        #region event handler event trapping   ...                #endregion
228        #region custom functions   ...        #endregion
533
534    }
535
536    /// <summary>
537
538    /// Handles simple file logging. Recommend switching to trace log.
539
540    /// </summary>
541
542    class HTMLFileLogging
543
544    {
545        #region class properties   ...                #endregion
632                #region CTOR   ...        #endregion
681        #region custom code   ...        #endregion
722
723
724
725    }
726
727    /// <summary>
728
729    /// Thanks to impersonation example of Victor Vogelpoel [Macaw] 
730
731    /// http://dotnetjunkies.com/WebLog/victorv/archive/category/2032.aspx
732
733    /// </summary>
734
735    public sealed class ImpersonationUtility
736
737    {        
738
739        private static string ADMINDOMAINACCOUNT = @"domain\user";//CHANGE THIS!
740
741        private static string ADMINDOMAIN = "domain";//CHANGE THIS!
742
743        private static string ADMINACCOUNT = "user";//CHANGE THIS!
744
745        private static string ADMINPASSWORD = "password";//CHANGE THIS!
746
747        private WindowsImpersonationContext _wiContext;
748
749        public IntPtr token;
750
751        /// <summary>
752
753        /// Private ctor.
754
755        /// </summary>
756
757        private ImpersonationUtility()
758
759        { }
760
761        /// <summary>
762
763        /// Start impersonating the administrator.
764
765        /// </summary>
766
767        /// <returns>an ImpersonationUtility instance.</returns>
768
769        public static ImpersonationUtility ImpersonateAdmin()
770
771        {
772
773            ImpersonationUtility imp = new ImpersonationUtility();
774
775            imp._ImpersonateAdmin();
776
777            return imp;
778
779        }
780
781        /// <summary>
782
783        /// Undo the impersonation.
784
785        /// </summary>
786
787        public void Undo()
788
789        {
790
791            if (this._wiContext != null)
792
793            {
794
795                this._wiContext.Undo();
796
797                this._wiContext = null;
798
799            }
800
801        }
802
803        private void _ImpersonateAdmin()
804
805        {
806
807            token = IntPtr.Zero;
808
809            IntPtr tokenDuplicate = IntPtr.Zero;
810
811            try
812
813            {
814
815                // Only start admin impersonation if we're not the admin...
816
817                if (String.Compare(ADMINDOMAINACCOUNT, WindowsIdentity.GetCurrent().Name, true, CultureInfo.InvariantCulture) != 0)
818
819                {
820
821                    // Temporarily stop the impersonation started by Web.Config.
822
823                    // WindowsIdentity.Impersonate() will store the current identity (the
824
825                    // account of the requestor) and return to the account of the ApplicationPool
826
827                    // which is "DOMAIN\SPAdmin".
828
829                    this._wiContext = WindowsIdentity.Impersonate(IntPtr.Zero);
830
831                    // But somehow the reverted account "DOMAIN\SPAdmin" still does
832
833                    // not have enough privileges to access SharePoint objects, so
834
835                    // we're logging in DOMAIN\SPAdmin again...
836
837                    if (NativeMethods.LogonUserA(ADMINACCOUNT, ADMINDOMAIN, ADMINPASSWORD, NativeMethods.LOGON32_LOGON_INTERACTIVE,
838
839                    NativeMethods.LOGON32_PROVIDER_DEFAULT, ref token) != 0)
840
841                    {
842
843                        if (NativeMethods.DuplicateToken(token, 2, ref tokenDuplicate) != 0)
844
845                        {
846
847                            WindowsIdentity wi = new WindowsIdentity(tokenDuplicate);
848
849                            // NOTE: Impersonate may fail if account that tries to impersonate does
850
851                            // not hold the "Impersonate after Authentication" privilege
852
853                            // See local security policy - user rights assignment.
854
855                            // Note that the ImpersonationContext from the Impersonate() call
856
857                            // is ignored. Upon the Undo() call, the original account
858
859                            // will be reinstated.
860
861                            wi.Impersonate();
862
863                        }
864
865                        else
866
867                        {
868
869                            throw new Win32Exception(Marshal.GetLastWin32Error(),
870
871                            "Impersonation: Error duplicating token after logon for user \"DOMAIN\\SPAdmin\"");
872
873                        }
874
875                    }
876
877                    else
878
879                    {
880
881                        throw new Win32Exception(Marshal.GetLastWin32Error(),
882
883                        "Impersonation: Error logging on user \"DOMAIN\\SPAdmin\"");
884
885                    }
886
887                }
888
889            }
890
891            finally
892
893            {
894
895                if (token != IntPtr.Zero)
896
897                    NativeMethods.CloseHandle(token);
898
899                if (tokenDuplicate != IntPtr.Zero)
900
901                    NativeMethods.CloseHandle(tokenDuplicate);
902
903            }
904
905        }
906
907    }
908
909    /// <summary>
910
911    /// Thanks to impersonation example of Victor Vogelpoel [Macaw] 
912
913    /// http://dotnetjunkies.com/WebLog/victorv/archive/category/2032.aspx
914
915    /// </summary>
916
917    internal sealed class NativeMethods
918
919    {
920
921        private NativeMethods() { }
922
923
924
925        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
926
927        public static extern bool CloseHandle(IntPtr handle);
928
929
930
931        public const int LOGON32_PROVIDER_DEFAULT = 0;
932
933        public const int LOGON32_LOGON_INTERACTIVE = 2;
934
935        public const int LOGON32_LOGON_NETWORK = 3;
936
937
938
939        [DllImport("advapi32.dll")]
940
941        public static extern int LogonUserA(String lpszUserName,
942
943        String lpszDomain,
944
945        String lpszPassword,
946
947        int dwLogonType,
948
949        int dwLogonProvider,
950
951        ref IntPtr phToken);
952
953
954
955        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
956
957        public static extern int DuplicateToken(IntPtr hToken,
958
959        int impersonationLevel,
960
961        ref IntPtr hNewToken);
962
963
964
965
966
967        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
968
969        public static extern bool RevertToSelf();
970
971    } 
972
973}
Notes
A request is often made to have an event handler that automagically sets the permissions on a list item so that only the author of the item can edit it, while other people with contributor permissions on the library can only read it. Please note that it is a sample code and should not be used in production environment without some major changes. For example - getting the user name and password of a user with elevated permissions on the list should be from an encrypted config file. Another example for a change is changing the logging to use a trace log. All that aside, this is still a good working example that shows some interesting things: •How to get a list item in the event handler •How to impersonate another user totaly (not using RunWithElevatedPrivilages) •How to change an item's permissions •How to create a new permission role in a web site •How to check if a role exists or not (nice trick there - can you spot it?)