user/group lookup
Stefan Schuermans

Stefan Schuermans commited on 2020-08-23 09:21:48
Showing 9 changed files, with 196 additions and 15 deletions.

... ...
@@ -2,13 +2,17 @@ add_library(
2 2
   permissioner
3 3
   STATIC
4 4
   include/permissioner/Config.h
5
+  include/permissioner/Group.h
5 6
   include/permissioner/Permissions.h
6 7
   include/permissioner/StringUtils.h
7 8
   include/permissioner/Tree.h
9
+  include/permissioner/User.h
8 10
   src/Config.cpp
11
+  src/Group.cpp
9 12
   src/Permissions.cpp
10 13
   src/StringUtils.cpp
11 14
   src/Tree.cpp
15
+  src/User.cpp
12 16
 )
13 17
 
14 18
 target_include_directories(
... ...
@@ -0,0 +1,28 @@
1
+#ifndef GROUP_H
2
+#define GROUP_H
3
+
4
+#include <boost/optional.hpp>
5
+#include <string>
6
+
7
+/// group name and ID configuration
8
+class Group {
9
+public:
10
+  /**
11
+   * @brief parse group name
12
+   * @param[in] groupNameStr group name
13
+   * @throws std::exception if something goes wrong
14
+   */
15
+  void parseGroupName(std::string const &groupNameStr);
16
+
17
+  /// return group name
18
+  boost::optional<std::string> const & getGroupName() const;
19
+
20
+  /// return group ID (or -1 if none)
21
+  int getGid() const;
22
+
23
+protected:
24
+  boost::optional<std::string> groupName;
25
+  int gid = -1;
26
+};
27
+
28
+#endif // #ifndef GROUP_H
... ...
@@ -1,10 +1,11 @@
1 1
 #ifndef TREE_H
2 2
 #define TREE_H
3 3
 
4
+#include <permissioner/Group.h>
4 5
 #include <permissioner/Permissions.h>
6
+#include <permissioner/User.h>
5 7
 
6 8
 #include <boost/filesystem.hpp>
7
-#include <boost/optional.hpp>
8 9
 #include <string>
9 10
 
10 11
 /// directory tree configuration
... ...
@@ -18,8 +19,8 @@ public:
18 19
   void parseParams(std::string const &paramStr);
19 20
 
20 21
 protected:
21
-  boost::optional<std::string> user;
22
-  boost::optional<std::string> group;
22
+  User user;
23
+  Group group;
23 24
   Permissions permissions;
24 25
   boost::filesystem::path root;
25 26
 };
... ...
@@ -0,0 +1,28 @@
1
+#ifndef USER_H
2
+#define USER_H
3
+
4
+#include <boost/optional.hpp>
5
+#include <string>
6
+
7
+/// user name and ID configuration
8
+class User {
9
+public:
10
+  /**
11
+   * @brief parse user name
12
+   * @param[in] userNameStr user name
13
+   * @throws std::exception if something goes wrong
14
+   */
15
+  void parseUserName(std::string const &userNameStr);
16
+
17
+  /// return user name
18
+  boost::optional<std::string> const & getUserName() const;
19
+
20
+  /// return user ID (or -1 if none)
21
+  int getUid() const;
22
+
23
+protected:
24
+  boost::optional<std::string> userName;
25
+  int uid = -1;
26
+};
27
+
28
+#endif // #ifndef USER_H
... ...
@@ -0,0 +1,50 @@
1
+#include <permissioner/Group.h>
2
+
3
+#include <boost/optional.hpp>
4
+#include <cerrno>
5
+#include <cstring>
6
+#include <grp.h>
7
+#include <sstream>
8
+#include <stdexcept>
9
+#include <string>
10
+#include <sys/types.h>
11
+#include <unistd.h>
12
+
13
+void Group::parseGroupName(std::string const &groupNameStr) {
14
+  if (groupNameStr == "-") {
15
+    groupName = boost::none;
16
+    gid = -1;
17
+    return;
18
+  }
19
+
20
+  long size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
21
+  if (size_max <= 0) {
22
+    std::stringstream msg;
23
+    msg << "invalid maximum size of group entry structure " << size_max;
24
+    throw std::runtime_error(msg.str());
25
+  }
26
+
27
+  struct group gr_buf, *gr;
28
+  char buf[size_max];
29
+  if (getgrnam_r(groupNameStr.c_str(), &gr_buf, buf, sizeof(buf), &gr) != 0) {
30
+    std::string err(strerror(errno));
31
+    std::stringstream msg;
32
+    msg << "looking up group name \"" << groupNameStr << "\" failed: " << err;
33
+    throw std::runtime_error(msg.str());
34
+  }
35
+  if (! gr) {
36
+    std::stringstream msg;
37
+    msg << "group name \"" << groupNameStr << "\" not found";
38
+    throw std::runtime_error(msg.str());
39
+  }
40
+
41
+  gid = gr->gr_gid;
42
+}
43
+
44
+boost::optional<std::string> const & Group::getGroupName() const {
45
+  return groupName;
46
+}
47
+
48
+int Group::getGid() const {
49
+  return gid;
50
+}
... ...
@@ -1,5 +1,7 @@
1 1
 #include <permissioner/Permissions.h>
