This repository has been archived by the owner on May 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrecon-devel.py
5647 lines (4237 loc) · 230 KB
/
wrecon-devel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -*- coding: utf-8 -*-
# CODING=UTF8
#
# Weechat Remote Control
# ======================================================================
# Author : Radek Valasek
# Contact : https://github.com/reddy75/wrecon/issues
# Licence : GPL3
# Description : Script for control remote server
# Requirements : weechat, python3, tmate, ircrypt (script for weechat)
# GIT ................... : https://github.com/reddy75/wrecon
# LATEST RELEASE ........ : https://github.com/reddy75/wrecon/releases/latest
# BUG REPORTS ........... : https://github.com/reddy75/wrecon/issues
# IMPROVEMENT SUGGESTIONS : https://github.com/reddy75/wrecon/issues
# WIKI / HELP ........... : https://github.com/reddy75/wrecon/wiki
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# Changelog:
# 2.00.0 (unusable, full reworking in progress)
# - Full code rewriting (for better lucidity, and also for code enhancements)
# -- function 'display_message' replaces 'f_message' and 'f_message_simple'
# -- function 'command_update' fully changed (splitted into functions)
# -- functions 'encrypt/decrypt' enhanced into levels (also backward compatibility ensure with older script communication)
# -- added possibility choice BOT by INDEX number (for commands DEL/RENAME/REVOKE/SSH/UPDATE)
# -- added security feature - strict check advertised bot (once advertised should be same source)
# -- added security feature - ssh using random encrypt keys
#
# 1.18.14 - Allowing to accept python version since 2.7
# 1.18.13 - Bug fix UPDATE (arguments incorrectly checked after additional advertise)
# 1.18.12 - Bug fix REGISTER/UNREGISTER (add/del registered channels and keys)
# 1.18.11 - Bug fix UPDATE CHECK VERSION
# 1.18.10 - Bug fix SSH AUTOADVERTISE
# 1.18.9 - Bug fix SSH AUTOADVERTISE
# 1.18.8 - Version correction
# 1.18.7 - Fixed bug of variables (lower cases and UPPER CASEs)
# - in commands REGISTER and UNREGISTER
# 1.18.6 - Fixed bug of variables (lower cases and UPPER CASEs)
# 1.18.5 - Fixed list command (correction of command arguments)
# 1.18.4 - Fix command ADVERTISE
# 1.18.3 - Small fix of call ADDITIONAL ADVERTISE
# - assignment variables fix (another patch)
# - Fix ssh call
# 1.18.2 - Small fix of call ADDITIONAL ADVERTISE
# - assignment variables fix (another patch)
# 1.18.1 - Small fix of call ADDITIONAL ADVERTISE
# - assignment variables fix (another patch)
# 1.18 - Small fix of call ADDITIONAL ADVERTISE
# - assignment variables fixed
# 1.17 - Small fix of call ADDITIONAL ADVERTISE
# 1.16 - Small fix of call ADVERTISE after RENAME
# 1.15 - Small fix in HELP - REGISTER
# 1.14 - Bug fix REMOTE RENAME
# 1.13 - Bug fixes
# 1.12 - Version fix
# 1.11 - Bug fix for HELP command
# 1.10 - Command UPDATE added - New feature (check and install new version from GIT repo)
# - Added UNIQUE HASH to all called commands
# - Command UNREGISTER changed to UN[REGISTER]
# - Help for UNREGISTER updated
# - Corrected LATEST RELEASE in header of script
# 1.05 - Bug fix issue #3
# 1.04 - Bug fix issue #2
# - Removed never used variable(s)
# - Added autoadvertise request from local PC for non-advertised remote BOT when calling SSH
# - Small bug fixes
# 1.03 - Update Contact field
# - Small fixes of parts of short help
# - Small fixes of parts of comments of code
# 1.02 - Bug fix issue #1
# added github links into header
# 1.01 - Bug fix
# 1.00 - First release
#
# Purpose:
# Start 'tmate' session on remote PC over Weechat.
# - tmate session is started only for granted server(s)
# - communication between servers is accomplished over a registered IRC #Channel
# - IRC #Channel is encrypted via ircrypt
#
#
# Dependencies:
# Weechat, Tmate, Python3
# Python3 modules:
# - ast, base64, contextlib, datetime, gnupg, hashlib, json, os, random,
# - shutil, string, sys, tarfile, time, urllib, uuid
#
#
# Limitations:
# - only one IRC #Channel with IRC Server is allowed to register
# - supported platform is only linux and android (9/10 - with termux installed)
#
#
# Tested on platform:
# - Fedora 30/31
# - Xubuntu 18.04
# - Android 9/10 (in termux)
#####
#
# BASIC INITIALIZATION
# try import modules for python and check version of python
global SCRIPT_NAME, SCRIPT_VERSION, SCRIPT_AUTHOR, SCRIPT_LICENSE, SCRIPT_DESC, SCRIPT_UNLOAD, SCRIPT_CONTINUE, SCRIPT_TIMESTAMP, SCRIPT_FILE, SCRIPT_FILE_SIG, SCRIPT_BASE_NAME
SCRIPT_NAME = 'wrecon-devel'
SCRIPT_VERSION = '2.0.0 devel'
SCRIPT_TIMESTAMP = ''
SCRIPT_FILE = 'wrecon-devel.py'
SCRIPT_FILE_SIG = 'wrecon-devel.py.sig'
SCRIPT_BASE_NAME = 'reddy75/wrecon-devel'
SCRIPT_AUTHOR = 'Radek Valasek'
SCRIPT_LICENSE = 'GPL3'
SCRIPT_DESC = 'Weechat Remote control (WRECON)'
SCRIPT_UNLOAD = 'wrecon_unload'
SCRIPT_CONTINUE = True
import importlib
for IMPORT_MOD in ['ast', 'base64', 'contextlib', 'datetime', 'gnupg', 'hashlib', 'json', 'os', 'platform', 'random', 'shutil', 'string', 'sys', 'tarfile', 'time', 'urllib', 'uuid', 'weechat']:
try:
IMPORT_OBJECT = importlib.import_module(IMPORT_MOD, package=None)
globals()[IMPORT_MOD] = IMPORT_OBJECT
# ~ print('[%s v%s] > module %s imported' % (SCRIPT_NAME, SCRIPT_VERSION, IMPORT_MOD))
except ImportError:
SCRIPT_CONTINUE = False
print('[%s v%s] > module >> %s << import error' % (SCRIPT_NAME, SCRIPT_VERSION, IMPORT_MOD))
if sys.version_info >= (2,7):
#print('[%s v%s] > python version 3' % (SCRIPT_NAME, SCRIPT_VERSION))
pass
else:
SCRIPT_CONTINUE = False
print('[%s v%s] > python version %s is not supported' % (SCRIPT_NAME, SCRIPT_VERSION, sys.version_info))
if SCRIPT_CONTINUE == False:
# I there was issue with initialization basic modules for importing or version of python is unsupported, then
# we write error message
print('[%s v%s] > script not started, resolve dependencies and requirements' % (SCRIPT_NAME, SCRIPT_VERSION))
else:
#####
#
# INITIALIZE SCRIP FOR WEECHAT
weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, SCRIPT_UNLOAD, 'UTF-8')
#####
#
# FUNCTION DISPLAY MESSAGE
def display_message(BUFFER, INPUT_MESSAGE):
global SCRIPT_NAME
if isinstance(INPUT_MESSAGE, list):
# ~ weechat.prnt(BUFFER, '')
# ~ INPUT_MESSAGE.append('[%s]\t%s' %(SCRIPT_NAME, ''))
for OUTPUT_MESSAGE in INPUT_MESSAGE:
weechat.prnt(BUFFER, '\t%s' % str(OUTPUT_MESSAGE))
else:
weechat.prnt(BUFFER, '[%s]\t%s' % (SCRIPT_NAME, str(INPUT_MESSAGE)))
return weechat.WEECHAT_RC_OK
def display_message_info(BUFFER, INPUT_TAG, INPUT_MESSAGE):
global WRECON_BOT_NAME, WRECON_BOT_ID
OUT_MESSAGE =['']
OUT_MESSAGE.append('--- %s (%s %s) ---' % (INPUT_TAG, WRECON_BOT_NAME, WRECON_BOT_ID))
OUT_MESSAGE.append('')
if isinstance(INPUT_MESSAGE, list):
for OUT_MSG in INPUT_MESSAGE:
OUT_MESSAGE.append(OUT_MSG)
else:
OUT_MESSAGE.append(INPUT_MESSAGE)
display_message(BUFFER, OUT_MESSAGE)
return weechat.WEECHAT_RC_OK
# For debug purspose only
def display_data(FUNCTION, WEECHAT_DATA, BUFFER, SOURCE, DATE, TAGS, DISPLAYED, HIGHLIGHT, PREFIX, COMMAND, TARGET_BOT_ID, SOURCE_BOT_ID, COMMAND_ID, COMMAND_ARGUMENTS_LIST):
global ID_CALL_LOCAL, ID_CALL_REMOTE, WAIT_FOR_VERIFICATION
OUT_MESSAGE = ['FUNCTION : %s' % FUNCTION]
OUT_MESSAGE.append('WEECAHT_DATA : %s' % WEECHAT_DATA)
OUT_MESSAGE.append('BUFFER : %s' % BUFFER)
OUT_MESSAGE.append('SOURCE : %s' % SOURCE)
OUT_MESSAGE.append('DATE : %s' % DATE)
OUT_MESSAGE.append('TAGS : %s' % TAGS)
OUT_MESSAGE.append('DISPLAYED : %s' % DISPLAYED)
OUT_MESSAGE.append('HIGHLIGHT : %s' % HIGHLIGHT)
OUT_MESSAGE.append('PREFIX : %s' % PREFIX)
OUT_MESSAGE.append('COMMAND/DATA : %s' % COMMAND)
OUT_MESSAGE.append('TARGET_BOT_ID : %s' % TARGET_BOT_ID)
OUT_MESSAGE.append('SOURCE_BOT_ID : %s' % SOURCE_BOT_ID)
OUT_MESSAGE.append('COMMAND_ID : %s' % COMMAND_ID)
OUT_MESSAGE.append('COMMAND_ARGUMENTS_LIST : %s' % COMMAND_ARGUMENTS_LIST)
OUT_MESSAGE.append('LOCAL ID CALL : %s' % ID_CALL_LOCAL)
OUT_MESSAGE.append('REMOTE ID CALL : %s' % ID_CALL_REMOTE)
OUT_MESSAGE.append('WAIT_FOR_VERIFICATION : %s' % WAIT_FOR_VERIFICATION)
display_message_info(BUFFER, 'INFO OF COMMAND > %s < VARIABLES' % COMMAND, OUT_MESSAGE)
return weechat.WEECHAT_RC_OK
#
##### END FUNCTION DISPLAY MESSAGE
#####
#
# FUNCTION FOR GENERATING RANDOM CHARACTERS AND NUMBERS
def get_random_string(STRING_LENGTH):
STR_LETTERS_AND_DIGITS = string.ascii_letters + string.digits
return ''.join(random.choice(STR_LETTERS_AND_DIGITS) for INDEX in range(STRING_LENGTH))
#
##### END FUNCTION FOR GENERATING RANDOM CHARACTERS AND NUMBERS
#####
#
# FUNCTION GET HASH OF A STRING
def get_hash(INPUT_STRING):
CONVERT_STRING = str(INPUT_STRING)
RESULT = hashlib.md5(CONVERT_STRING.encode())
return str(RESULT.hexdigest())
#
##### END FUNCTION GET HASH OF A STRING
#####
#
# FUNCTION FOR COUNTING COMMANDS AND ADD UNIQ HASH
def get_command_uniq_id():
global WRECON_COMMAND_COUNTER
WRECON_COMMAND_COUNTER = WRECON_COMMAND_COUNTER + 1
if WRECON_COMMAND_COUNTER > 9999:
WRECON_COMMAND_COUNTER = 0
return '%04d-%s' % (WRECON_COMMAND_COUNTER, get_random_string(4))
#
##### END FUNCTION FOR COUNTING COMMANDS AND ADD UNIQ HASH
#####
#
# FUNCTION GET STATUS NICK
# Will check my nick is operator, if yes, it will return 1, else 0
def get_status_my_nick_is_op(SERVER_NAME, CHANNEL_NAME):
RESULT_NICK = 0
# Get name of our nick
MY_NICK_NAME = weechat.info_get('irc_nick', SERVER_NAME)
INFOLIST = weechat.infolist_get('irc_nick', '', '%s,%s' % (SERVER_NAME, CHANNEL_NAME))
while weechat.infolist_next(INFOLIST):
FOUND_NICK_NAME = weechat.infolist_string(INFOLIST, 'name')
if MY_NICK_NAME == FOUND_NICK_NAME:
NICK_PREFIX = weechat.infolist_string(INFOLIST, 'prefix')
NICK_PREFIXES = weechat.infolist_string(INFOLIST, 'prefixes')
if '@' in NICK_PREFIXES:
RESULT_NICK = 1
weechat.infolist_free(INFOLIST)
return RESULT_NICK
#
##### END FUNCTION GET STATUS NICK
#####
#
# FUNCTION FOR VERIFY CHANNEL SETUP AND POSSIBILITY TO CHANGE MODE IF NECESSARY
def setup_channel_2_mode(DATA, BUFFER, SERVER_NAME, CHANNEL_NAME):
global WRECON_CHANNEL_KEY
RESULT = 0
RESULT_CHANNEL = 0
RESULT_MODE = 0
RESULT_NICK = get_status_my_nick_is_op(SERVER_NAME, CHANNEL_NAME)
INFOLIST = weechat.infolist_get('irc_channel', '', '%s,%s' % (SERVER_NAME, CHANNEL_NAME))
while weechat.infolist_next(INFOLIST):
FOUND_CHANNEL_NAME = weechat.infolist_string(INFOLIST, 'name')
FOUND_CHANNEL_KEY = weechat.infolist_string(INFOLIST, 'key')
FOUND_CHANNEL_MODE = weechat.infolist_string(INFOLIST, 'modes')
if FOUND_CHANNEL_NAME == CHANNEL_NAME:
if not WRECON_CHANNEL_KEY in FOUND_CHANNEL_MODE:
RESULT_CHANNEL = 1
if not 'k' in FOUND_CHANNEL_MODE:
RESULT_MODE = 1
weechat.infolist_free(INFOLIST)
if RESULT_NICK == 1:
if RESULT_MODE == 1 or RESULT_CHANNEL == 1:
weechat.command(BUFFER, '/mode %s -n+sk %s' % (CHANNEL_NAME, WRECON_CHANNEL_KEY))
return RESULT
#
##### END FUNCTION FOR VERIFY CHANNEL SETUP AND POSSIBILITY TO CHANGE MODE IF NECESSARY
#####
#
# FUNCTION ENCRYPT AND DECTRYPT STRING, CORRECT LENGTH OF KEY, REVERT STRING
#
# ENCRYPT
#
global ENCRYPT_LEVEL
ENCRYPT_LEVEL = {}
def string_encrypt(LEVEL, INPUT_STRING, INPUT_KEY, INPUT_KEY2):
global ENCRYPT_LEVEL
return ENCRYPT_LEVEL[LEVEL](INPUT_STRING, INPUT_KEY, INPUT_KEY2)
def string_encrypt_function(INPUT_STRING, INPUT_KEY):
INPUT_KEY = string_correct_key_length(INPUT_STRING, INPUT_KEY)
OUTPUT_LIST = []
for INDEX in range(len(INPUT_STRING)):
KEY_CHAR = INPUT_STRING[INDEX % len(INPUT_STRING)]
OUTPUT_CHAR = chr((ord(INPUT_KEY[INDEX]) + ord(KEY_CHAR)) % 256)
OUTPUT_LIST.append(OUTPUT_CHAR)
OUTPUT_LIST = ''.join(OUTPUT_LIST)
return OUTPUT_LIST
def string_encrypt_level_0(INPUT_STRING, INPUT_KEY, NULL):
ERROR = False
try:
OUTPUT_LIST = string_encrypt_function(INPUT_STRING, INPUT_KEY)
OUTPUT_RESULT = base64.urlsafe_b64encode(OUTPUT_LIST.encode()).decode()
except:
ERROR = True
OUTPUT_RESULT = 'ERROR'
return [ERROR, OUTPUT_RESULT]
def string_encrypt_level_1(INPUT_STRING, INPUT_KEY, NULL):
ERROR = False
try:
NEW_INPUT_KEY = get_hash(INPUT_KEY)
SALT_STRING = get_random_string(8)
OUTPUT_RESULT_LEVEL_1 = str(string_encrypt_function(INPUT_STRING, SALT_STRING + INPUT_KEY))
OUTPUT_RESULT_LEVEL_2 = string_encrypt_function(SALT_STRING + OUTPUT_RESULT_LEVEL_1, NEW_INPUT_KEY)
OUTPUT_RESULT = base64.urlsafe_b64encode(OUTPUT_RESULT_LEVEL_2.encode()).decode()
except:
ERROR = True
OUTPUT_RESULT = 'ERROR'
return [ERROR, OUTPUT_RESULT]
def string_encrypt_level_2(INPUT_STRING, INPUT_KEY, INPUT_KEY2):
ERROR = False
try:
INPUT_STRING = string_reverse(INPUT_STRING)
INPUT_KEY = string_join_keys(INPUT_KEY2, INPUT_KEY)
NEW_INPUT_KEY = get_hash(INPUT_KEY)
SALT_STRING = get_random_string(8)
OUTPUT_RESULT_LEVEL_1 = str(string_encrypt_function(INPUT_STRING, SALT_STRING + INPUT_KEY))
OUTPUT_RESULT_LEVEL_2 = string_encrypt_function(SALT_STRING + OUTPUT_RESULT_LEVEL_1, NEW_INPUT_KEY)
OUTPUT_RESULT = base64.urlsafe_b64encode(OUTPUT_RESULT_LEVEL_2.encode()).decode()
except:
ERROR = True
OUTPUT_RESULT = 'ERROR'
return [ERROR, OUTPUT_RESULT]
ENCRYPT_LEVEL[0] = string_encrypt_level_0
ENCRYPT_LEVEL[1] = string_encrypt_level_1
ENCRYPT_LEVEL[2] = string_encrypt_level_2
#
# DECRYPT
#
global DECRYPT_LEVEL
DECRYPT_LEVEL = {}
def string_decrypt(LEVEL, INPUT_STRING, INPUT_KEY, INPUT_KEY2):
global DECRYPT_LEVEL
return DECRYPT_LEVEL[LEVEL](INPUT_STRING, INPUT_KEY, INPUT_KEY2)
def string_decrypt_function(INPUT_STRING, INPUT_KEY):
INPUT_KEY = string_correct_key_length(INPUT_STRING, INPUT_KEY)
OUTPUT_LIST = []
for INDEX in range(len(INPUT_STRING)):
KEY_CHAR = INPUT_KEY[INDEX % len(INPUT_KEY)]
OUTPUT_CHAR = chr((256 + ord(INPUT_STRING[INDEX]) - ord(KEY_CHAR)) % 256)
OUTPUT_LIST.append(OUTPUT_CHAR)
OUTPUT_LIST = ''.join(OUTPUT_LIST)
return OUTPUT_LIST
def string_decrypt_level_0(INPUT_STRING, INPUT_KEY, NULL):
ERROR = False
try:
DECODE_STRING = base64.urlsafe_b64decode(INPUT_STRING).decode()
OUTPUT_RESULT = string_decrypt_function(DECODE_STRING, INPUT_KEY)
except:
ERROR = True
OUTPUT_RESULT = 'ERROR'
return [ERROR, OUTPUT_RESULT]
def string_decrypt_level_1(INPUT_STRING, INPUT_KEY, NULL):
ERROR = False
try:
DECODE_STRING = base64.urlsafe_b64decode(INPUT_STRING).decode()
NEW_INPUT_KEY = get_hash(INPUT_KEY)
OUTPUT_RESULT_LEVEL_2 = string_decrypt_function(DECODE_STRING, NEW_INPUT_KEY)
SALT_STRING = OUTPUT_RESULT_LEVEL_2[:8]
OUTPUT_RESULT_LEVEL_1 = string_decrypt_function(OUTPUT_RESULT_LEVEL_2[8:], SALT_STRING + INPUT_KEY)
except:
ERROR = True
OUTPUT_RESULT_LEVEL_1 = 'ERROR'
return [ERROR, OUTPUT_RESULT_LEVEL_1]
def string_decrypt_level_2(INPUT_STRING, INPUT_KEY, INPUT_KEY2):
ERROR = False
try:
DECODE_STRING = base64.urlsafe_b64decode(INPUT_STRING).decode()
INPUT_KEY = string_join_keys(INPUT_KEY2, INPUT_KEY)
NEW_INPUT_KEY = get_hash(INPUT_KEY)
OUTPUT_RESULT_LEVEL_2 = string_decrypt_function(DECODE_STRING, NEW_INPUT_KEY)
SALT_STRING = OUTPUT_RESULT_LEVEL_2[:8]
OUTPUT_RESULT_LEVEL_1 = string_decrypt_function(OUTPUT_RESULT_LEVEL_2[8:], SALT_STRING + INPUT_KEY)
DECODE_STRING = string_reverse(OUTPUT_RESULT_LEVEL_1)
except:
ERROR = True
DECODE_STRING = 'ERROR'
return [ERROR, DECODE_STRING]
DECRYPT_LEVEL[0] = string_decrypt_level_0
DECRYPT_LEVEL[1] = string_decrypt_level_1
DECRYPT_LEVEL[2] = string_decrypt_level_2
#
# CORRECT LENGTH OF KEY
#
def string_correct_key_length(INPUT_STRING, INPUT_KEY):
OUTPUT_KEY = INPUT_KEY
while len(INPUT_STRING) > len(OUTPUT_KEY):
OUTPUT_KEY += INPUT_KEY
return OUTPUT_KEY
#
# REVERSE STRING
#
def string_reverse(INPUT_STRING):
OUTPUT_STRING = ''
for INDEX in range(len(INPUT_STRING)):
OUTPUT_STRING = INPUT_STRING[INDEX] + OUTPUT_STRING
return OUTPUT_STRING
#
# JOIN KEYS
#
def string_join_keys(INPUT_KEY1, INPUT_KEY2):
OUTPUT_KEY = ''
INDEX_KEY1 = 0
INDEX_KEY2 = 0
for INDEX in range(len(INPUT_KEY1 + INPUT_KEY2)):
OUTPUT_KEY = OUTPUT_KEY + INPUT_KEY1[INDEX_KEY1] + INPUT_KEY2[INDEX_KEY2]
INDEX_KEY1 += 1
INDEX_KEY2 += 1
if INDEX_KEY1 >= len(INPUT_KEY1):
INDEX_KEY1 = 0
if INDEX_KEY2 >= len(INPUT_KEY2):
INDEX_KEY2 = 0
return OUTPUT_KEY
#
#### END FUNCFUNCTION ENCRYPT AND DECTRYPT STRING, CORRECT LENGTH OF KEY, REVERT STRING
######
#
# SETUP BASIC GLOBAL VARIABLES FOR WRECON - BOT, SERVER, CHANNEL etc.
#
#
# SETUP VARIABLES OF BOT
#
def setup_wrecon_variables_of_local_bot():
global WRECON_START_TIME, I_WAS_VERIFIED, VERIFY_REQUEST
WRECON_START_TIME = int(datetime.datetime.utcnow().timestamp())
I_WAS_VERIFIED = {}
VERIFY_REQUEST = {}
global WRECON_DEFAULT_BOTNAMES, WRECON_BOT_NAME, WRECON_BOT_ID, WRECON_BOT_KEY
WRECON_DEFAULT_BOTNAMES = ['anee', 'anet', 'ann', 'annee', 'annet', 'bob', 'brad', 'don', 'fred', 'freddie', 'john', 'mia', 'moon', 'pooh', 'red', 'ron', 'ronnie', 'shark', 'ted', 'teddy', 'zed', 'zoe', 'zombie']
WRECON_BOT_NAME = weechat.string_eval_expression("${sec.data.wrecon_bot_name}",{},{},{})
WRECON_BOT_ID = weechat.string_eval_expression("${sec.data.wrecon_bot_id}",{},{},{})
WRECON_BOT_KEY = weechat.string_eval_expression("${sec.data.wrecon_bot_key}",{},{},{})
# Choice default BOT NAME if not exist and save it
if not WRECON_BOT_NAME:
WRECON_BOT_NAME = random.choice(WRECON_DEFAULT_BOTNAMES)
weechat.command('', '/secure set wrecon_bot_name %s' % (WRECON_BOT_NAME))
# Generate BOT ID if not exit and save it
if not WRECON_BOT_ID:
WRECON_BOT_ID = get_random_string(16)
weechat.command('', '/secure set wrecon_bot_id %s' % (WRECON_BOT_ID))
# Generate BOT KEY if not exist and save it
if not WRECON_BOT_KEY:
WRECON_BOT_KEY = get_random_string(64)
weechat.command('', '/secure set wrecon_bot_key %s' % (WRECON_BOT_KEY))
return
#
# SETUP VARIABLES OF SERVER
#
def setup_wrecon_variables_of_server_and_channel():
global WRECON_SERVER
WRECON_SERVER = weechat.string_eval_expression("${sec.data.wrecon_server}",{},{},{})
#
# SETUP VARIABLES OF CHANNEL
#
global WRECON_CHANNEL, WRECON_CHANNEL_KEY, WRECON_CHANNEL_ENCRYPTION_KEY
WRECON_CHANNEL = weechat.string_eval_expression("${sec.data.wrecon_channel}",{},{},{})
WRECON_CHANNEL_KEY = weechat.string_eval_expression("${sec.data.wrecon_channel_key}",{},{},{})
WRECON_CHANNEL_ENCRYPTION_KEY = weechat.string_eval_expression("${sec.data.wrecon_channel_encryption_key}",{},{},{})
#
# SETUP VARIABLES OF BUFFER
#
global WRECON_BUFFERS, WRECON_BUFFER_CHANNEL, WRECON_BUFFER_HOOKED
WRECON_BUFFERS = {}
WRECON_BUFFER_CHANNEL = ''
WRECON_BUFFER_HOOKED = False
return
#
# SETUP VARIABLES OF REMOTE BOTS
#
# CONTROL - bots you can control remotely on remote system
# table contain BOT IDs and it's BOT KEYs
#
# GRANTED - bots from remote system can control your system (you grant controol of your system)
# table contain only BOT IDs
#
# VERIFIED - runtime variable of bots from remote system can control your system only after verification
# table contain BOT IDs and additional info from irc_channel of related NICK
# in case information of remote NICK will be changed, then new verification will be triggered
#
# ADVERTISED - runtime variable of bots which has been advertised in channel, it is only informational and for internal purpose to
# have actual state
# table contain BOT IDs and BOT NAMEs only
def setup_wrecon_variables_of_remote_bots():
global WRECON_REMOTE_BOTS_CONTROL, WRECON_REMOTE_BOTS_GRANTED, WRECON_REMOTE_BOTS_VERIFIED, WRECON_REMOTE_BOTS_ADVERTISED, WRECON_REMOTE_BOTS_GRANTED_SECRET, WRECON_REMOTE_BOTS_CONTROL_SECRET
WRECON_REMOTE_BOTS_CONTROL = weechat.string_eval_expression("${sec.data.wrecon_remote_bots_control}",{},{},{})
WRECON_REMOTE_BOTS_GRANTED = weechat.string_eval_expression("${sec.data.wrecon_remote_bots_granted}",{},{},{})
WRECON_REMOTE_BOTS_VERIFIED = {}
WRECON_REMOTE_BOTS_ADVERTISED = {}
WRECON_REMOTE_BOTS_CONTROL_SECRET = weechat.string_eval_expression("${sec.data.wrecon_remote_bots_control_secret}",{},{},{})
WRECON_REMOTE_BOTS_GRANTED_SECRET = weechat.string_eval_expression("${sec.data.wrecon_remote_bots_granted_secret}",{},{},{})
if WRECON_REMOTE_BOTS_CONTROL:
WRECON_REMOTE_BOTS_CONTROL = ast.literal_eval(WRECON_REMOTE_BOTS_CONTROL)
else:
WRECON_REMOTE_BOTS_CONTROL = {}
if WRECON_REMOTE_BOTS_GRANTED:
WRECON_REMOTE_BOTS_GRANTED = ast.literal_eval(WRECON_REMOTE_BOTS_GRANTED)
else:
WRECON_REMOTE_BOTS_GRANTED = {}
if WRECON_REMOTE_BOTS_CONTROL_SECRET:
WRECON_REMOTE_BOTS_CONTROL_SECRET = ast.literal_eval(WRECON_REMOTE_BOTS_CONTROL_SECRET)
else:
WRECON_REMOTE_BOTS_CONTROL_SECRET = {}
if WRECON_REMOTE_BOTS_GRANTED_SECRET:
WRECON_REMOTE_BOTS_GRANTED_SECRET = ast.literal_eval(WRECON_REMOTE_BOTS_GRANTED_SECRET)
else:
WRECON_REMOTE_BOTS_GRANTED_SECRET = {}
#
# SETUP VARIABLES OF COUNTER COMMAND AND AUTO ADVERTISE
#
global WRECON_COMMAND_COUNTER, WRECON_AUTO_ADVERTISED
WRECON_COMMAND_COUNTER = 0
WRECON_AUTO_ADVERTISED = False
return
#
# PUBLIC KEY
#
def setup_wrecon_variables_of_public_key():
global PUBLIC_KEY
PUBLIC_KEY = '''
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
KPX4rlTJFYD/K/Hb0OM4NwaXz5Q=
=FtIt
-----END PGP PUBLIC KEY BLOCK-----
'''
return
#
# SETUP OF FUNCTIONAL VARIABLES
#
def setup_wrecon_variables_of_functions():
global SCRIPT_COMMAND_CALL, PREPARE_USER_CALL, SCRIPT_ARGS, SCRIPT_ARGS_DESCRIPTION, SCRIPT_COMPLETION, COLOR_TEXT, SCRIPT_ARGS_DESCRIPTION, COMMAND_IN_BUFFER, SCRIPT_BUFFER_CALL, TIMEOUT_COMMAND, COMMAND_VERSION, SHORT_HELP, TIMEOUT_CONNECT, TIMEOUT_COMMAND_SHORT, SCRIPT_INTERNAL_CALL, TIMEOUT_COMMAND_L2, TIMEOUT_COMMAND_SSH
SCRIPT_COMMAND_CALL = {}
SCRIPT_BUFFER_CALL = {}
SCRIPT_INTERNAL_CALL = {}
PREPARE_USER_CALL = {}
SCRIPT_ARGS = ''
SCRIPT_ARGS_DESCRIPTION = ''
SCRIPT_COMPLETION = ''
COMMAND_IN_BUFFER = 'WRECON-CMD>'
COLOR_TEXT = {
'bold' : weechat.color('bold'),
'nbold' : weechat.color('-bold'),
'italic' : weechat.color('italic'),
'nitalic' : weechat.color('-italic'),
'underline' : weechat.color('underline'),
'nunderline' : weechat.color('-underline')}
SCRIPT_ARGS_DESCRIPTION = '''
%(bold)s%(underline)sWeechat Remote control (WRECON) commands and options:%(nunderline)s%(nbold)s
''' % COLOR_TEXT
TIMEOUT_COMMAND = 15
TIMEOUT_COMMAND_SHORT = 5
TIMEOUT_CONNECT = 30
TIMEOUT_COMMAND_L2 = 10
TIMEOUT_COMMAND_SSH = 20
COMMAND_VERSION = {}
global GLOBAL_VERSION_LIMIT
GLOBAL_VERSION_LIMIT = '2.0.0'
global SCRIPT_NAME, HELP_COMMAND
SHORT_HELP = ''
HELP_COMMAND = {}
# Number of required or optional arguments of user commands
#
# ARGUMENTS_REQUIRED == ARGUMENTS - command requires strict number of arguments
# ARGUMENTS_OPTIONAL (list) >= ARGUMENTS - command requires optional number of arguments
# - there can be no argument, or number of arguments up to limit number
# ARGUMENTS_REQUIRED_MINIMAL <= ARGUMENTS - command requires minimum number of arguments, more is allowed
# - there should be minimum number of arguments
global ARGUMENTS_REQUIRED, ARGUMENTS_OPTIONAL, ARGUMENTS_REQUIRED_MINIMAL
ARGUMENTS_REQUIRED = {}
ARGUMENTS_OPTIONAL = {}
ARGUMENTS_REQUIRED_MINIMAL = {}
#
# SETUP OF VARIABLES FOR LOCAL or REMOTE REQUIREMENTS
#
global COMMAND_REQUIREMENTS_LOCAL, COMMAND_REQUIREMENTS_REMOTE, COMMAND_RECEIVED_FROM
COMMAND_REQUIREMENTS_LOCAL = {}
COMMAND_REQUIREMENTS_REMOTE = {}
COMMAND_RECEIVED_FROM = {}
#
# SETUP OF HOOK VARIABLES
#
global WRECON_HOOK_COMMAND, WRECON_HOOK_CONNECT, WRECON_HOOK_JOIN, WRECON_HOOK_BUFFER, WRECON_HOOK_LOCAL_COMMANDS
WRECON_HOOK_COMMAND = ''
WRECON_HOOK_CONNECT = ''
WRECON_HOOK_JOIN = ''
WRECON_HOOK_BUFFER = ''
WRECON_HOOK_LOCAL_COMMANDS = ''
#
# SETUP VERIFICATION VARIABLE (for waiting of remote bot verification)
#
global WAIT_FOR_VERIFICATION, WAIT_FOR_REMOTE_DATA, WAIT_FOR_ADVERTISE_ADA, WAIT_FOR_VALIDATION, WAIT_FOR_VERSION, WAIT_FOR_ADVERTISE, WAIT_FOR_RENAME, WAIT_FOR_VERIFY_ME
WAIT_FOR_VERIFICATION = {}
WAIT_FOR_REMOTE_DATA = {}
WAIT_FOR_ADVERTISE = {}
WAIT_FOR_ADVERTISE_ADA = {}
WAIT_FOR_VALIDATION = {}
WAIT_FOR_VERSION = {}
WAIT_FOR_RENAME = {}
WAIT_FOR_VERIFY_ME = {}
# VARIABLES FOR ENHANCED ENCRYPTION VERIFICATION
global VERIFICATION_PROTOCOL, VERIFICATION_REPLY_EXPECT
VERIFICATION_PROTOCOL = {}
VERIFICATION_REPLY_EXPECT = {}
# ENCRYPT/DECRYPT KEYS FOR EACH SESSION
global SESSION_KEYS
SESSION_KEYS = {}
return
#
##### END SETUP BASIC GLOBAL VARIABLES FOR WRECON - BOT, SERVER, CHANNEL etc.
#####
#
# FUNCTION GET BUFFERS AND BUFFER OF REGISTERED CHANNEL
def get_buffers():
WRECON_BUFFERS = {}
INFOLIST_BUFFER = weechat.infolist_get('BUFFER', '', '')
while weechat.infolist_next(INFOLIST_BUFFER):
BUFFER_POINTER = weechat.infolist_pointer(INFOLIST_BUFFER, 'pointer')
BUFFER_NAME = weechat.buffer_get_string(BUFFER_POINTER, 'localvar_name')
WRECON_BUFFERS[BUFFER_NAME] = BUFFER_POINTER
weechat.infolist_free(INFOLIST_BUFFER)
return WRECON_BUFFERS
def get_buffer_channel():
global WRECON_SERVER, WRECON_CHANNEL
WRECON_BUFFER_NAME = '%s.%s' % (WRECON_SERVER, WRECON_CHANNEL)
WRECON_BUFFERS = get_buffers()
if WRECON_BUFFER_NAME in WRECON_BUFFERS:
return WRECON_BUFFERS[WRECON_BUFFER_NAME]
else:
return ''
#
##### END FUNCTION GET BUFFERS AND BUFFER OF REGISTERED CHANNEL
#####
#
# FUNCTION STATUS CHANNEL
# We need to know how many users are joined
def get_status_channel():
global WRECON_SERVER, WRECON_CHANNEL
INFOLIST_CHANNEL = weechat.infolist_get('irc_channel', '', WRECON_SERVER)
CHANNEL_STATUS = {}
DO_RECORD = False
while weechat.infolist_next(INFOLIST_CHANNEL):
CHANNEL_FIELDS = weechat.infolist_fields(INFOLIST_CHANNEL).split(",")
for CHANNEL_FIELD in CHANNEL_FIELDS:
(CHANNEL_FIELD_TYPE, CHANNEL_FIELD_NAME) = CHANNEL_FIELD.split(':', 1)
if CHANNEL_FIELD_TYPE == 'i':
CHANNEL_FIELD_VALUE = weechat.infolist_integer(INFOLIST_CHANNEL, CHANNEL_FIELD_NAME)
elif CHANNEL_FIELD_TYPE == 'p':
CHANNEL_FIELD_VALUE = weechat.infolist_pointer(INFOLIST_CHANNEL, CHANNEL_FIELD_NAME)
elif CHANNEL_FIELD_TYPE == 's':
CHANNEL_FIELD_VALUE = weechat.infolist_string(INFOLIST_CHANNEL, CHANNEL_FIELD_NAME)
elif CHANNEL_FIELD_TYPE == 'b':
CHANNEL_FIELD_VALUE = weechat.infolist_buffer(INFOLIST_CHANNEL, CHANNEL_FIELD_NAME)
elif CHANNEL_FIELD_TYPE == 't':
CHANNEL_FIELD_VALUE = weechat.infolist_time(INFOLIST_CHANNEL, CHANNEL_FIELD_NAME)
else:
CHANNEL_FIELD_VALUE = 'N/A'
if CHANNEL_FIELD_NAME == 'buffer_short_name' and CHANNEL_FIELD_VALUE == WRECON_CHANNEL:
DO_RECORD = True
elif CHANNEL_FIELD_NAME == 'buffer_short_name' and CHANNEL_FIELD_VALUE != WRECON_CHANNEL:
DO_RECORD = False
if DO_RECORD == True:
CHANNEL_STATUS[CHANNEL_FIELD_NAME] = CHANNEL_FIELD_VALUE
weechat.infolist_free(INFOLIST_CHANNEL)
if 'nicks_count' in CHANNEL_STATUS:
return CHANNEL_STATUS['nicks_count']
else:
return 0
#
##### END FUNCTION STATUS CHANNEL
#####
#
# FUNCTION GET STATUS SERVER
def get_status_server():
global WRECON_SERVER
INFOLIST_SERVER = weechat.infolist_get('irc_server', '', '')
SERVER_STATUS = {}
while weechat.infolist_next(INFOLIST_SERVER):
SERVER_NAME = weechat.infolist_string(INFOLIST_SERVER, 'name')
SERVER_STAT = weechat.infolist_integer(INFOLIST_SERVER, 'is_connected')
SERVER_STATUS[SERVER_NAME] = SERVER_STAT
weechat.infolist_free(INFOLIST_SERVER)
if WRECON_SERVER in SERVER_STATUS:
return SERVER_STATUS[WRECON_SERVER]
else:
return '0'
#
##### END FUNCTION GET STATUS SERVER
#####
#
# FUNCTION GET VERSION AND TIMESTAMP
def get_version_and_timestamp(INPUT_VERSION, INPUT_TIMESTAMP):
LIST_VERSION = INPUT_VERSION.split(' ')
OUTPUT_VERSION = LIST_VERSION[0].split('v')[0]
LIST_VERSION.pop(0)
OUTPUT_TIMESTAMP = INPUT_TIMESTAMP
if len(LIST_VERSION) > 0:
OUT_STAMP = ' '.join(LIST_VERSION)
OUTPUT_TIMESTAMP = '%s %s' % (OUT_STAMP, OUTPUT_TIMESTAMP)
return [OUTPUT_VERSION, OUTPUT_TIMESTAMP]
#
##### END FUNCTION GET VERSION AND TIMESTAMP
#####
#
# GET NICK INFO
def get_nick_info(TAGS, PREFIX):
# Get actual TIMESTAP of time in UTC as INT format, we no need FLOAT
ACTUAL_TIMESTAMP = int(datetime.datetime.utcnow().timestamp())
# Convert TIMESTAMP to human readable form also
# Both values will be in content of NICK info
# TIMESTAMP is used for easy comparing of last advertisement of remote BOT
YMD, HMS = str(datetime.datetime.utcfromtimestamp(ACTUAL_TIMESTAMP)).split(' ')
YR, MO, DY = YMD.split('-')
HR, MI, SC = HMS.split(':')
ACTUAL_DATE_TIME = YR + MO + DY + HR + MI + SC
NICK_NAME = TAGS.split(',')[3].split('_')[1]
HOST_NAME = TAGS.split(',')[4]
HOST_NAME = HOST_NAME.split('_')[1]
NICK_INFO = '%s|%s|%s|%s|%s' % (NICK_NAME, HOST_NAME, PREFIX, ACTUAL_DATE_TIME, ACTUAL_TIMESTAMP)
return NICK_INFO
#
##### END GET NICK INFO
#####
#
# FUNCTION IGNORE BUFFER COMMAND (do nothing)
def ignore_buffer_command(WEECHAT_DATA, BUFFER, DATE, TAGS, DISPLAYED, HIGHLIGHT, PREFIX, TARGET_BOT_ID, SOURCE_BOT_ID, COMMAND_ID, COMMAND_ARGUMENTS):
UNIQ_COMMAND_ID = SOURCE_BOT_ID + COMMAND_ID
cleanup_unique_command_id('REMOTE', UNIQ_COMMAND_ID)
return weechat.WEECHAT_RC_OK
#
##### END FUNCTION IGNORE BUFFER COMMAND
#####
#
# GET BASIC DATA OF REMOTE BOT
def get_basic_data_of_remote_bot(TAGS, PREFIX, COMMAND_ARGUMENTS):
COMMAND_ARGS = ' '.join(COMMAND_ARGUMENTS)
SOURCE_BOT_NAME = COMMAND_ARGS.split('[')[0].rstrip()
SOURCE_BOT_VERSION_DATA = COMMAND_ARGS.split('[')[1].split(']')[0]
# Not all advertised data contain time of version, so following condition
# will result proper data will be saved
if ' ' in SOURCE_BOT_VERSION_DATA:
SOURCE_BOT_VERSION = SOURCE_BOT_VERSION_DATA.split(' ')[0].split('v')[1]
SOURCE_BOT_VERSION_TIME = SOURCE_BOT_VERSION_DATA.split(' ')[1]
else:
SOURCE_BOT_VERSION = SOURCE_BOT_VERSION_DATA.split('v')[1]
SOURCE_BOT_VERSION_TIME = ''
SOURCE_BOT_NICK_INFO = get_nick_info(TAGS, PREFIX)