23a4b14e8021af739649d6c939ec09ccbad71567
[platform/core/security/security-server.git] / src / server / service / password-manager.cpp
1 /*
2  *  Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Bumjin Im <bj.im@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18 /*
19  * @file        password-manager.cpp
20  * @author      Zbigniew Jasinski (z.jasinski@samsung.com)
21  * @author      Lukasz Kostyra (l.kostyra@partner.samsung.com)
22  * @version     1.0
23  * @brief       Implementation of password management functions
24  */
25
26 #include <password-manager.h>
27
28 #include <iostream>
29 #include <iterator>
30 #include <algorithm>
31
32 #include <limits.h>
33
34 #include <dpl/log/log.h>
35
36 #include <protocols.h>
37
38 #include <security-server.h>
39
40 namespace {
41     bool calculateExpiredTime(unsigned int receivedDays, unsigned int &validSecs)
42     {
43         validSecs = 0;
44
45         if(receivedDays == 0)
46             return true;
47
48         time_t curTime = time(NULL);
49
50         if (receivedDays > ((UINT_MAX - curTime) / 86400)) {
51             LogError("Incorrect input param.");
52             return false;
53         } else {
54             validSecs = (curTime + (receivedDays * 86400));
55             return true;
56         }
57
58         //when receivedDays equal to zero, it means infinite password valid time
59         //if receivedDays is 0 return true, else return false (that is, an error)
60         return false;
61     }
62 } //namespace
63
64 namespace SecurityServer
65 {
66     int PasswordManager::isPwdValid(unsigned int &currentAttempt, unsigned int &maxAttempt,
67                                     unsigned int &expirationTime) const
68     {
69         if (m_pwdFile.isIgnorePeriod()) {
70             LogError("Retry timeout occured.");
71             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
72         }
73
74         if (!m_pwdFile.isPasswordActive()) {
75             LogError("Current password not active.");
76             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
77         } else {
78             currentAttempt = m_pwdFile.getAttempt();
79             maxAttempt = m_pwdFile.getMaxAttempt();
80             expirationTime = m_pwdFile.getExpireTimeLeft();
81
82             return SECURITY_SERVER_API_ERROR_PASSWORD_EXIST;
83         }
84
85         return SECURITY_SERVER_API_SUCCESS;
86     }
87
88     int PasswordManager::checkPassword(const std::string &challenge, unsigned int &currentAttempt,
89                                        unsigned int &maxAttempt, unsigned int &expirationTime)
90     {
91         LogSecureDebug("Inside checkPassword function.");
92
93         if (m_pwdFile.isIgnorePeriod()) {
94             LogError("Retry timeout occurred.");
95             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
96         }
97
98         if (!m_pwdFile.isPasswordActive()) {
99             LogError("Password not active.");
100             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
101         }
102
103         currentAttempt = m_pwdFile.getAttempt();
104         maxAttempt = m_pwdFile.getMaxAttempt();
105         expirationTime = m_pwdFile.getExpireTimeLeft();
106
107         if ((maxAttempt != 0) && (currentAttempt >= maxAttempt)) {
108             LogError("Too many tries.");
109             return SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
110         }
111
112         m_pwdFile.incrementAttempt();
113         m_pwdFile.writeAttemptToFile();
114
115         if (!m_pwdFile.checkPassword(challenge)) {
116             LogError("Wrong password.");
117             return SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH;
118         }
119
120         if (m_pwdFile.checkExpiration()) {
121             LogError("Password expired.");
122             return SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED;
123         }
124
125         m_pwdFile.resetAttempt();
126         m_pwdFile.writeAttemptToFile();
127
128         return SECURITY_SERVER_API_SUCCESS;
129     }
130
131     int PasswordManager::setPassword(const std::string &currentPassword,
132                                      const std::string &newPassword,
133                                      const unsigned int receivedAttempts,
134                                      const unsigned int receivedDays)
135     {
136         LogSecureDebug("Curpwd = " << currentPassword << ", newpwd = " << newPassword <<
137                        ", recatt = " << receivedAttempts << ", recdays = " << receivedDays);
138
139         unsigned int valid_secs = 0;
140
141         //check retry timer
142         if (m_pwdFile.isIgnorePeriod()) {
143             LogError("Retry timeout occured.");
144             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
145         }
146
147         //check if passwords are correct
148         if (currentPassword.size() > MAX_PASSWORD_LEN) {
149             LogError("Current password length failed.");
150             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
151         }
152
153         if (newPassword.size() > MAX_PASSWORD_LEN) {
154             LogError("New password length failed.");
155             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
156         }
157
158         //check delivered currentPassword
159         //when m_passwordActive flag is true, currentPassword shouldn't be empty
160         if (currentPassword.empty() && m_pwdFile.isPasswordActive()) {
161             LogError("Password is already set.");
162             return SECURITY_SERVER_API_ERROR_PASSWORD_EXIST;
163         }
164
165         // check attempt
166         unsigned int maxAttempt = m_pwdFile.getMaxAttempt();
167         if ((maxAttempt != 0) && (m_pwdFile.getAttempt() >= maxAttempt)) {
168             LogError("Too many attempts.");
169             return SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
170         }
171
172         //if we didn't exceed max attempts, increment attempt count and save it to separate file
173         m_pwdFile.incrementAttempt();
174         m_pwdFile.writeAttemptToFile();
175
176         //check current password, however only when we don't send empty string as current.
177         if(!currentPassword.empty()) {
178             if(!m_pwdFile.checkPassword(currentPassword)) {
179                 LogError("Wrong password.");
180                 return SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH;
181             }
182         }
183
184         //check if password expired
185         if (m_pwdFile.checkExpiration()) {
186             LogError("Password expired.");
187             return SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED;
188         }
189
190         //check history
191         if (m_pwdFile.isPasswordActive()) {
192             if (m_pwdFile.isPasswordReused(newPassword)) {
193                 LogError("Password reused.");
194                 return SECURITY_SERVER_API_ERROR_PASSWORD_REUSED;
195             }
196         }
197
198         if(!calculateExpiredTime(receivedDays, valid_secs)) {
199             LogError("Received expiration time incorrect.");
200             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
201         }
202
203         //setting password
204         m_pwdFile.setPassword(newPassword);
205         m_pwdFile.setMaxAttempt(receivedAttempts);
206         m_pwdFile.setExpireTime(valid_secs);
207         m_pwdFile.writeMemoryToFile();
208
209         m_pwdFile.resetAttempt();
210         m_pwdFile.writeAttemptToFile();
211
212         return SECURITY_SERVER_API_SUCCESS;
213     }
214
215     int PasswordManager::setPasswordValidity(const unsigned int receivedDays)
216     {
217         unsigned int valid_secs = 0;
218
219         LogSecureDebug("received_days: " << receivedDays);
220
221         if (!m_pwdFile.isPasswordActive()) {
222             LogError("Current password is not active.");
223             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
224         }
225
226         if(!calculateExpiredTime(receivedDays, valid_secs))
227             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
228
229         m_pwdFile.setExpireTime(valid_secs);
230         m_pwdFile.writeMemoryToFile();
231
232         return SECURITY_SERVER_API_SUCCESS;
233     }
234
235     int PasswordManager::resetPassword(const std::string &newPassword,
236                                        const unsigned int receivedAttempts,
237                                        const unsigned int receivedDays)
238     {
239         unsigned int valid_secs = 0;
240
241         if (m_pwdFile.isIgnorePeriod()) {
242             LogError("Retry timeout occured.");
243             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
244         }
245
246         if(!calculateExpiredTime(receivedDays, valid_secs))
247             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
248
249         m_pwdFile.setPassword(newPassword);
250         m_pwdFile.setMaxAttempt(receivedAttempts);
251         m_pwdFile.setExpireTime(valid_secs);
252         m_pwdFile.writeMemoryToFile();
253
254         m_pwdFile.resetAttempt();
255         m_pwdFile.writeAttemptToFile();
256
257         return SECURITY_SERVER_API_SUCCESS;
258     }
259
260     int PasswordManager::setPasswordHistory(const unsigned int history)
261     {
262         if(history > MAX_PASSWORD_HISTORY) {
263             LogError("Incorrect input param.");
264             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
265         }
266
267         // check retry time
268         if (m_pwdFile.isIgnorePeriod()) {
269             LogError("Retry timeout occurred.");
270             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
271         }
272
273         m_pwdFile.setHistory(history);
274         m_pwdFile.writeMemoryToFile();
275
276         return SECURITY_SERVER_API_SUCCESS;
277     }
278
279     int PasswordManager::setPasswordMaxChallenge(const unsigned int maxChallenge)
280     {
281         // check if there is password
282         if (!m_pwdFile.isPasswordActive()) {
283             LogError("Password not active.");
284             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
285         }
286
287         m_pwdFile.setMaxAttempt(maxChallenge);
288         m_pwdFile.writeMemoryToFile();
289
290         m_pwdFile.resetAttempt();
291         m_pwdFile.writeAttemptToFile();
292
293         return SECURITY_SERVER_API_SUCCESS;
294     }
295 } //namespace SecurityServer