1、一些相关概念
在Windows NT/XP下的对象,不一定是文件系统,还有其它的一些对象,如:进程、命名管道、打印机、网络共享、或是注册表等等,都可以设置用户访问权限。在 Windows系统中,其是用一个安全描述符(Security Descriptors)的结构来保存其权限的设置信息,简称为SD,其在Windows SDK中的结构名是“SECURITY_DESCRIPTOR”,这是包括了安全设置信息的结构体。一个安全描述符包含以下信息:
一个安全标识符(Security identifiers),其标识了该信息是哪个对象的,也就是用于记录安全对象的ID。简称为:SID。
一个DACL(Discretionary Access Control List),其指出了允许和拒绝某用户或用户组的存取控制列表。当一个进程需要访问安全对象,系统就会检查DACL来决定进程的访问权。如果一个对象没有 DACL,那么就是说这个对象是任何人都可以拥有完全的访问权限。
一个SACL(System Access Control List),其指出了在该对象上的一组存取方式(如,读、写、运行等)的存取控制权限细节的列表。
DACL和SACL构成了整个存取控制列表Access Control List,简称ACL,ACL中的每一项,我们叫做ACE(Access Control Entry),ACL中的每一个ACE。
我们的程序不用直接维护SD这个结构,这个结构由系统维护。我们只用使用Windows 提供的相关的API函数来取得并设置SD中的信息就行了。不过这些API函数只有Windows NT/XP才支持。
安全对象Securable Object是拥有SD的Windows的对象。所有的被命名的Windows的对象都是安全对象。一些没有命名的对象是安全对象,如:进程和线程,也有安全描述符SD。在对大多数的创建安全对象的操作中都需要你传递一个SD的参数,如:CreateFile和CreateProcess函数。另外,Windows还提供了一系列有关安全对象的安全信息的存取函数,以供你取得对象上的安全设置,或修改对象上的安全设置。如:GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo。
2、SID的设置(obsolete)
http://msdn.microsoft.com/en-us/library/aa379597(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa379649(VS.85).aspx
http://www.reddragonfly.org/ntfs/attributes/security_descriptor.html
3、涉及的一些API
AddAccessDeniedAce Function
The AddAccessDeniedAce function adds an access-denied access control entry (ACE) to an access control list (ACL). The access is denied to a specified security identifier (SID).
http://msdn.microsoft.com/en-us/library/aa374962(VS.85).aspx
InitializeSecurityDescriptor Function
The InitializeSecurityDescriptor function initializes a new security descriptor.
http://msdn.microsoft.com/en-us/library/aa378863(VS.85).aspx
AllocateAndInitializeSid Function
The AllocateAndInitializeSid function allocates and initializes a security identifier (SID) with up to eight subauthorities.
http://msdn.microsoft.com/en-us/library/aa375213(VS.85).aspx
系统会按照顺序依次检查所有的ACE规则,如下面的条件满足,则退出:
1)、如果一个Access-Denied的ACE明显地拒绝了请求者。
2)、如果某Access-Allowed的ACE明显地同意了请求者。
3)、全部的ACE都检查完了,但是没有一条ACE明显地允许或是拒绝请求者,那么系统将使用默认值,拒绝请求者的访问。
4、如何向文件添加允许访问的 ACE
[1] http://support.microsoft.com/kb/102102
[2] http://www.lihuasoft.net/article/list.php?frmid=52
5、权限控制是如何提出来的
由于Share and Storage Management的发展而提出来。
6、共享管理
Windows操作系统下NTFS和FAT32文件格式在文件共享,读写权限设置方面的区别,简单点说就是:
1). NTFS文件系统自身可以设置文件和文件夹的读写访问权限,而FAT32文件系统则不具备这样的功能;
2). NTFS文件系统的读写访问控制对于本地用户访问以及通过文件夹共享的网络访问均有效;
3). 文件夹共享也有自己的访问权限设置,但这种访问控制机制仅对网络访问有效,对本地用户访问不起作用;
4). 如果共享的文件夹在NTFS分区,则网络访问同时受到共享权限设置和NTFS文件系统权限设置的控制,最终的约束结果为两者中较严格的那一项约束。
更具体的信息请参考:
1)实现共享
1. 调用API函数NetShareAdd()将文件夹设置为共享,调用此函数后如果不做其他设置,网络用户是无法访问共享文件夹的,因为此文件夹在NTFS分区中,同时受到NTFS文件系统的访问控制,因此还需要第2步;
2. 调用DOS命令cacls,赋予Guest用户组读写权限;
Cacls 显示或者修改文件的访问控制表(ACL)
http://support.microsoft.com/kb/318754/
3. 如果要取消文件共享,直接调用API函数NetShareDel()。[6]
MSDN这一部分专题:
http://msdn.microsoft.com/en-us/library/bb525380%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb525391%28VS.85%29.aspx
示例代码
1 #include <windows.h>
2 #include <stdio.h>
3 #include <lm.h>
4 #pragma comment(lib, "Netapi32.lib")
5 #pragma comment(lib, "Advapi32.lib")
6
7 void NetShare(TCHAR *argv[]){
8 NET_API_STATUS res;
9 SHARE_INFO_2 p;
10 DWORD parm_err = 0;
11 //
12 // Fill in the SHARE_INFO_2 structure.
13 //
14 p.shi2_netname = (LMSTR)argv[1];
15 p.shi2_type = STYPE_DISKTREE; // disk drive
16 p.shi2_remark = (LMSTR)argv[1];
17 p.shi2_permissions = ACCESS_ALL;
18 p.shi2_max_uses = 4;
19 p.shi2_current_uses = 0;
20 p.shi2_path = (LMSTR)argv[2];
21 p.shi2_passwd = NULL; // no password
22 //
23 // Call the NetShareAdd function,
24 // specifying level 2.
25 //
26 res=NetShareAdd(NULL, 2, (LPBYTE) &p, &parm_err);
27 //
28 // If the call succeeds, inform the user.
29 //
30 switch(res){
31 case 0:
32 printf("Share created.\n");
33 break;
34 case ERROR_ACCESS_DENIED:
35 printf("The user does not have access to the requested information..\n");
36 break;
37 case ERROR_INVALID_LEVEL:
38 printf("The value specified for the level parameter is not valid...\n");
39 break;
40 case ERROR_INVALID_NAME:
41 printf("The character or file system name is not valid...\n");
42 break;
43 case ERROR_INVALID_PARAMETER:
44 printf("The specified parameter is not valid..\n");
45 break;
46 case NERR_DuplicateShare:
47 printf("The share name is already in use on this server...\n");
48 break;
49 case NERR_RedirectedPath:
50 printf("The operation is not valid for a redirected resource. The specified device name is assigned to a shared resource...\n");
51 break;
52 case NERR_UnknownDevDir:
53 printf("The device or directory does not exist..\n");
54 break;
55 default:
56 printf("Unknown Error: %u\tparmerr=%u\n", res, parm_err);
57 break;
58 }//switch
59 }
60
61 void NetDel(TCHAR *argv[]){
62 NET_API_STATUS res;
63 DWORD parm_err = 0;
64 TCHAR *p = argv[1];
65 res=NetShareDel(NULL, (LPSTR)p, 0);
66 //
67 // Display the result of the call.
68 //
69 switch(res){
70 case 0:
71 printf("Share Removed.\n");
72 break;
73 case ERROR_INVALID_PARAMETER:
74 printf("The specified parameter is not valid.\n");
75 break;
76 case ERROR_ACCESS_DENIED:
77 printf("The user does not have access to the requested information.\n");
78 break;
79 case ERROR_NOT_ENOUGH_MEMORY:
80 printf("Insufficient memory is available.\n");
81 break;
82 case NERR_NetNameNotFound:
83 printf("The share name does not exist...\n");
84 break;
85 default:
86 printf("Unknown Error: %u\n", res);
87 break;
88 }//switch
89 }
90 void NetEnum()
91 {
92 PSHARE_INFO_502 BufPtr,p;
93 NET_API_STATUS res;
94 LPSTR lpszServer = NULL;
95 DWORD er=0,tr=0,resume=0, i;
96
97 printf("Share: Local Path: Uses: Descriptor:\n");
98 printf("---------------------------------------------------------------------\n");
99 //
100 // Call the NetShareEnum function; specify level 502.
101 //
102 do // begin do
103 {
104 res = NetShareEnum (lpszServer, 502, (LPBYTE *) &BufPtr, -1, &er, &tr, &resume);
105 //
106 // If the call succeeds,
107 //
108 if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
109 p=BufPtr;
110 //
111 // Loop through the entries;
112 // print retrieved data.
113 //
114 for (i = 1; i <= er; i++)
115 {
116 printf("%-20S%-30S%-8u",p->shi502_netname, p->shi502_path, p->shi502_current_uses);
117 //
118 // Validate the value of the
119 // shi502_security_descriptor member.
120 //
121 if (IsValidSecurityDescriptor(p->shi502_security_descriptor))
122 printf("Yes\n");
123 else
124 printf("No\n");
125 p++;
126 }
127 //
128 // Free the allocated buffer.
129 //
130 NetApiBufferFree(BufPtr);
131 }
132 else
133 printf("Error: %ld\n",res);
134 }
135 // Continue to call NetShareEnum while
136 // there are more entries.
137 //
138 while (res==ERROR_MORE_DATA); // end do
139
140 }
141
142 void NetGetInfo(TCHAR *argv[]){
143 PSHARE_INFO_502 BufPtr;
144 NET_API_STATUS res;
145 LPSTR lpszServer = NULL, lpszShare;
146 lpszShare = (LPSTR)argv[1];
147 res = NetShareGetInfo (lpszServer,lpszShare,502,(LPBYTE *) &BufPtr);
148 switch(res){
149 case ERROR_SUCCESS:
150 {
151 printf("%S\t%S\t%u\n",BufPtr->shi502_netname, BufPtr->shi502_path, BufPtr->shi502_current_uses);
152 //
153 // Validate the value of the
154 // shi502_security_descriptor member.
155 //
156 if (IsValidSecurityDescriptor(BufPtr->shi502_security_descriptor))
157 printf("It has a valid Security Descriptor.\n");
158 else
159 printf("It does not have a valid Security Descriptor.\n");
160 //
161 // Free the allocated memory.
162 //
163 NetApiBufferFree(BufPtr);
164 }//case
165 break;
166 case ERROR_ACCESS_DENIED:
167 printf("The user does not have access to the requested information..\n");
168 break;
169 case ERROR_INVALID_LEVEL:
170 printf("The value specified for the level parameter is not valid...\n");
171 break;
172 case ERROR_INVALID_PARAMETER:
173 printf("The specified parameter is not valid..\n");
174 break;
175 case NERR_NetNameNotFound:
176 printf("The share name does not exist..\n");
177 break;
178 default:
179 printf("Unknown Error: %ld\n",res);
180 }//switch
181 }
182
183 void wmain( int argc, TCHAR *argv[])
184 {
185 printf("the moduler provides the following function:\n");
186 printf("Press 1 to enter netshare.\n");
187 printf("Press 2 to enter netdel.\n");
188 printf("Press 3 to retrieve all share information.\n");
189 printf("Press 4 to retrieve appointed share information.\n");
190
191 int flag = 0;
192 scanf_s("%d", &flag);
193 switch(flag){
194 case 1:
195 printf("Usage: *.exe NetName(共享名) Path(共享路径)\n");
196
197 if(argc < 3)
198 printf("Format error;\n should be like this: Usage: *.exe NetName(共享名) Path(共享路径)\n");
199 else NetShare(argv);
200 break;
201 case 2:
202 printf("Usage: *.exe NetName(共享名)\n");
203
204 if(argc < 3)
205 printf("Format error;\n should be like this: Usage: *.exe NetName(共享名)\n");
206 else NetDel(argv);
207 break;
208 case 3:
209 printf("Usage: *.exe\n");
210 NetEnum();
211 break;
212 case 4:
213 printf("Usage: *.exe NetName(共享名)\n");
214 NetGetInfo(argv);
215 break;
216 default:
217 break;
218 }//switch
219 return;
220 }
其它参考
[1] http://msdn.microsoft.com/en-us/library/aa385413%28VS.85%29.aspx
[2] http://msdn.microsoft.com/en-us/library/aa385353%28VS.85%29.aspx
[3] http://msdn.microsoft.com/en-us/library/aa446627%28VS.85%29.aspx
[4] http://msdn.microsoft.com/en-us/library/aa379636%28VS.85%29.aspx
[5] http://www.cnblogs.com/wdhust/archive/2008/08/09/1264388.html
[6] http://msdn.microsoft.com/en-us/library/bb525410%28VS.85%29.aspx
[7] http://msdn.microsoft.com/en-us/library/aa379570%28VS.85%29.aspx
[8] http://msdn.microsoft.com/en-us/library/aa379566%28VS.85%29.aspx
[9] http://msdn.microsoft.com/en-us/library/aa379602%28VS.85%29.aspx
[10] http://msdn.microsoft.com/en-us/library/ms717798%28VS.85%29.aspx
[11] http://msdn.microsoft.com/en-us/library/ms717798%28VS.85%29.aspx
[12] http://msdn.microsoft.com/en-us/library/aa379560%28VS.85%29.aspx
[13] http://msdn.microsoft.com/en-us/library/aa374931%28VS.85%29.aspx
[14] http://msdn.microsoft.com/en-us/library/aa374962%28VS.85%29.aspx
[15] Acess mask:
http://msdn.microsoft.com/en-us/library/aa374892%28VS.85%29.aspx
[16] Access mask format:
http://msdn.microsoft.com/en-us/library/aa374896%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa446683%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa379637%28VS.85%29.aspx
[17] 网络访问控制
http://msdn.microsoft.com/en-us/library/bb720817.aspx
[18] windows提供的一个命令行工具cacls来设置,需要说明的是:用这个命令所设置的是本地的安全权限,不是NTFS权限
http://support.microsoft.com/kb/162786
[19] 关于system函数:
http://msdn.microsoft.com/en-us/library/277bwbdz%28VS.71%29.aspx
[20] 配额管理
http://msdn.microsoft.com/en-us/library/bb870630%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb613280%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb613277%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb625490%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb625507%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb625488%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb870619%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb870623%28VS.85%29.aspx
[21] COM库的两个基础函数
http://msdn.microsoft.com/en-us/library/ms695279%28VS.85%29.aspx
这个函数是通过CLSID用来创建一个单例的未初始化的对象。
http://msdn.microsoft.com/en-us/library/bb613280%28VS.85%29.aspx#methods
http://msdn.microsoft.com/en-us/library/ms686615%28VS.85%29.aspx