1: <?php
2: declare(strict_types=1);
3: /**
4: * +------------------------------------------------------------+
5: * | apnscp |
6: * +------------------------------------------------------------+
7: * | Copyright (c) Apis Networks |
8: * +------------------------------------------------------------+
9: * | Licensed under Artistic License 2.0 |
10: * +------------------------------------------------------------+
11: * | Author: Matt Saladna (msaladna@apisnetworks.com) |
12: * +------------------------------------------------------------+
13: */
14:
15: use Opcenter\Terminal;
16:
17: /**
18: * Provides common functionality associated with SSH
19: *
20: * @package core
21: */
22: class Ssh_Module extends Module_Skeleton implements \Module\Skeleton\Contracts\Hookable
23: {
24: const PAM_SVC_NAME = 'ssh';
25: const DEPENDENCY_MAP = [
26: 'siteinfo',
27: 'ipinfo',
28: 'ipinfo6',
29: 'users',
30: 'auth'
31: ];
32:
33: /**
34: * {{{ void __construct(void)
35: *
36: * @ignore
37: */
38:
39: public function __construct()
40: {
41: parent::__construct();
42: $this->exportedFunctions = array(
43: '*' => PRIVILEGE_SITE,
44: 'enabled' => PRIVILEGE_SITE | PRIVILEGE_USER
45: );
46: }
47:
48: public function deny_user(string $user): bool
49: {
50: return (new Util_Pam($this->getAuthContext()))->remove($user, self::PAM_SVC_NAME);
51: }
52:
53: public function permit_user(string $user): bool
54: {
55: if ($this->auth_is_demo()) {
56: return error('SSH disabled for demo account');
57: }
58:
59: return (new Util_Pam($this->getAuthContext()))->add($user, self::PAM_SVC_NAME);
60: }
61:
62: public function _edit_user(string $userold, string $usernew, array $oldpwd)
63: {
64: if ($userold === $usernew) {
65: return;
66: }
67:
68: if (!$this->enabled() || !$this->user_enabled($userold)) {
69: return true;
70: }
71: // @TODO nuke active ssh sessions?
72: $pam = new Util_Pam($this->getAuthContext());
73: $pam->remove($userold, self::PAM_SVC_NAME);
74: $pam->add($usernew, self::PAM_SVC_NAME);
75:
76: return true;
77: }
78:
79: public function enabled()
80: {
81: $check = (bool)$this->getServiceValue('ssh', 'enabled');
82: if ($this->permission_level & PRIVILEGE_USER) {
83: $check = $check && $this->user_enabled($this->username);
84: }
85:
86: return $check;
87: }
88:
89: public function port_range(): array
90: {
91: if (!$this->getServiceValue('ssh', 'enabled') || !SSH_USER_DAEMONS) {
92: return array();
93: }
94:
95: return Terminal::formatPortRange(
96: $this->getServiceValue('ssh', 'port_index', [])
97: );
98: }
99:
100: public function user_enabled($user)
101: {
102: if (!$this->getConfig('ssh', 'enabled')) {
103: return warn('ssh not enabled on account');
104: }
105:
106: return (new Util_Pam($this->getAuthContext()))->check($user, self::PAM_SVC_NAME);
107: }
108:
109: public function _housekeeping()
110: {
111: if (SSH_EMBED_TERMINAL && !APNSCPD_HEADLESS) {
112: dlog('Loading terminal...');
113: Service_Terminal::autostart();
114: } else {
115: Service_Terminal::stop();
116: }
117: }
118:
119: public function _create()
120: {
121: // stupid thor...
122: $conf = $this->getAuthContext()->getAccount()->new;
123: $admin = $conf['siteinfo']['admin_user'];
124: $pam = new Util_Pam($this->getAuthContext());
125: if ($this->auth_is_demo() && $pam->check($admin, self::PAM_SVC_NAME)) {
126: $pam->remove($admin, self::PAM_SVC_NAME);
127: }
128: }
129:
130: public function _verify_conf(\Opcenter\Service\ConfigurationContext $ctx): bool
131: {
132: return true;
133: }
134:
135: public function _delete()
136: {
137: // TODO: Implement _delete() method.
138: }
139:
140: public function _edit()
141: {
142: // TODO: Implement _edit() method.
143: }
144:
145: public function _create_user(string $user)
146: {
147: // TODO: Implement _create_user() method.
148: }
149:
150: public function _delete_user(string $user)
151: {
152: // TODO: Implement _delete_user() method.
153: }
154:
155:
156: }