1# Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License, version 2.0, as
5# published by the Free Software Foundation.
6#
7# This program is also distributed with certain software (including
8# but not limited to OpenSSL) that is licensed under separate terms,
9# as designated in a particular file or component or in included license
10# documentation.  The authors of MySQL hereby grant you an
11# additional permission to link the program and your derivative works
12# with the separately licensed software that they have included with
13# MySQL.
14#
15# Without limiting anything contained in the foregoing, this file,
16# which is part of MySQL Connector/Python, is also subject to the
17# Universal FOSS Exception, version 1.0, a copy of which can be found at
18# http://oss.oracle.com/licenses/universal-foss-exception.
19#
20# This program is distributed in the hope that it will be useful, but
21# WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23# See the GNU General Public License, version 2.0, for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program; if not, write to the Free Software Foundation, Inc.,
27# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
28
29"""Various MySQL constants and character sets
30"""
31
32import ssl
33import warnings
34
35from .utils import make_abc
36from .errors import ProgrammingError
37from .charsets import MYSQL_CHARACTER_SETS
38
39MAX_PACKET_LENGTH = 16777215
40NET_BUFFER_LENGTH = 8192
41MAX_MYSQL_TABLE_COLUMNS = 4096
42# Flag used to send the Query Attributes with 0 (or more) parameters.
43PARAMETER_COUNT_AVAILABLE = 8
44
45DEFAULT_CONFIGURATION = {
46    'database': None,
47    'user': '',
48    'password': '',
49    'password1': '',
50    'password2': '',
51    'password3': '',
52    'host': '127.0.0.1',
53    'port': 3306,
54    'unix_socket': None,
55    'use_unicode': True,
56    'charset': 'utf8mb4',
57    'collation': None,
58    'converter_class': None,
59    'converter_str_fallback': False,
60    'autocommit': False,
61    'time_zone': None,
62    'sql_mode': None,
63    'get_warnings': False,
64    'raise_on_warnings': False,
65    'connection_timeout': None,
66    'client_flags': 0,
67    'compress': False,
68    'buffered': False,
69    'raw': False,
70    'ssl_ca': None,
71    'ssl_cert': None,
72    'ssl_key': None,
73    'ssl_verify_cert': False,
74    'ssl_verify_identity': False,
75    'ssl_cipher': None,
76    'tls_ciphersuites': None,
77    'ssl_disabled': False,
78    'tls_versions': None,
79    'passwd': None,
80    'db': None,
81    'connect_timeout': None,
82    'dsn': None,
83    'force_ipv6': False,
84    'auth_plugin': None,
85    'allow_local_infile': False,
86    'allow_local_infile_in_path': None,
87    'consume_results': False,
88    'conn_attrs': None,
89    'dns_srv': False,
90    'use_pure': False,
91    'krb_service_principal': None,
92    'oci_config_file': None
93}
94
95CNX_POOL_ARGS = ('pool_name', 'pool_size', 'pool_reset_session')
96
97TLS_VERSIONS = ["TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"]
98
99
100def flag_is_set(flag, flags):
101    """Checks if the flag is set
102
103    Returns boolean"""
104    if (flags & flag) > 0:
105        return True
106    return False
107
108
109def _obsolete_option(name, new_name, value):
110    warnings.warn('The option "{}" has been deprecated, use "{}" instead.'
111                  ''.format(name, new_name), category=DeprecationWarning)
112    return value
113
114
115class _Constants(object):
116    """
117    Base class for constants
118    """
119    prefix = ''
120    desc = {}
121
122    def __new__(cls):
123        raise TypeError("Can not instanciate from %s" % cls.__name__)
124
125    @classmethod
126    def get_desc(cls, name):
127        """Get description of given constant"""
128        try:
129            return cls.desc[name][1]
130        except:
131            return None
132
133    @classmethod
134    def get_info(cls, setid):
135        """Get information about given constant"""
136        for name, info in cls.desc.items():
137            if info[0] == setid:
138                return name
139        return None
140
141    @classmethod
142    def get_full_info(cls):
143        """get full information about given constant"""
144        res = ()
145        try:
146            res = ["%s : %s" % (k, v[1]) for k, v in cls.desc.items()]
147        except Exception as err:  # pylint: disable=W0703
148            res = ('No information found in constant class.%s' % err)
149
150        return res
151
152
153class _Flags(_Constants):
154    """Base class for classes describing flags
155    """
156
157    @classmethod
158    def get_bit_info(cls, value):
159        """Get the name of all bits set
160
161        Returns a list of strings."""
162        res = []
163        for name, info in cls.desc.items():
164            if value & info[0]:
165                res.append(name)
166        return res
167
168
169class FieldType(_Constants):
170    """MySQL Field Types
171    """
172    prefix = 'FIELD_TYPE_'
173    DECIMAL = 0x00
174    TINY = 0x01
175    SHORT = 0x02
176    LONG = 0x03
177    FLOAT = 0x04
178    DOUBLE = 0x05
179    NULL = 0x06
180    TIMESTAMP = 0x07
181    LONGLONG = 0x08
182    INT24 = 0x09
183    DATE = 0x0a
184    TIME = 0x0b
185    DATETIME = 0x0c
186    YEAR = 0x0d
187    NEWDATE = 0x0e
188    VARCHAR = 0x0f
189    BIT = 0x10
190    JSON = 0xf5
191    NEWDECIMAL = 0xf6
192    ENUM = 0xf7
193    SET = 0xf8
194    TINY_BLOB = 0xf9
195    MEDIUM_BLOB = 0xfa
196    LONG_BLOB = 0xfb
197    BLOB = 0xfc
198    VAR_STRING = 0xfd
199    STRING = 0xfe
200    GEOMETRY = 0xff
201
202    desc = {
203        'DECIMAL': (0x00, 'DECIMAL'),
204        'TINY': (0x01, 'TINY'),
205        'SHORT': (0x02, 'SHORT'),
206        'LONG': (0x03, 'LONG'),
207        'FLOAT': (0x04, 'FLOAT'),
208        'DOUBLE': (0x05, 'DOUBLE'),
209        'NULL': (0x06, 'NULL'),
210        'TIMESTAMP': (0x07, 'TIMESTAMP'),
211        'LONGLONG': (0x08, 'LONGLONG'),
212        'INT24': (0x09, 'INT24'),
213        'DATE': (0x0a, 'DATE'),
214        'TIME': (0x0b, 'TIME'),
215        'DATETIME': (0x0c, 'DATETIME'),
216        'YEAR': (0x0d, 'YEAR'),
217        'NEWDATE': (0x0e, 'NEWDATE'),
218        'VARCHAR': (0x0f, 'VARCHAR'),
219        'BIT': (0x10, 'BIT'),
220        'JSON': (0xf5, 'JSON'),
221        'NEWDECIMAL': (0xf6, 'NEWDECIMAL'),
222        'ENUM': (0xf7, 'ENUM'),
223        'SET': (0xf8, 'SET'),
224        'TINY_BLOB': (0xf9, 'TINY_BLOB'),
225        'MEDIUM_BLOB': (0xfa, 'MEDIUM_BLOB'),
226        'LONG_BLOB': (0xfb, 'LONG_BLOB'),
227        'BLOB': (0xfc, 'BLOB'),
228        'VAR_STRING': (0xfd, 'VAR_STRING'),
229        'STRING': (0xfe, 'STRING'),
230        'GEOMETRY': (0xff, 'GEOMETRY'),
231    }
232
233    @classmethod
234    def get_string_types(cls):
235        """Get the list of all string types"""
236        return [
237            cls.VARCHAR,
238            cls.ENUM,
239            cls.VAR_STRING, cls.STRING,
240        ]
241
242    @classmethod
243    def get_binary_types(cls):
244        """Get the list of all binary types"""
245        return [
246            cls.TINY_BLOB, cls.MEDIUM_BLOB,
247            cls.LONG_BLOB, cls.BLOB,
248        ]
249
250    @classmethod
251    def get_number_types(cls):
252        """Get the list of all number types"""
253        return [
254            cls.DECIMAL, cls.NEWDECIMAL,
255            cls.TINY, cls.SHORT, cls.LONG,
256            cls.FLOAT, cls.DOUBLE,
257            cls.LONGLONG, cls.INT24,
258            cls.BIT,
259            cls.YEAR,
260        ]
261
262    @classmethod
263    def get_timestamp_types(cls):
264        """Get the list of all timestamp types"""
265        return [
266            cls.DATETIME, cls.TIMESTAMP,
267        ]
268
269
270class FieldFlag(_Flags):
271    """MySQL Field Flags
272
273    Field flags as found in MySQL sources mysql-src/include/mysql_com.h
274    """
275    _prefix = ''
276    NOT_NULL = 1 << 0
277    PRI_KEY = 1 << 1
278    UNIQUE_KEY = 1 << 2
279    MULTIPLE_KEY = 1 << 3
280    BLOB = 1 << 4
281    UNSIGNED = 1 << 5
282    ZEROFILL = 1 << 6
283    BINARY = 1 << 7
284
285    ENUM = 1 << 8
286    AUTO_INCREMENT = 1 << 9
287    TIMESTAMP = 1 << 10
288    SET = 1 << 11
289
290    NO_DEFAULT_VALUE = 1 << 12
291    ON_UPDATE_NOW = 1 << 13
292    NUM = 1 << 14
293    PART_KEY = 1 << 15
294    GROUP = 1 << 14  # SAME AS NUM !!!!!!!????
295    UNIQUE = 1 << 16
296    BINCMP = 1 << 17
297
298    GET_FIXED_FIELDS = 1 << 18
299    FIELD_IN_PART_FUNC = 1 << 19
300    FIELD_IN_ADD_INDEX = 1 << 20
301    FIELD_IS_RENAMED = 1 << 21
302
303    desc = {
304        'NOT_NULL': (1 << 0, "Field can't be NULL"),
305        'PRI_KEY': (1 << 1, "Field is part of a primary key"),
306        'UNIQUE_KEY': (1 << 2, "Field is part of a unique key"),
307        'MULTIPLE_KEY': (1 << 3, "Field is part of a key"),
308        'BLOB': (1 << 4, "Field is a blob"),
309        'UNSIGNED': (1 << 5, "Field is unsigned"),
310        'ZEROFILL': (1 << 6, "Field is zerofill"),
311        'BINARY': (1 << 7, "Field is binary  "),
312        'ENUM': (1 << 8, "field is an enum"),
313        'AUTO_INCREMENT': (1 << 9, "field is a autoincrement field"),
314        'TIMESTAMP': (1 << 10, "Field is a timestamp"),
315        'SET': (1 << 11, "field is a set"),
316        'NO_DEFAULT_VALUE': (1 << 12, "Field doesn't have default value"),
317        'ON_UPDATE_NOW': (1 << 13, "Field is set to NOW on UPDATE"),
318        'NUM': (1 << 14, "Field is num (for clients)"),
319
320        'PART_KEY': (1 << 15, "Intern; Part of some key"),
321        'GROUP': (1 << 14, "Intern: Group field"),  # Same as NUM
322        'UNIQUE': (1 << 16, "Intern: Used by sql_yacc"),
323        'BINCMP': (1 << 17, "Intern: Used by sql_yacc"),
324        'GET_FIXED_FIELDS': (1 << 18, "Used to get fields in item tree"),
325        'FIELD_IN_PART_FUNC': (1 << 19, "Field part of partition func"),
326        'FIELD_IN_ADD_INDEX': (1 << 20, "Intern: Field used in ADD INDEX"),
327        'FIELD_IS_RENAMED': (1 << 21, "Intern: Field is being renamed"),
328    }
329
330
331class ServerCmd(_Constants):
332    """MySQL Server Commands
333    """
334    _prefix = 'COM_'
335    SLEEP = 0
336    QUIT = 1
337    INIT_DB = 2
338    QUERY = 3
339    FIELD_LIST = 4
340    CREATE_DB = 5
341    DROP_DB = 6
342    REFRESH = 7
343    SHUTDOWN = 8
344    STATISTICS = 9
345    PROCESS_INFO = 10
346    CONNECT = 11
347    PROCESS_KILL = 12
348    DEBUG = 13
349    PING = 14
350    TIME = 15
351    DELAYED_INSERT = 16
352    CHANGE_USER = 17
353    BINLOG_DUMP = 18
354    TABLE_DUMP = 19
355    CONNECT_OUT = 20
356    REGISTER_REPLICA = 21
357    STMT_PREPARE = 22
358    STMT_EXECUTE = 23
359    STMT_SEND_LONG_DATA = 24
360    STMT_CLOSE = 25
361    STMT_RESET = 26
362    SET_OPTION = 27
363    STMT_FETCH = 28
364    DAEMON = 29
365    BINLOG_DUMP_GTID = 30
366    RESET_CONNECTION = 31
367
368    desc = {
369        'SLEEP': (0, 'SLEEP'),
370        'QUIT': (1, 'QUIT'),
371        'INIT_DB': (2, 'INIT_DB'),
372        'QUERY': (3, 'QUERY'),
373        'FIELD_LIST': (4, 'FIELD_LIST'),
374        'CREATE_DB': (5, 'CREATE_DB'),
375        'DROP_DB': (6, 'DROP_DB'),
376        'REFRESH': (7, 'REFRESH'),
377        'SHUTDOWN': (8, 'SHUTDOWN'),
378        'STATISTICS': (9, 'STATISTICS'),
379        'PROCESS_INFO': (10, 'PROCESS_INFO'),
380        'CONNECT': (11, 'CONNECT'),
381        'PROCESS_KILL': (12, 'PROCESS_KILL'),
382        'DEBUG': (13, 'DEBUG'),
383        'PING': (14, 'PING'),
384        'TIME': (15, 'TIME'),
385        'DELAYED_INSERT': (16, 'DELAYED_INSERT'),
386        'CHANGE_USER': (17, 'CHANGE_USER'),
387        'BINLOG_DUMP': (18, 'BINLOG_DUMP'),
388        'TABLE_DUMP': (19, 'TABLE_DUMP'),
389        'CONNECT_OUT': (20, 'CONNECT_OUT'),
390        'REGISTER_REPLICA': (21, 'REGISTER_REPLICA'),
391        'STMT_PREPARE': (22, 'STMT_PREPARE'),
392        'STMT_EXECUTE': (23, 'STMT_EXECUTE'),
393        'STMT_SEND_LONG_DATA': (24, 'STMT_SEND_LONG_DATA'),
394        'STMT_CLOSE': (25, 'STMT_CLOSE'),
395        'STMT_RESET': (26, 'STMT_RESET'),
396        'SET_OPTION': (27, 'SET_OPTION'),
397        'STMT_FETCH': (28, 'STMT_FETCH'),
398        'DAEMON': (29, 'DAEMON'),
399        'BINLOG_DUMP_GTID': (30, 'BINLOG_DUMP_GTID'),
400        'RESET_CONNECTION': (31, 'RESET_CONNECTION'),
401    }
402
403
404class ClientFlag(_Flags):
405    """MySQL Client Flags
406
407    Client options as found in the MySQL sources mysql-src/include/mysql_com.h
408    """
409    LONG_PASSWD = 1 << 0
410    FOUND_ROWS = 1 << 1
411    LONG_FLAG = 1 << 2
412    CONNECT_WITH_DB = 1 << 3
413    NO_SCHEMA = 1 << 4
414    COMPRESS = 1 << 5
415    ODBC = 1 << 6
416    LOCAL_FILES = 1 << 7
417    IGNORE_SPACE = 1 << 8
418    PROTOCOL_41 = 1 << 9
419    INTERACTIVE = 1 << 10
420    SSL = 1 << 11
421    IGNORE_SIGPIPE = 1 << 12
422    TRANSACTIONS = 1 << 13
423    RESERVED = 1 << 14
424    SECURE_CONNECTION = 1 << 15
425    MULTI_STATEMENTS = 1 << 16
426    MULTI_RESULTS = 1 << 17
427    PS_MULTI_RESULTS = 1 << 18
428    PLUGIN_AUTH = 1 << 19
429    CONNECT_ARGS = 1 << 20
430    PLUGIN_AUTH_LENENC_CLIENT_DATA = 1 << 21
431    CAN_HANDLE_EXPIRED_PASSWORDS = 1 << 22
432    SESION_TRACK = 1 << 23
433    DEPRECATE_EOF = 1 << 24
434    CLIENT_QUERY_ATTRIBUTES = 1 << 27
435    SSL_VERIFY_SERVER_CERT = 1 << 30
436    REMEMBER_OPTIONS = 1 << 31
437
438    desc = {
439        'LONG_PASSWD': (1 << 0, 'New more secure passwords'),
440        'FOUND_ROWS': (1 << 1, 'Found instead of affected rows'),
441        'LONG_FLAG': (1 << 2, 'Get all column flags'),
442        'CONNECT_WITH_DB': (1 << 3, 'One can specify db on connect'),
443        'NO_SCHEMA': (1 << 4, "Don't allow database.table.column"),
444        'COMPRESS': (1 << 5, 'Can use compression protocol'),
445        'ODBC': (1 << 6, 'ODBC client'),
446        'LOCAL_FILES': (1 << 7, 'Can use LOAD DATA LOCAL'),
447        'IGNORE_SPACE': (1 << 8, "Ignore spaces before ''"),
448        'PROTOCOL_41': (1 << 9, 'New 4.1 protocol'),
449        'INTERACTIVE': (1 << 10, 'This is an interactive client'),
450        'SSL': (1 << 11, 'Switch to SSL after handshake'),
451        'IGNORE_SIGPIPE': (1 << 12, 'IGNORE sigpipes'),
452        'TRANSACTIONS': (1 << 13, 'Client knows about transactions'),
453        'RESERVED': (1 << 14, 'Old flag for 4.1 protocol'),
454        'SECURE_CONNECTION': (1 << 15, 'New 4.1 authentication'),
455        'MULTI_STATEMENTS': (1 << 16, 'Enable/disable multi-stmt support'),
456        'MULTI_RESULTS': (1 << 17, 'Enable/disable multi-results'),
457        'PS_MULTI_RESULTS': (1 << 18, 'Multi-results in PS-protocol'),
458        'PLUGIN_AUTH': (1 << 19, 'Client supports plugin authentication'),
459        'CONNECT_ARGS': (1 << 20, 'Client supports connection attributes'),
460        'PLUGIN_AUTH_LENENC_CLIENT_DATA': (1 << 21,
461                                           'Enable authentication response packet to be larger than 255 bytes'),
462        'CAN_HANDLE_EXPIRED_PASSWORDS': (1 << 22, "Don't close the connection for a connection with expired password"),
463        'SESION_TRACK': (1 << 23, 'Capable of handling server state change information'),
464        'DEPRECATE_EOF': (1 << 24, 'Client no longer needs EOF packet'),
465        'CLIENT_QUERY_ATTRIBUTES': (1 << 27, 'Support optional extension for query parameters'),
466        'SSL_VERIFY_SERVER_CERT': (1 << 30, ''),
467        'REMEMBER_OPTIONS': (1 << 31, ''),
468    }
469
470    default = [
471        LONG_PASSWD,
472        LONG_FLAG,
473        CONNECT_WITH_DB,
474        PROTOCOL_41,
475        TRANSACTIONS,
476        SECURE_CONNECTION,
477        MULTI_STATEMENTS,
478        MULTI_RESULTS,
479        CONNECT_ARGS,
480    ]
481
482    @classmethod
483    def get_default(cls):
484        """Get the default client options set
485
486        Returns a flag with all the default client options set"""
487        flags = 0
488        for option in cls.default:
489            flags |= option
490        return flags
491
492
493class ServerFlag(_Flags):
494    """MySQL Server Flags
495
496    Server flags as found in the MySQL sources mysql-src/include/mysql_com.h
497    """
498    _prefix = 'SERVER_'
499    STATUS_IN_TRANS = 1 << 0
500    STATUS_AUTOCOMMIT = 1 << 1
501    MORE_RESULTS_EXISTS = 1 << 3
502    QUERY_NO_GOOD_INDEX_USED = 1 << 4
503    QUERY_NO_INDEX_USED = 1 << 5
504    STATUS_CURSOR_EXISTS = 1 << 6
505    STATUS_LAST_ROW_SENT = 1 << 7
506    STATUS_DB_DROPPED = 1 << 8
507    STATUS_NO_BACKSLASH_ESCAPES = 1 << 9
508    SERVER_STATUS_METADATA_CHANGED = 1 << 10
509    SERVER_QUERY_WAS_SLOW = 1 << 11
510    SERVER_PS_OUT_PARAMS = 1 << 12
511    SERVER_STATUS_IN_TRANS_READONLY = 1 << 13
512    SERVER_SESSION_STATE_CHANGED = 1 << 14
513
514    desc = {
515        'SERVER_STATUS_IN_TRANS': (1 << 0,
516                                   'Transaction has started'),
517        'SERVER_STATUS_AUTOCOMMIT': (1 << 1,
518                                     'Server in auto_commit mode'),
519        'SERVER_MORE_RESULTS_EXISTS': (1 << 3,
520                                       'Multi query - '
521                                       'next query exists'),
522        'SERVER_QUERY_NO_GOOD_INDEX_USED': (1 << 4, ''),
523        'SERVER_QUERY_NO_INDEX_USED': (1 << 5, ''),
524        'SERVER_STATUS_CURSOR_EXISTS': (1 << 6,
525                                        'Set when server opened a read-only '
526                                        'non-scrollable cursor for a query.'),
527        'SERVER_STATUS_LAST_ROW_SENT': (1 << 7,
528                                        'Set when a read-only cursor is '
529                                        'exhausted'),
530        'SERVER_STATUS_DB_DROPPED': (1 << 8, 'A database was dropped'),
531        'SERVER_STATUS_NO_BACKSLASH_ESCAPES': (1 << 9, ''),
532        'SERVER_STATUS_METADATA_CHANGED': (1024,
533                                           'Set if after a prepared statement '
534                                           'reprepare we discovered that the '
535                                           'new statement returns a different '
536                                           'number of result set columns.'),
537        'SERVER_QUERY_WAS_SLOW': (2048, ''),
538        'SERVER_PS_OUT_PARAMS': (4096,
539                                 'To mark ResultSet containing output '
540                                 'parameter values.'),
541        'SERVER_STATUS_IN_TRANS_READONLY': (8192,
542                                            'Set if multi-statement '
543                                            'transaction is a read-only '
544                                            'transaction.'),
545        'SERVER_SESSION_STATE_CHANGED': (1 << 14,
546                                         'Session state has changed on the '
547                                         'server because of the execution of '
548                                         'the last statement'),
549    }
550
551
552class RefreshOption_meta(type):
553    @property
554    def SLAVE(self):
555        return _obsolete_option("RefreshOption.SLAVE", "RefreshOption.REPLICA",
556                                RefreshOption.REPLICA)
557
558@make_abc(RefreshOption_meta)
559class RefreshOption(_Constants):
560    """MySQL Refresh command options
561
562    Options used when sending the COM_REFRESH server command.
563    """
564    _prefix = 'REFRESH_'
565    GRANT = 1 << 0
566    LOG = 1 << 1
567    TABLES = 1 << 2
568    HOST = 1 << 3
569    STATUS = 1 << 4
570    THREADS = 1 << 5
571    REPLICA = 1 << 6
572
573    desc = {
574        'GRANT': (1 << 0, 'Refresh grant tables'),
575        'LOG': (1 << 1, 'Start on new log file'),
576        'TABLES': (1 << 2, 'close all tables'),
577        'HOST': (1 << 3, 'Flush host cache'),
578        'STATUS': (1 << 4, 'Flush status variables'),
579        'THREADS': (1 << 5, 'Flush thread cache'),
580        'REPLICA': (1 << 6, 'Reset source info and restart replica thread'),
581        'SLAVE': (1 << 6, 'Deprecated option; use REPLICA instead.'),
582    }
583
584
585class ShutdownType(_Constants):
586    """MySQL Shutdown types
587
588    Shutdown types used by the COM_SHUTDOWN server command.
589    """
590    _prefix = ''
591    SHUTDOWN_DEFAULT = 0
592    SHUTDOWN_WAIT_CONNECTIONS = 1
593    SHUTDOWN_WAIT_TRANSACTIONS = 2
594    SHUTDOWN_WAIT_UPDATES = 8
595    SHUTDOWN_WAIT_ALL_BUFFERS = 16
596    SHUTDOWN_WAIT_CRITICAL_BUFFERS = 17
597    KILL_QUERY = 254
598    KILL_CONNECTION = 255
599
600    desc = {
601        'SHUTDOWN_DEFAULT': (
602            SHUTDOWN_DEFAULT,
603            "defaults to SHUTDOWN_WAIT_ALL_BUFFERS"),
604        'SHUTDOWN_WAIT_CONNECTIONS': (
605            SHUTDOWN_WAIT_CONNECTIONS,
606            "wait for existing connections to finish"),
607        'SHUTDOWN_WAIT_TRANSACTIONS': (
608            SHUTDOWN_WAIT_TRANSACTIONS,
609            "wait for existing trans to finish"),
610        'SHUTDOWN_WAIT_UPDATES': (
611            SHUTDOWN_WAIT_UPDATES,
612            "wait for existing updates to finish"),
613        'SHUTDOWN_WAIT_ALL_BUFFERS': (
614            SHUTDOWN_WAIT_ALL_BUFFERS,
615            "flush InnoDB and other storage engine buffers"),
616        'SHUTDOWN_WAIT_CRITICAL_BUFFERS': (
617            SHUTDOWN_WAIT_CRITICAL_BUFFERS,
618            "don't flush InnoDB buffers, "
619            "flush other storage engines' buffers"),
620        'KILL_QUERY': (
621            KILL_QUERY,
622            "(no description)"),
623        'KILL_CONNECTION': (
624            KILL_CONNECTION,
625            "(no description)"),
626    }
627
628
629class CharacterSet(_Constants):
630    """MySQL supported character sets and collations
631
632    List of character sets with their collations supported by MySQL. This
633    maps to the character set we get from the server within the handshake
634    packet.
635
636    The list is hardcode so we avoid a database query when getting the
637    name of the used character set or collation.
638    """
639    desc = MYSQL_CHARACTER_SETS
640
641    # Multi-byte character sets which use 5c (backslash) in characters
642    slash_charsets = (1, 13, 28, 84, 87, 88)
643
644    @classmethod
645    def get_info(cls, setid):
646        """Retrieves character set information as tuple using an ID
647
648        Retrieves character set and collation information based on the
649        given MySQL ID.
650
651        Raises ProgrammingError when character set is not supported.
652
653        Returns a tuple.
654        """
655        try:
656            return cls.desc[setid][0:2]
657        except IndexError:
658            raise ProgrammingError(
659                "Character set '{0}' unsupported".format(setid))
660
661    @classmethod
662    def get_desc(cls, name):
663        """Retrieves character set information as string using an ID
664
665        Retrieves character set and collation information based on the
666        given MySQL ID.
667
668        Returns a tuple.
669        """
670        try:
671            return "%s/%s" % cls.get_info(name)
672        except:
673            raise
674
675    @classmethod
676    def get_default_collation(cls, charset):
677        """Retrieves the default collation for given character set
678
679        Raises ProgrammingError when character set is not supported.
680
681        Returns list (collation, charset, index)
682        """
683        if isinstance(charset, int):
684            try:
685                info = cls.desc[charset]
686                return info[1], info[0], charset
687            except:
688                ProgrammingError("Character set ID '%s' unsupported." % (
689                    charset))
690
691        for cid, info in enumerate(cls.desc):
692            if info is None:
693                continue
694            if info[0] == charset and info[2] is True:
695                return info[1], info[0], cid
696
697        raise ProgrammingError("Character set '%s' unsupported." % (charset))
698
699    @classmethod
700    def get_charset_info(cls, charset=None, collation=None):
701        """Get character set information using charset name and/or collation
702
703        Retrieves character set and collation information given character
704        set name and/or a collation name.
705        If charset is an integer, it will look up the character set based
706        on the MySQL's ID.
707        For example:
708            get_charset_info('utf8',None)
709            get_charset_info(collation='utf8_general_ci')
710            get_charset_info(47)
711
712        Raises ProgrammingError when character set is not supported.
713
714        Returns a tuple with (id, characterset name, collation)
715        """
716        if isinstance(charset, int):
717            try:
718                info = cls.desc[charset]
719                return (charset, info[0], info[1])
720            except IndexError:
721                ProgrammingError("Character set ID {0} unknown.".format(
722                    charset))
723
724        if charset is not None and collation is None:
725            info = cls.get_default_collation(charset)
726            return (info[2], info[1], info[0])
727        elif charset is None and collation is not None:
728            for cid, info in enumerate(cls.desc):
729                if info is None:
730                    continue
731                if collation == info[1]:
732                    return (cid, info[0], info[1])
733            raise ProgrammingError("Collation '{0}' unknown.".format(collation))
734        else:
735            for cid, info in enumerate(cls.desc):
736                if info is None:
737                    continue
738                if info[0] == charset and info[1] == collation:
739                    return (cid, info[0], info[1])
740            _ = cls.get_default_collation(charset)
741            raise ProgrammingError("Collation '{0}' unknown.".format(collation))
742
743    @classmethod
744    def get_supported(cls):
745        """Retrieves a list with names of all supproted character sets
746
747        Returns a tuple.
748        """
749        res = []
750        for info in cls.desc:
751            if info and info[0] not in res:
752                res.append(info[0])
753        return tuple(res)
754
755
756class SQLMode(_Constants):
757    """MySQL SQL Modes
758
759    The numeric values of SQL Modes are not interesting, only the names
760    are used when setting the SQL_MODE system variable using the MySQL
761    SET command.
762
763    See http://dev.mysql.com/doc/refman/5.6/en/server-sql-mode.html
764    """
765    _prefix = 'MODE_'
766    REAL_AS_FLOAT = 'REAL_AS_FLOAT'
767    PIPES_AS_CONCAT = 'PIPES_AS_CONCAT'
768    ANSI_QUOTES = 'ANSI_QUOTES'
769    IGNORE_SPACE = 'IGNORE_SPACE'
770    NOT_USED = 'NOT_USED'
771    ONLY_FULL_GROUP_BY = 'ONLY_FULL_GROUP_BY'
772    NO_UNSIGNED_SUBTRACTION = 'NO_UNSIGNED_SUBTRACTION'
773    NO_DIR_IN_CREATE = 'NO_DIR_IN_CREATE'
774    POSTGRESQL = 'POSTGRESQL'
775    ORACLE = 'ORACLE'
776    MSSQL = 'MSSQL'
777    DB2 = 'DB2'
778    MAXDB = 'MAXDB'
779    NO_KEY_OPTIONS = 'NO_KEY_OPTIONS'
780    NO_TABLE_OPTIONS = 'NO_TABLE_OPTIONS'
781    NO_FIELD_OPTIONS = 'NO_FIELD_OPTIONS'
782    MYSQL323 = 'MYSQL323'
783    MYSQL40 = 'MYSQL40'
784    ANSI = 'ANSI'
785    NO_AUTO_VALUE_ON_ZERO = 'NO_AUTO_VALUE_ON_ZERO'
786    NO_BACKSLASH_ESCAPES = 'NO_BACKSLASH_ESCAPES'
787    STRICT_TRANS_TABLES = 'STRICT_TRANS_TABLES'
788    STRICT_ALL_TABLES = 'STRICT_ALL_TABLES'
789    NO_ZERO_IN_DATE = 'NO_ZERO_IN_DATE'
790    NO_ZERO_DATE = 'NO_ZERO_DATE'
791    INVALID_DATES = 'INVALID_DATES'
792    ERROR_FOR_DIVISION_BY_ZERO = 'ERROR_FOR_DIVISION_BY_ZERO'
793    TRADITIONAL = 'TRADITIONAL'
794    NO_AUTO_CREATE_USER = 'NO_AUTO_CREATE_USER'
795    HIGH_NOT_PRECEDENCE = 'HIGH_NOT_PRECEDENCE'
796    NO_ENGINE_SUBSTITUTION = 'NO_ENGINE_SUBSTITUTION'
797    PAD_CHAR_TO_FULL_LENGTH = 'PAD_CHAR_TO_FULL_LENGTH'
798
799    @classmethod
800    def get_desc(cls, name):
801        raise NotImplementedError
802
803    @classmethod
804    def get_info(cls, setid):
805        raise NotImplementedError
806
807    @classmethod
808    def get_full_info(cls):
809        """Returns a sequence of all available SQL Modes
810
811        This class method returns a tuple containing all SQL Mode names. The
812        names will be alphabetically sorted.
813
814        Returns a tuple.
815        """
816        res = []
817        for key in vars(cls).keys():
818            if not key.startswith('_') \
819                    and not hasattr(getattr(cls, key), '__call__'):
820                res.append(key)
821        return tuple(sorted(res))
822
823CONN_ATTRS_DN = ["_pid", "_platform", "_source_host", "_client_name",
824                 "_client_license", "_client_version", "_os", "_connector_name",
825                 "_connector_license", "_connector_version"]
826
827# TLS v1.0 cipher suites IANI to OpenSSL name translation
828TLSV1_CIPHER_SUITES = {
829    "TLS_RSA_WITH_NULL_MD5": "NULL-MD5",
830    "TLS_RSA_WITH_NULL_SHA": "NULL-SHA",
831    "TLS_RSA_WITH_RC4_128_MD5": "RC4-MD5",
832    "TLS_RSA_WITH_RC4_128_SHA": "RC4-SHA",
833    "TLS_RSA_WITH_IDEA_CBC_SHA": "IDEA-CBC-SHA",
834    "TLS_RSA_WITH_3DES_EDE_CBC_SHA": "DES-CBC3-SHA",
835
836    "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA": "Not implemented.",
837    "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA": "Not implemented.",
838    "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA": "DHE-DSS-DES-CBC3-SHA",
839    "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA": "DHE-RSA-DES-CBC3-SHA",
840
841    "TLS_DH_anon_WITH_RC4_128_MD5": "ADH-RC4-MD5",
842    "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA": "ADH-DES-CBC3-SHA",
843
844    # AES cipher suites from RFC3268, extending TLS v1.0
845    "TLS_RSA_WITH_AES_128_CBC_SHA": "AES128-SHA",
846    "TLS_RSA_WITH_AES_256_CBC_SHA": "AES256-SHA",
847
848    "TLS_DH_DSS_WITH_AES_128_CBC_SHA": "DH-DSS-AES128-SHA",
849    "TLS_DH_DSS_WITH_AES_256_CBC_SHA": "DH-DSS-AES256-SHA",
850    "TLS_DH_RSA_WITH_AES_128_CBC_SHA": "DH-RSA-AES128-SHA",
851    "TLS_DH_RSA_WITH_AES_256_CBC_SHA": "DH-RSA-AES256-SHA",
852
853    "TLS_DHE_DSS_WITH_AES_128_CBC_SHA": "DHE-DSS-AES128-SHA",
854    "TLS_DHE_DSS_WITH_AES_256_CBC_SHA": "DHE-DSS-AES256-SHA",
855    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA": "DHE-RSA-AES128-SHA",
856    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA": "DHE-RSA-AES256-SHA",
857
858    "TLS_DH_anon_WITH_AES_128_CBC_SHA": "ADH-AES128-SHA",
859    "TLS_DH_anon_WITH_AES_256_CBC_SHA": "ADH-AES256-SHA",
860
861    # Camellia cipher suites from RFC4132, extending TLS v1.0
862    "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA": "CAMELLIA128-SHA",
863    "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA": "CAMELLIA256-SHA",
864
865    "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA": "DH-DSS-CAMELLIA128-SHA",
866    "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA": "DH-DSS-CAMELLIA256-SHA",
867    "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA": "DH-RSA-CAMELLIA128-SHA",
868    "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA": "DH-RSA-CAMELLIA256-SHA",
869
870    "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA": "DHE-DSS-CAMELLIA128-SHA",
871    "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA": "DHE-DSS-CAMELLIA256-SHA",
872    "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA": "DHE-RSA-CAMELLIA128-SHA",
873    "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA": "DHE-RSA-CAMELLIA256-SHA",
874
875    "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA": "ADH-CAMELLIA128-SHA",
876    "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA": "ADH-CAMELLIA256-SHA",
877
878    # SEED cipher suites from RFC4162, extending TLS v1.0
879    "TLS_RSA_WITH_SEED_CBC_SHA": "SEED-SHA",
880
881    "TLS_DH_DSS_WITH_SEED_CBC_SHA": "DH-DSS-SEED-SHA",
882    "TLS_DH_RSA_WITH_SEED_CBC_SHA": "DH-RSA-SEED-SHA",
883
884    "TLS_DHE_DSS_WITH_SEED_CBC_SHA": "DHE-DSS-SEED-SHA",
885    "TLS_DHE_RSA_WITH_SEED_CBC_SHA": "DHE-RSA-SEED-SHA",
886
887    "TLS_DH_anon_WITH_SEED_CBC_SHA": "ADH-SEED-SHA",
888
889    # GOST cipher suites from draft-chudov-cryptopro-cptls, extending TLS v1.0
890    "TLS_GOSTR341094_WITH_28147_CNT_IMIT": "GOST94-GOST89-GOST89",
891    "TLS_GOSTR341001_WITH_28147_CNT_IMIT": "GOST2001-GOST89-GOST89",
892    "TLS_GOSTR341094_WITH_NULL_GOSTR3411": "GOST94-NULL-GOST94",
893    "TLS_GOSTR341001_WITH_NULL_GOSTR3411": "GOST2001-NULL-GOST94"}
894
895# TLS v1.1 cipher suites IANI to OpenSSL name translation
896TLSV1_1_CIPHER_SUITES = TLSV1_CIPHER_SUITES
897
898# TLS v1.2 cipher suites IANI to OpenSSL name translation
899TLSV1_2_CIPHER_SUITES = {
900    "TLS_RSA_WITH_NULL_SHA256": "NULL-SHA256",
901
902    "TLS_RSA_WITH_AES_128_CBC_SHA256": "AES128-SHA256",
903    "TLS_RSA_WITH_AES_256_CBC_SHA256": "AES256-SHA256",
904    "TLS_RSA_WITH_AES_128_GCM_SHA256": "AES128-GCM-SHA256",
905    "TLS_RSA_WITH_AES_256_GCM_SHA384": "AES256-GCM-SHA384",
906
907    "TLS_DH_RSA_WITH_AES_128_CBC_SHA256": "DH-RSA-AES128-SHA256",
908    "TLS_DH_RSA_WITH_AES_256_CBC_SHA256": "DH-RSA-AES256-SHA256",
909    "TLS_DH_RSA_WITH_AES_128_GCM_SHA256": "DH-RSA-AES128-GCM-SHA256",
910    "TLS_DH_RSA_WITH_AES_256_GCM_SHA384": "DH-RSA-AES256-GCM-SHA384",
911
912    "TLS_DH_DSS_WITH_AES_128_CBC_SHA256": "DH-DSS-AES128-SHA256",
913    "TLS_DH_DSS_WITH_AES_256_CBC_SHA256": "DH-DSS-AES256-SHA256",
914    "TLS_DH_DSS_WITH_AES_128_GCM_SHA256": "DH-DSS-AES128-GCM-SHA256",
915    "TLS_DH_DSS_WITH_AES_256_GCM_SHA384": "DH-DSS-AES256-GCM-SHA384",
916
917    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256": "DHE-RSA-AES128-SHA256",
918    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256": "DHE-RSA-AES256-SHA256",
919    "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256": "DHE-RSA-AES128-GCM-SHA256",
920    "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384": "DHE-RSA-AES256-GCM-SHA384",
921
922    "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256": "DHE-DSS-AES128-SHA256",
923    "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256": "DHE-DSS-AES256-SHA256",
924    "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256": "DHE-DSS-AES128-GCM-SHA256",
925    "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384": "DHE-DSS-AES256-GCM-SHA384",
926
927    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": "ECDHE-RSA-AES128-SHA256",
928    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384": "ECDHE-RSA-AES256-SHA384",
929    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": "ECDHE-RSA-AES128-GCM-SHA256",
930    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": "ECDHE-RSA-AES256-GCM-SHA384",
931
932    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": "ECDHE-ECDSA-AES128-SHA256",
933    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384": "ECDHE-ECDSA-AES256-SHA384",
934    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": "ECDHE-ECDSA-AES128-GCM-SHA256",
935    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": "ECDHE-ECDSA-AES256-GCM-SHA384",
936
937    "TLS_DH_anon_WITH_AES_128_CBC_SHA256": "ADH-AES128-SHA256",
938    "TLS_DH_anon_WITH_AES_256_CBC_SHA256": "ADH-AES256-SHA256",
939    "TLS_DH_anon_WITH_AES_128_GCM_SHA256": "ADH-AES128-GCM-SHA256",
940    "TLS_DH_anon_WITH_AES_256_GCM_SHA384": "ADH-AES256-GCM-SHA384",
941
942    "RSA_WITH_AES_128_CCM": "AES128-CCM",
943    "RSA_WITH_AES_256_CCM": "AES256-CCM",
944    "DHE_RSA_WITH_AES_128_CCM": "DHE-RSA-AES128-CCM",
945    "DHE_RSA_WITH_AES_256_CCM": "DHE-RSA-AES256-CCM",
946    "RSA_WITH_AES_128_CCM_8": "AES128-CCM8",
947    "RSA_WITH_AES_256_CCM_8": "AES256-CCM8",
948    "DHE_RSA_WITH_AES_128_CCM_8": "DHE-RSA-AES128-CCM8",
949    "DHE_RSA_WITH_AES_256_CCM_8": "DHE-RSA-AES256-CCM8",
950    "ECDHE_ECDSA_WITH_AES_128_CCM": "ECDHE-ECDSA-AES128-CCM",
951    "ECDHE_ECDSA_WITH_AES_256_CCM": "ECDHE-ECDSA-AES256-CCM",
952    "ECDHE_ECDSA_WITH_AES_128_CCM_8": "ECDHE-ECDSA-AES128-CCM8",
953    "ECDHE_ECDSA_WITH_AES_256_CCM_8": "ECDHE-ECDSA-AES256-CCM8",
954
955    # ARIA cipher suites from RFC6209, extending TLS v1.2
956    "TLS_RSA_WITH_ARIA_128_GCM_SHA256": "ARIA128-GCM-SHA256",
957    "TLS_RSA_WITH_ARIA_256_GCM_SHA384": "ARIA256-GCM-SHA384",
958    "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256": "DHE-RSA-ARIA128-GCM-SHA256",
959    "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384": "DHE-RSA-ARIA256-GCM-SHA384",
960    "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256": "DHE-DSS-ARIA128-GCM-SHA256",
961    "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384": "DHE-DSS-ARIA256-GCM-SHA384",
962    "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256": "ECDHE-ECDSA-ARIA128-GCM-SHA256",
963    "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384": "ECDHE-ECDSA-ARIA256-GCM-SHA384",
964    "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256": "ECDHE-ARIA128-GCM-SHA256",
965    "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384": "ECDHE-ARIA256-GCM-SHA384",
966    "TLS_PSK_WITH_ARIA_128_GCM_SHA256": "PSK-ARIA128-GCM-SHA256",
967    "TLS_PSK_WITH_ARIA_256_GCM_SHA384": "PSK-ARIA256-GCM-SHA384",
968    "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256": "DHE-PSK-ARIA128-GCM-SHA256",
969    "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384": "DHE-PSK-ARIA256-GCM-SHA384",
970    "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256": "RSA-PSK-ARIA128-GCM-SHA256",
971    "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384": "RSA-PSK-ARIA256-GCM-SHA384",
972
973    # Camellia HMAC-Based cipher suites from RFC6367, extending TLS v1.2
974    "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256": "ECDHE-ECDSA-CAMELLIA128-SHA256",
975    "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384": "ECDHE-ECDSA-CAMELLIA256-SHA384",
976    "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256": "ECDHE-RSA-CAMELLIA128-SHA256",
977    "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384": "ECDHE-RSA-CAMELLIA256-SHA384",
978
979    # Pre-shared keying (PSK) cipher suites",
980    "PSK_WITH_NULL_SHA": "PSK-NULL-SHA",
981    "DHE_PSK_WITH_NULL_SHA": "DHE-PSK-NULL-SHA",
982    "RSA_PSK_WITH_NULL_SHA": "RSA-PSK-NULL-SHA",
983
984    "PSK_WITH_RC4_128_SHA": "PSK-RC4-SHA",
985    "PSK_WITH_3DES_EDE_CBC_SHA": "PSK-3DES-EDE-CBC-SHA",
986    "PSK_WITH_AES_128_CBC_SHA": "PSK-AES128-CBC-SHA",
987    "PSK_WITH_AES_256_CBC_SHA": "PSK-AES256-CBC-SHA",
988
989    "DHE_PSK_WITH_RC4_128_SHA": "DHE-PSK-RC4-SHA",
990    "DHE_PSK_WITH_3DES_EDE_CBC_SHA": "DHE-PSK-3DES-EDE-CBC-SHA",
991    "DHE_PSK_WITH_AES_128_CBC_SHA": "DHE-PSK-AES128-CBC-SHA",
992    "DHE_PSK_WITH_AES_256_CBC_SHA": "DHE-PSK-AES256-CBC-SHA",
993
994    "RSA_PSK_WITH_RC4_128_SHA": "RSA-PSK-RC4-SHA",
995    "RSA_PSK_WITH_3DES_EDE_CBC_SHA": "RSA-PSK-3DES-EDE-CBC-SHA",
996    "RSA_PSK_WITH_AES_128_CBC_SHA": "RSA-PSK-AES128-CBC-SHA",
997    "RSA_PSK_WITH_AES_256_CBC_SHA": "RSA-PSK-AES256-CBC-SHA",
998
999    "PSK_WITH_AES_128_GCM_SHA256": "PSK-AES128-GCM-SHA256",
1000    "PSK_WITH_AES_256_GCM_SHA384": "PSK-AES256-GCM-SHA384",
1001    "DHE_PSK_WITH_AES_128_GCM_SHA256": "DHE-PSK-AES128-GCM-SHA256",
1002    "DHE_PSK_WITH_AES_256_GCM_SHA384": "DHE-PSK-AES256-GCM-SHA384",
1003    "RSA_PSK_WITH_AES_128_GCM_SHA256": "RSA-PSK-AES128-GCM-SHA256",
1004    "RSA_PSK_WITH_AES_256_GCM_SHA384": "RSA-PSK-AES256-GCM-SHA384",
1005
1006    "PSK_WITH_AES_128_CBC_SHA256": "PSK-AES128-CBC-SHA256",
1007    "PSK_WITH_AES_256_CBC_SHA384": "PSK-AES256-CBC-SHA384",
1008    "PSK_WITH_NULL_SHA256": "PSK-NULL-SHA256",
1009    "PSK_WITH_NULL_SHA384": "PSK-NULL-SHA384",
1010    "DHE_PSK_WITH_AES_128_CBC_SHA256": "DHE-PSK-AES128-CBC-SHA256",
1011    "DHE_PSK_WITH_AES_256_CBC_SHA384": "DHE-PSK-AES256-CBC-SHA384",
1012    "DHE_PSK_WITH_NULL_SHA256": "DHE-PSK-NULL-SHA256",
1013    "DHE_PSK_WITH_NULL_SHA384": "DHE-PSK-NULL-SHA384",
1014    "RSA_PSK_WITH_AES_128_CBC_SHA256": "RSA-PSK-AES128-CBC-SHA256",
1015    "RSA_PSK_WITH_AES_256_CBC_SHA384": "RSA-PSK-AES256-CBC-SHA384",
1016    "RSA_PSK_WITH_NULL_SHA256": "RSA-PSK-NULL-SHA256",
1017    "RSA_PSK_WITH_NULL_SHA384": "RSA-PSK-NULL-SHA384",
1018
1019    "ECDHE_PSK_WITH_RC4_128_SHA": "ECDHE-PSK-RC4-SHA",
1020    "ECDHE_PSK_WITH_3DES_EDE_CBC_SHA": "ECDHE-PSK-3DES-EDE-CBC-SHA",
1021    "ECDHE_PSK_WITH_AES_128_CBC_SHA": "ECDHE-PSK-AES128-CBC-SHA",
1022    "ECDHE_PSK_WITH_AES_256_CBC_SHA": "ECDHE-PSK-AES256-CBC-SHA",
1023    "ECDHE_PSK_WITH_AES_128_CBC_SHA256": "ECDHE-PSK-AES128-CBC-SHA256",
1024    "ECDHE_PSK_WITH_AES_256_CBC_SHA384": "ECDHE-PSK-AES256-CBC-SHA384",
1025    "ECDHE_PSK_WITH_NULL_SHA": "ECDHE-PSK-NULL-SHA",
1026    "ECDHE_PSK_WITH_NULL_SHA256": "ECDHE-PSK-NULL-SHA256",
1027    "ECDHE_PSK_WITH_NULL_SHA384": "ECDHE-PSK-NULL-SHA384",
1028
1029    "PSK_WITH_CAMELLIA_128_CBC_SHA256": "PSK-CAMELLIA128-SHA256",
1030    "PSK_WITH_CAMELLIA_256_CBC_SHA384": "PSK-CAMELLIA256-SHA384",
1031
1032    "DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": "DHE-PSK-CAMELLIA128-SHA256",
1033    "DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": "DHE-PSK-CAMELLIA256-SHA384",
1034
1035    "RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256": "RSA-PSK-CAMELLIA128-SHA256",
1036    "RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384": "RSA-PSK-CAMELLIA256-SHA384",
1037
1038    "ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": "ECDHE-PSK-CAMELLIA128-SHA256",
1039    "ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": "ECDHE-PSK-CAMELLIA256-SHA384",
1040
1041    "PSK_WITH_AES_128_CCM": "PSK-AES128-CCM",
1042    "PSK_WITH_AES_256_CCM": "PSK-AES256-CCM",
1043    "DHE_PSK_WITH_AES_128_CCM": "DHE-PSK-AES128-CCM",
1044    "DHE_PSK_WITH_AES_256_CCM": "DHE-PSK-AES256-CCM",
1045    "PSK_WITH_AES_128_CCM_8": "PSK-AES128-CCM8",
1046    "PSK_WITH_AES_256_CCM_8": "PSK-AES256-CCM8",
1047    "DHE_PSK_WITH_AES_128_CCM_8": "DHE-PSK-AES128-CCM8",
1048    "DHE_PSK_WITH_AES_256_CCM_8": "DHE-PSK-AES256-CCM8",
1049
1050    # ChaCha20-Poly1305 cipher suites, extending TLS v1.2
1051    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "ECDHE-RSA-CHACHA20-POLY1305",
1052    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": "ECDHE-ECDSA-CHACHA20-POLY1305",
1053    "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "DHE-RSA-CHACHA20-POLY1305",
1054    "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256": "PSK-CHACHA20-POLY1305",
1055    "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256": "ECDHE-PSK-CHACHA20-POLY1305",
1056    "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256": "DHE-PSK-CHACHA20-POLY1305",
1057    "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256": "RSA-PSK-CHACHA20-POLY1305"}
1058
1059# TLS v1.3 cipher suites IANI to OpenSSL name translation
1060TLSV1_3_CIPHER_SUITES = {
1061    "TLS_AES_128_GCM_SHA256": "TLS_AES_128_GCM_SHA256",
1062    "TLS_AES_256_GCM_SHA384": "TLS_AES_256_GCM_SHA384",
1063    "TLS_CHACHA20_POLY1305_SHA256": "TLS_CHACHA20_POLY1305_SHA256",
1064    "TLS_AES_128_CCM_SHA256": "TLS_AES_128_CCM_SHA256",
1065    "TLS_AES_128_CCM_8_SHA256": "TLS_AES_128_CCM_8_SHA256"}
1066
1067TLS_CIPHER_SUITES = {
1068    "TLSv1": TLSV1_CIPHER_SUITES,
1069    "TLSv1.1": TLSV1_1_CIPHER_SUITES,
1070    "TLSv1.2": TLSV1_2_CIPHER_SUITES,
1071    "TLSv1.3": TLSV1_3_CIPHER_SUITES}
1072
1073OPENSSL_CS_NAMES = {
1074    "TLSv1": TLSV1_CIPHER_SUITES.values(),
1075    "TLSv1.1": TLSV1_1_CIPHER_SUITES.values(),
1076    "TLSv1.2": TLSV1_2_CIPHER_SUITES.values(),
1077    "TLSv1.3": TLSV1_3_CIPHER_SUITES.values()}
1078