File: message.pyx

package info (click to toggle)
python-gssapi 1.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 876 kB
  • sloc: python: 3,707; sh: 198; makefile: 154; ansic: 60
file content (280 lines) | stat: -rw-r--r-- 9,763 bytes parent folder | download | duplicates (3)
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
GSSAPI="BASE"  # This ensures that a full module is generated by Cython

from gssapi.raw.cython_types cimport *
from gssapi.raw.sec_contexts cimport SecurityContext

from gssapi.raw.misc import GSSError
from gssapi.raw.named_tuples import WrapResult, UnwrapResult


cdef extern from "python_gssapi.h":
    OM_uint32 gss_get_mic(OM_uint32 *min_stat,
                          const gss_ctx_id_t context,
                          gss_qop_t qop,
                          const gss_buffer_t message,
                          gss_buffer_t output_token) nogil

    OM_uint32 gss_verify_mic(OM_uint32 *min_stat,
                             const gss_ctx_id_t context,
                             const gss_buffer_t message,
                             const gss_buffer_t token,
                             gss_qop_t *qop) nogil

    OM_uint32 gss_wrap_size_limit(OM_uint32 *min_stat,
                                  const gss_ctx_id_t context,
                                  int conf_req,
                                  gss_qop_t qop,
                                  OM_uint32 max_output_size,
                                  OM_uint32 *max_input_size) nogil

    OM_uint32 gss_wrap(OM_uint32 *min_stat,
                       const gss_ctx_id_t context,
                       int conf_req,
                       gss_qop_t qop,
                       const gss_buffer_t input_message,
                       int *conf_used,
                       gss_buffer_t output_message) nogil

    OM_uint32 gss_unwrap(OM_uint32 *min_stat,
                         const gss_ctx_id_t context,
                         const gss_buffer_t input_message,
                         gss_buffer_t output_message,
                         int *conf_used,
                         gss_qop_t *qop) nogil


def get_mic(SecurityContext context not None, message, qop=None):
    """
    get_mic(context, message, qop=None)
    Generate a MIC for a message.

    This method generates a Message Integrity Check token for the
    given message.  This can be separately trasmitted to the other
    entity, unlike wrap, which bundles the MIC and the message
    together.

    Args:
        context (~gssapi.raw.sec_contexts.SecurityContext): the current
            security context
        message (bytes): the message for which to generate the MIC
        qop (int): the requested Quality of Protection
            (or None to use the default)

    Returns:
        bytes: the generated MIC token

    Raises:
        ~gssapi.exceptions.ExpiredContextError
        ~gssapi.exceptions.MissingContextError
        ~gssapi.exceptions.BadQoPError
    """

    cdef gss_buffer_desc message_buffer = gss_buffer_desc(len(message),
                                                          message)
    cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT

    # GSS_C_EMPYT_BUFFER
    cdef gss_buffer_desc token_buffer = gss_buffer_desc(0, NULL)

    cdef OM_uint32 maj_stat, min_stat

    with nogil:
        maj_stat = gss_get_mic(&min_stat, context.raw_ctx, qop_req,
                               &message_buffer, &token_buffer)

    if maj_stat == GSS_S_COMPLETE:
        res = (<char*>token_buffer.value)[:token_buffer.length]
        gss_release_buffer(&min_stat, &token_buffer)
        return res
    else:
        raise GSSError(maj_stat, min_stat)


def verify_mic(SecurityContext context not None, message, token):
    """
    verify_mic(context, message, token)
    Verify that a MIC matches a message.

    This method verifies that the given MIC matches the given message.
    If the MIC does not match the given message, an exception will
    be raised.

    Args:
        context (~gssapi.raw.sec_contexts.SecurityContext): the current
            security context
        message (bytes): the message in question
        token (bytes): the MIC token in question

    Returns:
        int: the QoP used.

    Raises:
        ~gssapi.exceptions.InvalidTokenError
        ~gssapi.exceptions.BadMICError
        ~gssapi.exceptions.DuplicateTokenError
        ~gssapi.exceptions.ExpiredTokenError
        ~gssapi.exceptions.TokenTooLateError
        ~gssapi.exceptions.TokenTooEarlyError
        ~gssapi.exceptions.ExpiredContextError
        ~gssapi.exceptions.MissingContextError
    """

    cdef gss_buffer_desc message_buffer = gss_buffer_desc(len(message),
                                                          message)
    cdef gss_buffer_desc token_buffer = gss_buffer_desc(len(token), token)

    cdef gss_qop_t qop_state

    cdef OM_uint32 maj_stat, min_stat

    with nogil:
        maj_stat = gss_verify_mic(&min_stat, context.raw_ctx, &message_buffer,
                                  &token_buffer, &qop_state)

    if maj_stat == GSS_S_COMPLETE:
        return qop_state
    else:
        raise GSSError(maj_stat, min_stat)


