opensipscli 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,281 @@
1
+ #!/usr/bin/env python
2
+ ##
3
+ ## This file is part of OpenSIPS CLI
4
+ ## (see https://github.com/OpenSIPS/opensips-cli).
5
+ ##
6
+ ## This program is free software: you can redistribute it and/or modify
7
+ ## it under the terms of the GNU General Public License as published by
8
+ ## the Free Software Foundation, either version 3 of the License, or
9
+ ## (at your option) any later version.
10
+ ##
11
+ ## This program is distributed in the hope that it will be useful,
12
+ ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ ## GNU General Public License for more details.
15
+ ##
16
+ ## You should have received a copy of the GNU General Public License
17
+ ## along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ ##
19
+
20
+ from opensipscli.module import Module
21
+ from opensipscli.logger import logger
22
+ from opensipscli.config import cfg
23
+ from opensipscli.db import (
24
+ osdb, osdbError
25
+ )
26
+
27
+ import os
28
+ import getpass
29
+ import hashlib
30
+
31
+ DEFAULT_DB_NAME = "opensips"
32
+ USER_TABLE = "subscriber"
33
+ USER_NAME_COL = "username"
34
+ USER_DOMAIN_COL = "domain"
35
+ USER_PASS_COL = "password"
36
+ USER_HA1_COL = "ha1"
37
+ USER_HA1B_COL = "ha1b"
38
+ USER_HA1_SHA256_COL = "ha1_sha256"
39
+ USER_HA1_SHA512T256_COL = "ha1_sha512t256"
40
+ USER_RPID_COL = "rpid"
41
+
42
+ class user(Module):
43
+
44
+ def user_db_connect(self):
45
+ engine = osdb.get_db_engine()
46
+
47
+ db_url = cfg.read_param(["database_user_url", "database_url"],
48
+ "Please provide us the URL of the database")
49
+ if db_url is None:
50
+ print()
51
+ logger.error("no URL specified: aborting!")
52
+ return None, None
53
+
54
+ db_url = osdb.set_url_driver(db_url, engine)
55
+ db_name = cfg.read_param(["database_user_name", "database_name"],
56
+ "Please provide the database to add user to", DEFAULT_DB_NAME)
57
+
58
+ try:
59
+ db = osdb(db_url, db_name)
60
+ except osdbError:
61
+ logger.error("failed to connect to database %s", db_name)
62
+ return None, None
63
+
64
+ if not db.connect():
65
+ return None, None
66
+
67
+ res = db.find('version', 'table_version', {'table_name': USER_TABLE})
68
+ if not res:
69
+ osips_ver = '3.2+'
70
+ else:
71
+ # RFC 8760 support was introduced in OpenSIPS 3.2 (table ver 8+)
72
+ tb_ver = res.first()[0]
73
+ if tb_ver >= 8:
74
+ osips_ver = '3.2+'
75
+ else:
76
+ osips_ver = '3.1'
77
+
78
+ return db, osips_ver
79
+
80
+ def user_get_domain(self, name):
81
+ s = name.split('@')
82
+ if len(s) > 2:
83
+ logger.warning("invalid username {}".
84
+ format(name))
85
+ return None
86
+ elif len(s) == 1:
87
+ domain = cfg.read_param("domain",
88
+ "Please provide the domain of the user")
89
+ if not domain:
90
+ logger.warning("no domain specified for {}".
91
+ format(name))
92
+ return None
93
+ return name, domain
94
+ return s[0], s[1]
95
+
96
+ def user_get_password(self):
97
+ while True:
98
+ pw1 = getpass.getpass("Please enter new password: ")
99
+ pw2 = getpass.getpass("Please repeat the password: ")
100
+ if pw1 != pw2:
101
+ logger.warning("passwords are not the same! Please retry...")
102
+ else:
103
+ return pw1
104
+
105
+ def user_get_ha1(self, user, domain, password):
106
+ string = "{}:{}:{}".format(user, domain, password)
107
+ return hashlib.md5(string.encode('utf-8')).hexdigest()
108
+
109
+ def user_get_ha1b(self, user, domain, password):
110
+ string = "{}@{}:{}:{}".format(user, domain, domain, password)
111
+ return hashlib.md5(string.encode('utf-8')).hexdigest()
112
+
113
+ def user_get_ha1_sha256(self, user, domain, password):
114
+ string = "{}:{}:{}".format(user, domain, password)
115
+ return hashlib.sha256(string.encode('utf-8')).hexdigest()
116
+
117
+ def user_get_ha1_sha512t256(self, user, domain, password):
118
+ string = "{}:{}:{}".format(user, domain, password)
119
+ try:
120
+ o = hashlib.new("sha512-256")
121
+ except ValueError:
122
+ # SHA-512/256 is only available w/ OpenSSL 1.1.1 (Sep 2018) or
123
+ # newer, so let's just leave the field blank if we get an exception
124
+ logger.error(("The SHA-512/256 hashing algorithm is "
125
+ "apparently not available!?"))
126
+ logger.error("Adding user, but with a blank '{}' column!".format(
127
+ USER_HA1_SHA512T256_COL))
128
+ logger.error("Tip: installing OpenSSL 1.1.1+ should fix this")
129
+ return ""
130
+
131
+ o.update(string.encode('utf-8'))
132
+ return o.hexdigest()
133
+
134
+ def do_add(self, params=None, modifiers=None):
135
+
136
+ if len(params) < 1:
137
+ name = cfg.read_param(None,
138
+ "Please provide the username you want to add")
139
+ if not name:
140
+ logger.warning("no username to add!")
141
+ return -1
142
+ else:
143
+ name = params[0]
144
+ username, domain = self.user_get_domain(name)
145
+
146
+ db, osips_ver = self.user_db_connect()
147
+ if not db:
148
+ return -1
149
+
150
+ insert_dict = {
151
+ USER_NAME_COL: username,
152
+ USER_DOMAIN_COL: domain
153
+ }
154
+ # check if the user already exists
155
+ if db.entry_exists(USER_TABLE, insert_dict):
156
+ logger.error("User {}@{} already exists".
157
+ format(username, domain))
158
+ return -1
159
+
160
+ if len(params) > 1:
161
+ password = params[1]
162
+ else:
163
+ password = self.user_get_password()
164
+ if password is None:
165
+ logger.error("password not specified: cannot add user {}@{}".
166
+ format(user, domain))
167
+ return -1
168
+ insert_dict[USER_HA1_COL] = \
169
+ self.user_get_ha1(username, domain, password)
170
+
171
+ # only populate the 'ha1b' column on 3.1 or older OpenSIPS DBs
172
+ if osips_ver < '3.2':
173
+ insert_dict[USER_HA1B_COL] = \
174
+ self.user_get_ha1b(username, domain, password)
175
+ else:
176
+ insert_dict[USER_HA1_SHA256_COL] = \
177
+ self.user_get_ha1_sha256(username, domain, password)
178
+ insert_dict[USER_HA1_SHA512T256_COL] = \
179
+ self.user_get_ha1_sha512t256(username, domain, password)
180
+
181
+ insert_dict[USER_PASS_COL] = \
182
+ password if cfg.getBool("plain_text_passwords") else ""
183
+
184
+ db.insert(USER_TABLE, insert_dict)
185
+ logger.info("Successfully added {}@{}".format(username, domain))
186
+
187
+ db.destroy()
188
+ return True
189
+
190
+ def do_password(self, params=None, modifiers=None):
191
+
192
+ if len(params) < 1:
193
+ name = cfg.read_param(None,
194
+ "Please provide the username to change the password for")
195
+ if not name:
196
+ logger.error("empty username")
197
+ return -1
198
+ else:
199
+ name = params[0]
200
+ username, domain = self.user_get_domain(name)
201
+
202
+ db, osips_ver = self.user_db_connect()
203
+ if not db:
204
+ return -1
205
+
206
+ user_dict = {
207
+ USER_NAME_COL: username,
208
+ USER_DOMAIN_COL: domain
209
+ }
210
+ # check if the user already exists
211
+ if not db.entry_exists(USER_TABLE, user_dict):
212
+ logger.warning("User {}@{} does not exist".
213
+ format(username, domain))
214
+ return -1
215
+
216
+ if len(params) > 1:
217
+ password = params[1]
218
+ else:
219
+ password = self.user_get_password()
220
+ if password is None:
221
+ logger.error("Password not specified: " +
222
+ "cannot change passowrd for user {}@{}".
223
+ format(user, domain))
224
+ return -1
225
+ plain_text_pw = cfg.getBool("plain_text_passwords")
226
+ update_dict = {
227
+ USER_HA1_COL: self.user_get_ha1(username, domain, password),
228
+ USER_PASS_COL: password if plain_text_pw else ""
229
+ }
230
+
231
+ if osips_ver < '3.2':
232
+ update_dict[USER_HA1B_COL] = self.user_get_ha1b(
233
+ username, domain, password)
234
+
235
+ db.update(USER_TABLE, update_dict, user_dict)
236
+ logger.info("Successfully changed password for {}@{}".
237
+ format(username, domain))
238
+ db.destroy()
239
+ return True
240
+
241
+ def do_delete(self, params=None, modifiers=None):
242
+
243
+ if len(params) < 1:
244
+ name = cfg.read_param(None,
245
+ "Please provide the username you want to delete")
246
+ if not name:
247
+ logger.warning("no username to delete!")
248
+ return -1
249
+ else:
250
+ name = params[0]
251
+ username, domain = self.user_get_domain(name)
252
+
253
+ db, _ = self.user_db_connect()
254
+ if not db:
255
+ return -1
256
+
257
+ delete_dict = {
258
+ USER_NAME_COL: username,
259
+ USER_DOMAIN_COL: domain
260
+ }
261
+ # check if the user already exists
262
+ if not db.entry_exists(USER_TABLE, delete_dict):
263
+ logger.error("User {}@{} does not exist".
264
+ format(username, domain))
265
+ return -1
266
+
267
+ db.delete(USER_TABLE, delete_dict)
268
+ logger.info("Successfully deleted {}@{}".format(username, domain))
269
+
270
+ db.destroy()
271
+ return True
272
+
273
+ def __exclude__(self):
274
+ if cfg.exists("dababase_user_url"):
275
+ db_url = cfg.get("database_user_url")
276
+ elif cfg.exists("database_url"):
277
+ db_url = cfg.get("database_url")
278
+ else:
279
+ return (not osdb.has_sqlalchemy(), None)
280
+ return (not osdb.has_dialect(osdb.get_dialect(db_url)), None)
281
+
opensipscli/version.py ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python
2
+ ##
3
+ ## This file is part of OpenSIPS CLI
4
+ ## (see https://github.com/OpenSIPS/opensips-cli).
5
+ ##
6
+ ## This program is free software: you can redistribute it and/or modify
7
+ ## it under the terms of the GNU General Public License as published by
8
+ ## the Free Software Foundation, either version 3 of the License, or
9
+ ## (at your option) any later version.
10
+ ##
11
+ ## This program is distributed in the hope that it will be useful,
12
+ ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ ## GNU General Public License for more details.
15
+ ##
16
+ ## You should have received a copy of the GNU General Public License
17
+ ## along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ ##
19
+
20
+ __version__ = '0.3.1'
21
+
22
+ # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
@@ -0,0 +1,9 @@
1
+ #!python
2
+
3
+ from opensipscli import main
4
+
5
+ def run_console():
6
+ main.main()
7
+
8
+ if __name__ == '__main__':
9
+ run_console()