2 2
 
3
+#include <sstream>
4
+#include <stdexcept>
3 5
 #include <string>
4 6
 
5 7
 void Permissions::parseParams(std::string const &paramStr) {
... ...
@@ -65,6 +67,13 @@ void Permissions::parseParams(std::string const &paramStr) {
65 67
     case 'X':
66 68
       whatCond |= flagExecute;
67 69
       break;
70
+    default:
71
+      {
72
+        std::stringstream msg;
73
+        msg << "invalid character \"" << c << "\" in permission string \""
74
+            << paramStr << "\"";
75
+        throw std::runtime_error(msg.str());
76
+      }
68 77
     }
69 78
   }
70 79
 }
... ...
@@ -1,10 +1,11 @@
1 1
 #include <permissioner/Tree.h>
2 2
 
3
+#include <permissioner/Group.h>
3 4
 #include <permissioner/Permissions.h>
5
+#include <permissioner/User.h>
4 6
 #include <permissioner/StringUtils.h>
5 7
 
6 8
 #include <boost/filesystem.hpp>
7
-#include <boost/optional.hpp>
8 9
 #include <sstream>
9 10
 #include <stdexcept>
10 11
 #include <string>
... ...
@@ -25,23 +26,32 @@ void Tree::parseParams(std::string const &paramStr) {
25 26
     throw std::runtime_error(msg.str());
26 27
   }
27 28
 
28
-  if (userStr == "-") {
29
-    user = boost::none;
30
-  } else {
31
-    user = userStr;
29
+  try {
30
+    user.parseUserName(userStr);
31
+  } catch (std::exception const & e) {
32
+    std::stringstream msg;
33
+    msg << "invalid <user> field \"" << userStr << "\" in \""
34
+        << paramStr << "\": " << e.what();
35
+    throw std::runtime_error(msg.str());
32 36
   }
33
-  if (groupStr == "-") {
34
-    group = boost::none;
35
-  } else {
36
-    group = groupStr;
37
+
38
+  try {
39
+    group.parseGroupName(groupStr);
40
+  } catch (std::exception const & e) {
41
+    std::stringstream msg;
42
+    msg << "invalid <group> field \"" << groupStr << "\" in \""
43
+        << paramStr << "\": " << e.what();
44
+    throw std::runtime_error(msg.str());
37 45
   }
46
+
38 47
   try {
39 48
     permissions.parseParams(permissionsStr);
40 49
   } catch (std::exception const & e) {
41 50
     std::stringstream msg;
42
-    msg << "invalid <permissions> field in \"" << paramStr << "\": "
43
-        << e.what();
51
+    msg << "invalid <permissions> field \"" << permissionsStr << "\" in \""
52
+        << paramStr << "\": " << e.what();
44 53
     throw std::runtime_error(msg.str());
45 54
   }
55
+
46 56
   root = rootStr;
47 57
 }
... ...
@@ -0,0 +1,50 @@
1
+#include <permissioner/User.h>
2
+
3
+#include <boost/optional.hpp>
4
+#include <cerrno>
5
+#include <cstring>
6
+#include <pwd.h>
7
+#include <sstream>
8
+#include <stdexcept>
9
+#include <string>
10
+#include <sys/types.h>
11
+#include <unistd.h>
12
+
13
+void User::parseUserName(std::string const &userNameStr) {
14
+  if (userNameStr == "-") {
15
+    userName = boost::none;
16
+    uid = -1;
17
+    return;
18
+  }
19
+
20
+  long size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
21
+  if (size_max <= 0) {
22
+    std::stringstream msg;
23
+    msg << "invalid maximum size of passwd entry structure " << size_max;
24
+    throw std::runtime_error(msg.str());
25
+  }
26
+
27
+  struct passwd pw_buf, *pw;
28
+  char buf[size_max];
29
+  if (getpwnam_r(userNameStr.c_str(), &pw_buf, buf, sizeof(buf), &pw) != 0) {
30
+    std::string err(strerror(errno));
31
+    std::stringstream msg;
32
+    msg << "looking up user name \"" << userNameStr << "\" failed: " << err;
33
+    throw std::runtime_error(msg.str());
34
+  }
35
+  if (! pw) {
36
+    std::stringstream msg;
37
+    msg << "user name \"" << userNameStr << "\" not found";
38
+    throw std::runtime_error(msg.str());
39
+  }
40
+
41
+  uid = pw->pw_uid;
42
+}
43
+
44
+boost::optional<std::string> const & User::getUserName() const {
45
+  return userName;
46
+}
47
+
48
+int User::getUid() const {
49
+  return uid;
50
+}
... ...
@@ -1 +1,2 @@
1
-tree myuser mygroup go+rX,go-w /some/dir
1
+tree nobody nogroup go+rX,go-w /some/dir
2
+tree - - a=rwx /some/other/dir
2 3