summaryrefslogtreecommitdiffstats
path: root/user.hpp
blob: 44dd3a3de8848a987fd4a60ebb8e2004ad68419d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once

#include <cstring>
#include <experimental/filesystem>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <xyz/openbmc_project/User/Password/server.hpp>
namespace phosphor
{
namespace user
{

using CryptAlgo = std::string;

namespace fs = std::experimental::filesystem;
namespace Base = sdbusplus::xyz::openbmc_project::User::server;
using Interface = sdbusplus::server::object::object<Base::Password>;

/** @class User
 *  @brief Responsible for managing a specific user account.
 *         It is implementing just the Password interface
 *         for now.
 */
class User : public Interface
{
    public:
        User() = delete;
        ~User() = default;
        User(const User&) = delete;
        User& operator=(const User&) = delete;
        User(User&&) = delete;
        User& operator=(User&&) = delete;

        /** @brief Constructs User object.
         *
         *  @param[in] bus  - sdbusplus handler
         *  @param[in] path - D-Bus path
         */
        User(sdbusplus::bus::bus& bus, const char* path)
            : Interface(bus, path),
              bus(bus),
              path(path),
              user(fs::path(path).filename())
        {
            // Do nothing
        }

        /** @brief user password set method. If this is called for
         *         a user ID that already has the password, the password
         *         would be updated, else password would be created.
         *         Since this needs an already authenticated session,
         *         old password is not needed.
         *
         *  @param[in] newPassword - New password
         */
        void setPassword(std::string newPassword) override;

    private:
        /** @brief sdbusplus handler */
        sdbusplus::bus::bus& bus;

        /** @brief object path */
        const std::string& path;

        /** @brief User id extracted from object path */
        const std::string user;

        /** @brief Returns a random string from set [A-Za-z0-9./]
         *         of length size
         *
         *  @param[in] numChars - length of string
         */
        static const std::string randomString(int length);

        /** @brief Returns password hash created with crypt algo,
         *         salt and password
         *
         *  @param[in] spPwdp   - sp_pwdp of struct spwd
         *  @param[in] password - clear text password
         *  @param[in] salt     - Random salt
         */
        std::string hashPassword(char* spPwdp,
                                 const std::string& password,
                                 const std::string& salt);

        /** @brief Extracts crypto number from the shadow entry for user
         *
         *  @param[in] spPwdp - sp_pwdp of struct spwd
         */
        static CryptAlgo getCryptField(char* spPwdp);

        /** @brief Generates one-way hash based on salt and password
         *
         *  @param[in] password - clear text password
         *  @param[in] salt     - Combination of crypto method and salt
         *                        Eg: $1$HELLO$, where in 1 is crypto method
         *                        and HELLO is salt
         */
        static std::string generateHash(const std::string& password,
                                        const std::string& salt);

        /** @brief Returns salt string with $ delimiter.
         *         Eg: If crypt is 1 and salt is HELLO, returns $1$HELLO$
         *
         *  @param[in] crypt - Crypt number in string
         *  @param[in] salt  - salt
         */
        static std::string getSaltString(const std::string& crypt,
                                         const std::string& salt);

        /** @brief Applies the password for a given user.
         *         Writes shadow entries into a temp file
         *
         *  @param[in] shadowFile - shadow password file
         *  @param[in] tempFile   - Temporary file
         *  @param[in] password   - clear text password
         *  @param[in] salt       - salt
         */
        void applyPassword(const std::string& shadowFile,
                           const std::string& tempFile,
                           const std::string& password,
                           const std::string& salt);

        /** @brief Wrapper for raising exception
         *
         *  @param[in] errNo  - errno
         *  @param[in] errMsg - Error message
         */
        void raiseException(int errNo,
                            const std::string& errMsg);
};

} // namespace user
} // namespace phosphor
OpenPOWER on IntegriCloud