2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 #include <sys/types.h>
18 #include <sys/inotify.h>
20 #include <unordered_map>
22 #include <dpm/pil/policy-context.h>
23 #include <dpm/pil/policy-model.h>
24 #include <dpm/pil/policy-storage.h>
25 #include <dpm/pil/app-bundle.h>
26 #include <dpm/pil/launchpad.h>
28 #include <klay/error.h>
29 #include <klay/exception.h>
31 #include "password-manager.h"
34 DPM_PASSWORD_QUALITY_UNSPECIFIED = 0x00, /**< No requirements for password. */
35 DPM_PASSWORD_QUALITY_SIMPLE_PASSWORD = 0x01, /**< Eas requirement for simple password */
36 DPM_PASSWORD_QUALITY_SOMETHING = 0x10, /**< Some kind password is required, but doesn't care what it is */
37 DPM_PASSWORD_QUALITY_NUMERIC = 0x20, /**< Containing at least numeric characters */
38 DPM_PASSWORD_QUALITY_ALPHABETIC = 0x40, /**< Containing at least alphabetic (or other symbol) characters */
39 DPM_PASSWORD_QUALITY_ALPHANUMERIC = 0x80, /**< Containing at least numeric and alphabetic characters */
40 } PasswordPolicyQuality;
43 DPM_PASSWORD_STATUS_NORMAL, /**< Password normal status */
44 DPM_PASSWORD_STATUS_CHANGED, /**< Password successfully changed */
45 DPM_PASSWORD_STATUS_NOT_CHANGED, /**< Password not changed */
46 DPM_PASSWORD_STATUS_CHANGE_REQUIRED , /**< Password change required */
47 DPM_PASSWORD_STATUS_MAX_ATTEMPTS_EXCEEDED, /**< Password Max Attempts Exceeded*/
49 DPM_PASSWORD_STATUS_EXPIRED, /**< Password expired */
50 DPM_PASSWORD_STATUS_RECOVERY_PASSWORD_FAILED, /**< Device unlock failed by Password Recovery */
51 DPM_PASSWORD_STATUS_RECOVERY_PASSWORD_SUCCEEDED,/**< Device unlock succeeded by Password Recovery */
53 DPM_PASSWORD_STATUS_QUALITY_CHANGED, /**< Password quality successfully changed */
54 DPM_PASSWORD_STATUS_MIN_LENGTH_CHANGED, /**< Password min_length successfully changed */
55 DPM_PASSWORD_STATUS_COMPLEX_CHAR_CHANGED, /**< Password complex_char successfully changed */
56 DPM_PASSWORD_STATUS_PATTERN_CHANGED, /**< Password pattern successfully changed */
57 DPM_PASSWORD_STATUS_MAX
58 } PasswordPolicyStatus;
62 const int simplePasswordLength = 4;
63 const int infinite = 32767;
65 const std::string BootCompleted = "/tmp/.dpm-bootCompleted";
66 int bootCompleted = -1;
68 std::unordered_map<uid_t, int> passwordStatus;
70 inline int inverse(int value)
75 inline PasswordManager::QualityType getPasswordQualityType(int quality)
78 case DPM_PASSWORD_QUALITY_UNSPECIFIED:
79 return AUTH_PWD_QUALITY_UNSPECIFIED;
80 case DPM_PASSWORD_QUALITY_SIMPLE_PASSWORD:
81 return AUTH_PWD_QUALITY_UNSPECIFIED;
82 case DPM_PASSWORD_QUALITY_SOMETHING:
83 return AUTH_PWD_QUALITY_SOMETHING;
84 case DPM_PASSWORD_QUALITY_NUMERIC:
85 return AUTH_PWD_QUALITY_NUMERIC;
86 case DPM_PASSWORD_QUALITY_ALPHABETIC:
87 return AUTH_PWD_QUALITY_ALPHABETIC;
88 case DPM_PASSWORD_QUALITY_ALPHANUMERIC:
89 return AUTH_PWD_QUALITY_ALPHANUMERIC;
91 throw runtime::Exception("Unknown quality type: " + std::to_string(quality));
97 class PasswordQuality : public DomainPolicy<DataSetInt> {
99 PasswordQuality() : DomainPolicy("password-quality")
103 bool apply(const DataType& value, uid_t domain)
105 if (bootCompleted < 0)
109 int auth = DPM_PASSWORD_QUALITY_UNSPECIFIED;
111 int quality = inverse(value);
112 if (quality & DPM_PASSWORD_QUALITY_SIMPLE_PASSWORD) {
113 auth = quality - DPM_PASSWORD_QUALITY_SIMPLE_PASSWORD;
116 PasswordManager::QualityType type = getPasswordQualityType(auth);
118 PasswordManager passwordManager(domain);
119 passwordManager.setQuality(type);
120 passwordManager.enforce();
121 } catch (runtime::Exception &e) {
130 class PasswordSequences : public DomainPolicy<DataSetInt> {
132 PasswordSequences() : DomainPolicy("password-numeric-sequences-length")
136 bool apply(const DataType& value, uid_t domain)
140 if (bootCompleted < 0)
144 v = v == infinite ? 0 : v;
145 PasswordManager passwordManager(domain);
146 passwordManager.setMaximumNumericSequenceLength(v);
147 passwordManager.enforce();
148 } catch (runtime::Exception &e) {
157 class PasswordOccurrences : public DomainPolicy<DataSetInt> {
159 PasswordOccurrences() : DomainPolicy("password-maximum-character-occurrences")
163 bool apply(const DataType& value, uid_t domain)
167 if (bootCompleted < 0)
171 v = v == infinite ? 0 : v;
172 PasswordManager passwordManager(domain);
173 passwordManager.setMaximumCharacterOccurrences(value);
174 passwordManager.enforce();
175 } catch (runtime::Exception &e) {
184 class PasswordHistory : public DomainPolicy<DataSetInt> {
186 PasswordHistory() : DomainPolicy("password-history")
190 bool apply(const DataType& value, uid_t domain)
192 if (bootCompleted < 0)
196 PasswordManager passwordManager(domain);
197 passwordManager.setHistory(inverse(value));
198 passwordManager.enforce();
199 } catch (runtime::Exception &e) {
208 class PasswordExpire : public DomainPolicy<DataSetInt> {
210 PasswordExpire() : DomainPolicy("password-expired")
214 bool apply(const DataType& value, uid_t domain)
216 if (bootCompleted < 0)
220 PasswordManager passwordManager(domain);
221 passwordManager.setExpires(value);
222 passwordManager.enforce();
223 } catch (runtime::Exception &e) {
232 class PasswordFailureCount : public DomainPolicy<DataSetInt> {
234 PasswordFailureCount() : DomainPolicy("password-maximum-failure-count")
238 bool apply(const DataType& value, uid_t domain)
240 if (bootCompleted < 0)
244 PasswordManager passwordManager(domain);
245 passwordManager.setMaximumFailedForWipe(value);
246 passwordManager.enforce();
247 } catch (runtime::Exception &e) {
256 class PasswordComplexity : public DomainPolicy<DataSetInt> {
258 PasswordComplexity() : DomainPolicy("password-minimum-complexity")
262 bool apply(const DataType& value, uid_t domain)
264 if (bootCompleted < 0)
268 PasswordManager passwordManager(domain);
269 passwordManager.setMinimumComplexCharacters(inverse(value));
270 passwordManager.enforce();
271 } catch (runtime::Exception &e) {
280 class PasswordLength : public DomainPolicy<DataSetInt> {
282 PasswordLength() : DomainPolicy("password-minimum-length")
286 bool apply(const DataType& value, uid_t domain)
288 if (bootCompleted < 0)
292 PasswordManager passwordManager(domain);
293 passwordManager.setMinimumLength(inverse(value));
294 passwordManager.enforce();
295 } catch (runtime::Exception &e) {
304 class PasswordTimeout : public DomainPolicy<DataSetInt> {
306 PasswordTimeout() : DomainPolicy("password-inactivity-timeout")
310 bool apply(const DataType& value, uid_t domain)
316 class PasswordRecovery : public DomainPolicy<DataSetInt> {
318 PasswordRecovery() : DomainPolicy("password-recovery")
322 bool apply(const DataType& value, uid_t domain)
328 class Password : public AbstractPolicyProvider {
330 Password(PolicyControlContext& context) {
331 inotifyFd = ::inotify_init1(IN_NONBLOCK);
333 throw runtime::Exception(runtime::GetSystemErrorMessage());
336 int wd = ::inotify_add_watch(inotifyFd, BootCompleted.c_str(), IN_MODIFY);
338 throw runtime::Exception(runtime::GetSystemErrorMessage());
341 auto setBootCompleted = [&context, this](int fd, runtime::Mainloop::Event event) {
343 context.mainloop.removeEventSource(inotifyFd);
348 context.mainloop.addEventSource(inotifyFd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, setBootCompleted);
356 int setQuality(int quality);
358 int setMinimumLength(int value);
359 int getMinimumLength();
360 int setMinComplexChars(int value);
361 int getMinComplexChars();
362 int setMaximumFailedForWipe(int value);
363 int getMaximumFailedForWipe();
364 int setExpires(int value);
366 int setHistory(int value);
368 int setPattern(const std::string &pattern);
369 int reset(const std::string &passwd);
371 int setMaxInactivityTimeDeviceLock(int value);
372 int getMaxInactivityTimeDeviceLock();
373 int setStatus(int status);
376 std::string getPattern();
377 int setMaximumCharacterOccurrences(int value);
378 int getMaximumCharacterOccurrences();
379 int setMaximumNumericSequenceLength(int value);
380 int getMaximumNumericSequenceLength();
381 int setForbiddenStrings(const std::vector<std::string> &forbiddenStrings);
382 std::vector<std::string> getForbiddenStrings();
383 int setRecovery(int enable);
389 PasswordQuality quality;
390 PasswordHistory history;
391 PasswordLength length;
392 PasswordComplexity complexity;
393 PasswordTimeout timeout;
394 PasswordExpire expire;
395 PasswordFailureCount failureCount;
396 PasswordSequences sequences;
397 PasswordOccurrences occurrences;
398 PasswordRecovery recovery;
401 int Password::setQuality(int value)
404 quality.set(inverse(value));
405 if (value & DPM_PASSWORD_QUALITY_SIMPLE_PASSWORD) {
406 length.set(inverse(simplePasswordLength));
408 } catch (runtime::Exception& e) {
416 int Password::getQuality()
418 int value = quality.get();
419 return inverse(value);
422 int Password::setMinimumLength(int value)
425 value = inverse(value);
427 } catch (runtime::Exception& e) {
435 int Password::getMinimumLength()
437 int value = length.get();
438 return inverse(value);
441 int Password::setMinComplexChars(int value)
444 value = inverse(value);
445 complexity.set(value);
446 } catch (runtime::Exception& e) {
454 int Password::getMinComplexChars()
456 int value = complexity.get();
457 return inverse(value);
460 int Password::setMaximumFailedForWipe(int value)
463 value = value == 0 ? infinite : value;
464 failureCount.set(value);
465 } catch (runtime::Exception& e) {
473 int Password::getMaximumFailedForWipe()
475 int value = failureCount.get();
476 return value == infinite ? 0 : value;
479 int Password::setExpires(int value)
482 value = value == 0 ? infinite : value;
484 } catch (runtime::Exception& e) {
492 int Password::getExpires()
494 int value = expire.get();
495 return value == infinite ? 0 : value;
498 int Password::setHistory(int value)
501 value = inverse(value);
503 } catch (runtime::Exception& e) {
511 int Password::getHistory()
513 int value = history.get();
514 return inverse(value);
517 int Password::reset(const std::string &passwd)
520 PasswordManager passwordManager(rmi::Service::getPeerUid());
521 passwordManager.resetPassword(passwd);
522 } catch (runtime::Exception& e) {
530 int Password::enforceChange()
534 bundle.add("id", "password-enforce-change");
536 Launchpad launchpad(rmi::Service::getPeerUid());
537 launchpad.launch("org.tizen.dpm-syspopup", bundle);
538 passwordStatus[rmi::Service::getPeerUid()] = DPM_PASSWORD_STATUS_CHANGE_REQUIRED;
539 } catch (runtime::Exception& e) {
547 int Password::setMaxInactivityTimeDeviceLock(int value)
550 value = value == 0 ? infinite : value;
552 } catch (runtime::Exception& e) {
560 int Password::getMaxInactivityTimeDeviceLock()
562 int value = timeout.get();
563 return value == infinite ? 0 : value;
566 int Password::setStatus(int status)
568 if (status >= DPM_PASSWORD_STATUS_MAX) {
569 ERROR("Invalid password status");
573 passwordStatus[rmi::Service::getPeerUid()] = status;
574 //ctx.notify("password", "password-status");
579 int Password::getStatus()
581 return passwordStatus[rmi::Service::getPeerUid()];
584 int Password::setMaximumCharacterOccurrences(int value)
587 value = value == 0 ? infinite : value;
588 occurrences.set(value);
589 } catch (runtime::Exception& e) {
597 int Password::getMaximumCharacterOccurrences()
599 int value = occurrences.get();
600 return value == infinite ? 0 : value;
603 int Password::setMaximumNumericSequenceLength(int value)
606 value = value == 0 ? infinite : value;
607 sequences.set(value);
608 } catch (runtime::Exception& e) {
616 int Password::getMaximumNumericSequenceLength()
618 int value = sequences.get();
619 return value == infinite ? 0 : value;
622 int Password::setRecovery(int enable)
625 enable = inverse(enable);
626 recovery.set(enable);
627 } catch (runtime::Exception& e) {
635 int Password::getRecovery()
637 int value = recovery.get();
638 return inverse(value);
643 #define PRIVILEGE "http://tizen.org/privilege/dpm.password"
645 AbstractPolicyProvider *PolicyFactory(PolicyControlContext& context)
647 Password *policy = new Password(context);
649 context.expose(policy, PRIVILEGE, (int)(Password::setQuality)(int));
650 context.expose(policy, PRIVILEGE, (int)(Password::setMinimumLength)(int));
651 context.expose(policy, PRIVILEGE, (int)(Password::setMinComplexChars)(int));
652 context.expose(policy, PRIVILEGE, (int)(Password::setMaximumFailedForWipe)(int));
653 context.expose(policy, PRIVILEGE, (int)(Password::setExpires)(int));
654 context.expose(policy, PRIVILEGE, (int)(Password::setHistory)(int));
655 context.expose(policy, PRIVILEGE, (int)(Password::reset)(std::string));
656 context.expose(policy, PRIVILEGE, (int)(Password::enforceChange)());
657 context.expose(policy, PRIVILEGE, (int)(Password::setMaxInactivityTimeDeviceLock)(int));
658 context.expose(policy, PRIVILEGE, (int)(Password::setStatus)(int));
659 context.expose(policy, PRIVILEGE, (int)(Password::setMaximumCharacterOccurrences)(int));
660 context.expose(policy, PRIVILEGE, (int)(Password::setMaximumNumericSequenceLength)(int));
661 context.expose(policy, PRIVILEGE, (int)(Password::setRecovery)(int));
663 context.expose(policy, "", (int)(Password::getStatus)());
664 context.expose(policy, PRIVILEGE, (int)(Password::getQuality)());
665 context.expose(policy, PRIVILEGE, (int)(Password::getMinimumLength)());
666 context.expose(policy, PRIVILEGE, (int)(Password::getMinComplexChars)());
667 context.expose(policy, PRIVILEGE, (int)(Password::getMaximumFailedForWipe)());
668 context.expose(policy, PRIVILEGE, (int)(Password::getExpires)());
669 context.expose(policy, PRIVILEGE, (int)(Password::getHistory)());
670 context.expose(policy, PRIVILEGE, (int)(Password::getMaxInactivityTimeDeviceLock)());
671 context.expose(policy, PRIVILEGE, (int)(Password::getMaximumCharacterOccurrences)());
672 context.expose(policy, PRIVILEGE, (int)(Password::getMaximumNumericSequenceLength)());
673 context.expose(policy, "", (int)(Password::getRecovery)());