1
2
3
4
5
6 using System;
7 using System.IO;
8 using System.Collections;
9
10 namespace System.Security
11 {
12 public class SecurityException : Exception
13 {
14 public nothrow SecurityException(const string& message_) : base(message_)
15 {
16 }
17 }
18
19 public class User
20 {
21 public nothrow User(const string& username_, bool hasPassword_, int uid_, int gid_, const string& info_, const string& home_, const string& shell_) :
22 username(username_), hasPassword(hasPassword_), uid(uid_), gid(gid_), info(info_), home(home_), shell(shell_)
23 {
24 }
25 public inline nothrow const string& Name() const
26 {
27 return username;
28 }
29 public inline nothrow bool HasPassword() const
30 {
31 return hasPassword;
32 }
33 public nothrow void SetHasPassword(bool hasPassword_)
34 {
35 hasPassword = hasPassword_;
36 }
37 public inline nothrow int UID() const
38 {
39 return uid;
40 }
41 public inline nothrow int GID() const
42 {
43 return gid;
44 }
45 public inline nothrow const string& Info() const
46 {
47 return info;
48 }
49 public inline nothrow const string& Home() const
50 {
51 return home;
52 }
53 public inline nothrow const string& Shell() const
54 {
55 return shell;
56 }
57 public void Write(StreamWriter& writer)
58 {
59 string hpwd;
60 if (hasPassword)
61 {
62 hpwd = "x";
63 }
64 writer << username << ":" << hpwd << ":" << uid << ":" << gid << ":" << info << ":" << home << ":" << shell << endl();
65 }
66 private string username;
67 private bool hasPassword;
68 private int uid;
69 private int gid;
70 private string info;
71 private string home;
72 private string shell;
73 }
74
75 public class Users
76 {
77 public nothrow Users() : lastUserId(0)
78 {
79 }
80 public void AddUser(const User& user)
81 {
82 users.Add(user);
83 if (user.UID() > lastUserId)
84 {
85 lastUserId = user.UID();
86 }
87 }
88 public void RemoveUser(User* user)
89 {
90 int index = -1;
91 int n = cast<int>(users.Count());
92 for (int i = 0; i < n; ++i;)
93 {
94 const User& usr = users[i];
95 if (usr.UID() == user->UID())
96 {
97 index = i;
98 break;
99 }
100 }
101 if (index != -1)
102 {
103 users.Remove(users.Begin() + index);
104 }
105 }
106 public User* GetUser(int uid) const
107 {
108 Map<int, User*>.ConstIterator it = uidUserMap.CFind(uid);
109 if (it != uidUserMap.CEnd())
110 {
111 return it->second;
112 }
113 else
114 {
115 return null;
116 }
117 }
118 public User* GetUser(const string& userName) const
119 {
120 Map<string, User*>.ConstIterator it = userNameUserMap.CFind(userName);
121 if (it != userNameUserMap.CEnd())
122 {
123 return it->second;
124 }
125 else
126 {
127 return null;
128 }
129 }
130 public void Finalize()
131 {
132 for (User& user : users)
133 {
134 uidUserMap[user.UID()] = &user;
135 userNameUserMap[user.Name()] = &user;
136 }
137 }
138 public void Write(StreamWriter& writer)
139 {
140 for (const User& user : users)
141 {
142 user.Write(writer);
143 }
144 }
145 public nothrow int GetFreeUserId() const
146 {
147 return lastUserId + 1;
148 }
149 private List<User> users;
150 private Map<int, User*> uidUserMap;
151 private Map<string, User*> userNameUserMap;
152 private int lastUserId;
153 }
154
155 public class Group
156 {
157 public nothrow Group(const string& groupname_, int gid_, const List<string>& users_) :
158 groupname(groupname_), gid(gid_), users(users_)
159 {
160 }
161 public inline nothrow const string& Name() const
162 {
163 return groupname;
164 }
165 public inline nothrow int GID() const
166 {
167 return gid;
168 }
169 public void Write(StreamWriter& writer)
170 {
171 writer << groupname << ":" << gid << ":" << ToCsv(users) << endl();
172 }
173 public inline nothrow const List<string>& Users() const
174 {
175 return users;
176 }
177 public void AddUser(const string& userName)
178 {
179 users.Add(userName);
180 }
181 private string groupname;
182 private int gid;
183 private List<string> users;
184 }
185
186 public class Groups
187 {
188 public nothrow Groups() : lastGroupId(0)
189 {
190 }
191 public void AddGroup(const Group& group)
192 {
193 groups.Add(group);
194 if (group.GID() > lastGroupId)
195 {
196 lastGroupId = group.GID();
197 }
198 }
199 public Group* GetGroup(int gid) const
200 {
201 Map<int, Group*>.ConstIterator it = gidGroupMap.CFind(gid);
202 if (it != gidGroupMap.CEnd())
203 {
204 return it->second;
205 }
206 else
207 {
208 return null;
209 }
210 }
211 public void Finalize()
212 {
213 for (Group& group : groups)
214 {
215 gidGroupMap[group.GID()] = &group;
216 }
217 }
218 public void Write(StreamWriter& writer)
219 {
220 for (const Group& group : groups)
221 {
222 group.Write(writer);
223 }
224 }
225 public nothrow int GetFreeGroupId() const
226 {
227 return lastGroupId + 1;
228 }
229 private List<Group> groups;
230 private Map<int, Group*> gidGroupMap;
231 private int lastGroupId;
232 }
233
234 public User GetUser(int uid)
235 {
236 StreamReader reader = File.OpenRead("/etc/passwd");
237 int lineNumber = 0;
238 while (!reader.EndOfStream())
239 {
240 string line = reader.ReadLine();
241 if (!line.IsEmpty() && !line.StartsWith("#"))
242 {
243 List<string> fields = line.Split(':');
244 if (fields.Count() != 7)
245 {
246 throw SecurityException("invalid line " + ToString(lineNumber) + " in /etc/passwd: wrong number of fields (" + ToString(fields.Count()) + "), should be 7.");
247 }
248 User user(fields[0], fields[1] == "x", ParseInt(fields[2]), ParseInt(fields[3]), fields[4], fields[5], fields[6]);
249 if (user.UID() == uid)
250 {
251 return user;
252 }
253 }
254 ++lineNumber;
255 }
256 throw SecurityException("no matching user account for UID " + ToString(uid) + " found from /etc/passwd");
257 }
258
259 public Users GetUsers()
260 {
261 Users users;
262 StreamReader reader = File.OpenRead("/etc/passwd");
263 int lineNumber = 0;
264 while (!reader.EndOfStream())
265 {
266 string line = reader.ReadLine();
267 if (!line.IsEmpty() && !line.StartsWith("#"))
268 {
269 List<string> fields = line.Split(':');
270 if (fields.Count() != 7)
271 {
272 throw SecurityException("invalid line " + ToString(lineNumber) + " in /etc/passwd: wrong number of fields (" + ToString(fields.Count()) + "), should be 7.");
273 }
274 User user(fields[0], fields[1] == "x", ParseInt(fields[2]), ParseInt(fields[3]), fields[4], fields[5], fields[6]);
275 users.AddUser(user);
276 }
277 ++lineNumber;
278 }
279 users.Finalize();
280 return users;
281 }
282
283 public void WriteUsers(const Users& users)
284 {
285 StreamWriter writer = File.CreateText("/etc/passwd");
286 users.Write(writer);
287 }
288
289 public Group GetGroup(int gid)
290 {
291 StreamReader reader = File.OpenRead("/etc/group");
292 int lineNumber = 0;
293 while (!reader.EndOfStream())
294 {
295 string line = reader.ReadLine();
296 if (!line.IsEmpty() && !line.StartsWith("#"))
297 {
298 List<string> fields = line.Split(':');
299 if (fields.Count() != 3)
300 {
301 throw SecurityException("invalid line " + ToString(lineNumber) + " in /etc/group: wrong number of fields (" + ToString(fields.Count()) + "), should be 3.");
302 }
303 Group group(fields[0], ParseInt(fields[1]), ParseCSV(fields[2]));
304 if (group.GID() == gid)
305 {
306 return group;
307 }
308 }
309 ++lineNumber;
310 }
311 throw SecurityException("no matching group for GID " + ToString(gid) + " found from /etc/group");
312 }
313
314 public Groups GetGroups()
315 {
316 Groups groups;
317 StreamReader reader = File.OpenRead("/etc/group");
318 int lineNumber = 0;
319 while (!reader.EndOfStream())
320 {
321 string line = reader.ReadLine();
322 if (!line.IsEmpty() && !line.StartsWith("#"))
323 {
324 List<string> fields = line.Split(':');
325 if (fields.Count() != 3)
326 {
327 throw SecurityException("invalid line " + ToString(lineNumber) + " in /etc/group: wrong number of fields (" + ToString(fields.Count()) + "), should be 3.");
328 }
329 Group group(fields[0], ParseInt(fields[1]), ParseCSV(fields[2]));
330 groups.AddGroup(group);
331 }
332 ++lineNumber;
333 }
334 groups.Finalize();
335 return groups;
336 }
337
338 public void WriteGroups(const Groups& groups)
339 {
340 StreamWriter writer = File.CreateText("/etc/group");
341 groups.Write(writer);
342 }
343 }