def wrap_size_limit(SecurityContext context not None, OM_uint32 output_size,
                    confidential=True, qop=None):
    """
    wrap_size_limit(context, output_size, confidential=True, qop=None)
    Calculate the max message size.

    This method calculates the unwrapped/unencrypted message size for
    the given maximum wrapped/encrypted message size.

    Args:
        context (~gssapi.raw.sec_contexts.SecurityContext): the current
            security context
        output_size (int): the maximum desired wrapped/encrypted message size
        confidential (bool): whether or not confidentiality is being used
        qop (int): the QoP that will be when you actually call wrap
            (or None for the default QoP)

    Returns:
        int: the maximum unencrypted/unwrapped message size

    Raises:
        ~gssapi.exceptions.MissingContextError
        ~gssapi.exceptions.ExpiredContextError
        ~gssapi.exceptions.BadQoPError
    """

    cdef int conf_req = confidential
    cdef OM_uint32 qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT

    cdef OM_uint32 max_input_size

    cdef OM_uint32 maj_stat, min_stat

    with nogil:
        maj_stat = gss_wrap_size_limit(&min_stat, context.raw_ctx, conf_req,
                                       qop_req, output_size, &max_input_size)

    if maj_stat == GSS_S_COMPLETE:
        return max_input_size
    else:
        raise GSSError(maj_stat, min_stat)


def wrap(SecurityContext context not None, message, confidential=True,
         qop=None):
    """
    wrap(context, message, confidential=True, qop=None)
    Wrap/Encrypt a message.

    This method wraps or encrypts a message (depending on the value
    of confidential) with the given Quality of Protection.

    Args:
        context (~gssapi.raw.sec_contexts.SecurityContext): the current
            security context
        message (bytes): the message to wrap or encrypt
        confidential (bool): whether or not to encrypt the message (True),
            or just wrap it with a MIC (False)
        qop (int): the desired Quality of Protection
            (or None for the default QoP)

    Returns:
        WrapResult: the wrapped/encrypted message, and whether or not
            encryption was actually used

    Raises:
        ~gssapi.exceptions.ExpiredContextError
        ~gssapi.exceptions.MissingContextError
        ~gssapi.exceptions.BadQoPError
    """

    cdef int conf_req = confidential
    cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
    cdef gss_buffer_desc message_buffer = gss_buffer_desc(len(message),
                                                          message)

    cdef int conf_used
    # GSS_C_EMPTY_BUFFER
    cdef gss_buffer_desc output_buffer = gss_buffer_desc(0, NULL)

    cdef OM_uint32 maj_stat, min_stat

    with nogil:
        maj_stat = gss_wrap(&min_stat, context.raw_ctx, conf_req, qop_req,
                            &message_buffer, &conf_used, &output_buffer)

    if maj_stat == GSS_S_COMPLETE:
        output_message = (<char*>output_buffer.value)[:output_buffer.length]
        gss_release_buffer(&min_stat, &output_buffer)
        return WrapResult(output_message, <bint>conf_used)
    else:
        raise GSSError(maj_stat, min_stat)


def unwrap(SecurityContext context not None, message):
    """
    unwrap(context, message)
    Unwrap/Decrypt a message.

    This method unwraps or decrypts a message, depending
    on whether the sender used confidentiality.

    Args:
        context (~gssapi.raw.sec_contexts.SecurityContext): the current
            security context
        message (bytes): the message to unwrap/decrypt

    Returns:
        UnwrapResult: the unwrapped/decrypted message, whether or on
            encryption was used, and the QoP used

    Raises:
        ~gssapi.exceptions.InvalidTokenError
        ~gssapi.exceptions.BadMICError
        ~gssapi.exceptions.DuplicateTokenError
        ~gssapi.exceptions.ExpiredTokenError
        ~gssapi.exceptions.TokenTooLateError
        ~gssapi.exceptions.TokenTooEarlyError
        ~gssapi.exceptions.ExpiredContextError
        ~gssapi.exceptions.MissingContextError
    """

    cdef gss_buffer_desc input_buffer = gss_buffer_desc(len(message), message)

    # GSS_C_EMPTY_BUFFER
    cdef gss_buffer_desc output_buffer = gss_buffer_desc(0, NULL)
    cdef int conf_state
    cdef gss_qop_t qop_state

    cdef OM_uint32 maj_stat, min_stat

    with nogil:
        maj_stat = gss_unwrap(&min_stat, context.raw_ctx, &input_buffer,
                              &output_buffer, &conf_state, &qop_state)

    if maj_stat == GSS_S_COMPLETE:
        output_message = (<char*>output_buffer.value)[:output_buffer.length]
        gss_release_buffer(&min_stat, &output_buffer)
        return UnwrapResult(output_message, <bint>conf_state, qop_state)
    else:
        raise GSSError(maj_stat, min_stat)