Add new constants to password service. Change infinite expiration time.
[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 = SecurityServer::PASSWORD_INFINITE_EXPIRATION_TIME;
44
45         //when receivedDays means infinite expiration, return default validSecs value.
46         if(receivedDays == SecurityServer::PASSWORD_INFINITE_EXPIRATION_DAYS)
47             return true;
48
49         time_t curTime = time(NULL);
50
51         if (receivedDays > ((UINT_MAX - curTime) / 86400)) {
52             LogError("Incorrect input param.");
53             return false;
54         } else {
55             validSecs = (curTime + (receivedDays * 86400));
56             return true;
57         }
58     }
59 } //namespace
60
61 namespace SecurityServer
62 {
63     int PasswordManager::isPwdValid(unsigned int &currentAttempt, unsigned int &maxAttempt,
64                                     unsigned int &expirationTime) const
65     {
66         if (m_pwdFile.isIgnorePeriod()) {
67             LogError("Retry timeout occured.");
68             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
69         }
70
71         if (!m_pwdFile.isPasswordActive()) {
72             LogError("Current password not active.");
73             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
74         } else {
75             currentAttempt = m_pwdFile.getAttempt();
76             maxAttempt = m_pwdFile.getMaxAttempt();
77             expirationTime = m_pwdFile.getExpireTimeLeft();
78
79             return SECURITY_SERVER_API_ERROR_PASSWORD_EXIST;
80         }
81
82         return SECURITY_SERVER_API_SUCCESS;
83     }
84
85     int PasswordManager::checkPassword(const std::string &challenge, unsigned int &currentAttempt,
86                                        unsigned int &maxAttempt, unsigned int &expirationTime)
87     {
88         LogSecureDebug("Inside checkPassword function.");
89
90         if (m_pwdFile.isIgnorePeriod()) {
91             LogError("Retry timeout occurred.");
92             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
93         }
94
95         if (!m_pwdFile.isPasswordActive()) {
96             LogError("Password not active.");
97             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
98         }
99
100         currentAttempt = m_pwdFile.getAttempt();
101         maxAttempt = m_pwdFile.getMaxAttempt();
102         expirationTime = m_pwdFile.getExpireTimeLeft();
103
104         if (m_pwdFile.checkIfAttemptsExceeded()) {
105             LogError("Too many tries.");
106             return SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
107         }
108
109         m_pwdFile.incrementAttempt();
110         m_pwdFile.writeAttemptToFile();
111
112         if (!m_pwdFile.checkPassword(challenge)) {
113             LogError("Wrong password.");
114             return SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH;
115         }
116
117         if (m_pwdFile.checkExpiration()) {
118             LogError("Password expired.");
119             return SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED;
120         }
121
122         m_pwdFile.resetAttempt();
123         m_pwdFile.writeAttemptToFile();
124
125         return SECURITY_SERVER_API_SUCCESS;
126     }
127
128     int PasswordManager::setPassword(const std::string &currentPassword,
129                                      const std::string &newPassword,
130                                      const unsigned int receivedAttempts,
131                                      const unsigned int receivedDays)
132     {
133         LogSecureDebug("Curpwd = " << currentPassword << ", newpwd = " << newPassword <<
134                        ", recatt = " << receivedAttempts << ", recdays = " << receivedDays);
135
136         unsigned int valid_secs = 0;
137
138         //check retry timer
139         if (m_pwdFile.isIgnorePeriod()) {
140             LogError("Retry timeout occured.");
141             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
142         }
143
144         //check if passwords are correct
145         if (currentPassword.size() > MAX_PASSWORD_LEN) {
146             LogError("Current password length failed.");
147             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
148         }
149
150         if (newPassword.size() > MAX_PASSWORD_LEN) {
151             LogError("New password length failed.");
152             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
153         }
154
155         //check delivered currentPassword
156         //when m_passwordActive flag is true, currentPassword shouldn't be empty
157         if (currentPassword.empty() && m_pwdFile.isPasswordActive()) {
158             LogError("Password is already set.");
159             return SECURITY_SERVER_API_ERROR_PASSWORD_EXIST;
160         }
161
162         // check attempt
163         if (m_pwdFile.checkIfAttemptsExceeded()) {
164             LogError("Too many attempts.");
165             return SECURITY_SERVER_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED;
166         }
167
168         //if we didn't exceed max attempts, increment attempt count and save it to separate file
169         m_pwdFile.incrementAttempt();
170         m_pwdFile.writeAttemptToFile();
171
172         //check current password, however only when we don't send empty string as current.
173         if(!currentPassword.empty()) {
174             if(!m_pwdFile.checkPassword(currentPassword)) {
175                 LogError("Wrong password.");
176                 return SECURITY_SERVER_API_ERROR_PASSWORD_MISMATCH;
177             }
178         }
179
180         //check if password expired
181         if (m_pwdFile.checkExpiration()) {
182             LogError("Password expired.");
183             return SECURITY_SERVER_API_ERROR_PASSWORD_EXPIRED;
184         }
185
186         //check history
187         if (m_pwdFile.isPasswordActive()) {
188             if (m_pwdFile.isPasswordReused(newPassword)) {
189                 LogError("Password reused.");
190                 return SECURITY_SERVER_API_ERROR_PASSWORD_REUSED;
191             }
192         }
193
194         if(!calculateExpiredTime(receivedDays, valid_secs)) {
195             LogError("Received expiration time incorrect.");
196             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
197         }
198
199         //setting password
200         m_pwdFile.setPassword(newPassword);
201         m_pwdFile.setMaxAttempt(receivedAttempts);
202         m_pwdFile.setExpireTime(valid_secs);
203         m_pwdFile.writeMemoryToFile();
204
205         m_pwdFile.resetAttempt();
206         m_pwdFile.writeAttemptToFile();
207
208         return SECURITY_SERVER_API_SUCCESS;
209     }
210
211     int PasswordManager::setPasswordValidity(const unsigned int receivedDays)
212     {
213         unsigned int valid_secs = 0;
214
215         LogSecureDebug("received_days: " << receivedDays);
216
217         if (!m_pwdFile.isPasswordActive()) {
218             LogError("Current password is not active.");
219             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
220         }
221
222         if(!calculateExpiredTime(receivedDays, valid_secs))
223             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
224
225         m_pwdFile.setExpireTime(valid_secs);
226         m_pwdFile.writeMemoryToFile();
227
228         return SECURITY_SERVER_API_SUCCESS;
229     }
230
231     int PasswordManager::resetPassword(const std::string &newPassword,
232                                        const unsigned int receivedAttempts,
233                                        const unsigned int receivedDays)
234     {
235         unsigned int valid_secs = 0;
236
237         if (m_pwdFile.isIgnorePeriod()) {
238             LogError("Retry timeout occured.");
239             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
240         }
241
242         if(!calculateExpiredTime(receivedDays, valid_secs))
243             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
244
245         m_pwdFile.setPassword(newPassword);
246         m_pwdFile.setMaxAttempt(receivedAttempts);
247         m_pwdFile.setExpireTime(valid_secs);
248         m_pwdFile.writeMemoryToFile();
249
250         m_pwdFile.resetAttempt();
251         m_pwdFile.writeAttemptToFile();
252
253         return SECURITY_SERVER_API_SUCCESS;
254     }
255
256     int PasswordManager::setPasswordHistory(const unsigned int history)
257     {
258         if(history > MAX_PASSWORD_HISTORY) {
259             LogError("Incorrect input param.");
260             return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
261         }
262
263         // check retry time
264         if (m_pwdFile.isIgnorePeriod()) {
265             LogError("Retry timeout occurred.");
266             return SECURITY_SERVER_API_ERROR_PASSWORD_RETRY_TIMER;
267         }
268
269         m_pwdFile.setHistory(history);
270         m_pwdFile.writeMemoryToFile();
271
272         return SECURITY_SERVER_API_SUCCESS;
273     }
274
275     int PasswordManager::setPasswordMaxChallenge(const unsigned int maxChallenge)
276     {
277         // check if there is password
278         if (!m_pwdFile.isPasswordActive()) {
279             LogError("Password not active.");
280             return SECURITY_SERVER_API_ERROR_NO_PASSWORD;
281         }
282
283         m_pwdFile.setMaxAttempt(maxChallenge);
284         m_pwdFile.writeMemoryToFile();
285
286         m_pwdFile.resetAttempt();
287         m_pwdFile.writeAttemptToFile();
288
289         return SECURITY_SERVER_API_SUCCESS;
290     }
291 } //namespace SecurityServer