d8f782f8d191138eae85995f43915cf641a73fe7
[metze/samba/wip.git] / source4 / auth / gensec / pygensec.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
4    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <Python.h>
20 #include "python/py3compat.h"
21 #include "includes.h"
22 #include "param/pyparam.h"
23 #include "auth/gensec/gensec.h"
24 #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
25 #include "auth/credentials/pycredentials.h"
26 #include "libcli/util/pyerrors.h"
27 #include "python/modules.h"
28 #include <pytalloc.h>
29 #include <tevent.h>
30 #include "librpc/rpc/pyrpc_util.h"
31
32 static PyObject *py_get_name_by_authtype(PyObject *self, PyObject *args)
33 {
34         int type;
35         const char *name;
36         struct gensec_security *security;
37
38         if (!PyArg_ParseTuple(args, "i", &type))
39                 return NULL;
40
41         security = pytalloc_get_type(self, struct gensec_security);
42
43         name = gensec_get_name_by_authtype(security, type);
44         if (name == NULL)
45                 Py_RETURN_NONE;
46
47         return PyStr_FromString(name);
48 }
49
50 static struct gensec_settings *settings_from_object(TALLOC_CTX *mem_ctx, PyObject *object)
51 {
52         struct gensec_settings *s;
53         PyObject *py_hostname, *py_lp_ctx;
54
55         if (!PyDict_Check(object)) {
56                 PyErr_SetString(PyExc_ValueError, "settings should be a dictionary");
57                 return NULL;
58         }
59
60         s = talloc_zero(mem_ctx, struct gensec_settings);
61         if (!s) return NULL;
62
63         py_hostname = PyDict_GetItemString(object, "target_hostname");
64         if (!py_hostname) {
65                 PyErr_SetString(PyExc_ValueError, "settings.target_hostname not found");
66                 return NULL;
67         }
68
69         py_lp_ctx = PyDict_GetItemString(object, "lp_ctx");
70         if (!py_lp_ctx) {
71                 PyErr_SetString(PyExc_ValueError, "settings.lp_ctx not found");
72                 return NULL;
73         }
74
75         s->target_hostname = PyStr_AsString(py_hostname);
76         s->lp_ctx = lpcfg_from_py_object(s, py_lp_ctx);
77         return s;
78 }
79
80 static PyObject *py_gensec_start_client(PyTypeObject *type, PyObject *args, PyObject *kwargs)
81 {
82         NTSTATUS status;
83         PyObject *self;
84         struct gensec_settings *settings;
85         const char *kwnames[] = { "settings", NULL };
86         PyObject *py_settings = Py_None;
87         struct gensec_security *gensec;
88         TALLOC_CTX *frame;
89
90         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", discard_const_p(char *, kwnames), &py_settings))
91                 return NULL;
92
93         frame = talloc_stackframe();
94
95         if (py_settings != Py_None) {
96                 settings = settings_from_object(frame, py_settings);
97                 if (settings == NULL) {
98                         PyErr_NoMemory();
99                         TALLOC_FREE(frame);
100                         return NULL;
101                 }
102         } else {
103                 settings = talloc_zero(frame, struct gensec_settings);
104                 if (settings == NULL) {
105                         PyErr_NoMemory();
106                         TALLOC_FREE(frame);
107                         return NULL;
108                 }
109
110                 settings->lp_ctx = loadparm_init_global(true);
111                 if (settings->lp_ctx == NULL) {
112                         PyErr_NoMemory();
113                         TALLOC_FREE(frame);
114                         return NULL;
115                 }
116         }
117
118         status = gensec_init();
119         if (!NT_STATUS_IS_OK(status)) {
120                 PyErr_SetNTSTATUS(status);
121                 TALLOC_FREE(frame);
122                 return NULL;
123         }
124
125         status = gensec_client_start(frame, &gensec, settings);
126         if (!NT_STATUS_IS_OK(status)) {
127                 PyErr_SetNTSTATUS(status);
128                 TALLOC_FREE(frame);
129                 return NULL;
130         }
131
132         self = pytalloc_steal(type, gensec);
133         TALLOC_FREE(frame);
134
135         return (PyObject *)self;
136 }
137
138 static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyObject *kwargs)
139 {
140         NTSTATUS status;
141         PyObject *self;
142         struct gensec_settings *settings = NULL;
143         const char *kwnames[] = { "settings", "auth_context", NULL };
144         PyObject *py_settings = Py_None;
145         PyObject *py_auth_context = Py_None;
146         struct gensec_security *gensec;
147         struct auth4_context *auth_context = NULL;
148         TALLOC_CTX *frame;
149
150         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", discard_const_p(char *, kwnames), &py_settings, &py_auth_context))
151                 return NULL;
152
153         frame = talloc_stackframe();
154
155         if (py_settings != Py_None) {
156                 settings = settings_from_object(frame, py_settings);
157                 if (settings == NULL) {
158                         PyErr_NoMemory();
159                         TALLOC_FREE(frame);
160                         return NULL;
161                 }
162         } else {
163                 settings = talloc_zero(frame, struct gensec_settings);
164                 if (settings == NULL) {
165                         PyErr_NoMemory();
166                         TALLOC_FREE(frame);
167                         return NULL;
168                 }
169
170                 settings->lp_ctx = loadparm_init_global(true);
171                 if (settings->lp_ctx == NULL) {
172                         PyErr_NoMemory();
173                         TALLOC_FREE(frame);
174                         return NULL;
175                 }
176         }
177
178         if (py_auth_context != Py_None) {
179                 bool ok = py_check_dcerpc_type(py_auth_context,
180                                                "samba.auth",
181                                                "AuthContext");
182                 if (!ok) {
183                         return NULL;
184                 }
185
186                 auth_context = pytalloc_get_type(py_auth_context,
187                                                  struct auth4_context);
188                 if (!auth_context) {
189                         PyErr_Format(PyExc_TypeError,
190                                      "Expected auth.AuthContext for auth_context argument, got %s",
191                                      talloc_get_name(pytalloc_get_ptr(py_auth_context)));
192                         return NULL;
193                 }
194         }
195
196         status = gensec_init();
197         if (!NT_STATUS_IS_OK(status)) {
198                 PyErr_SetNTSTATUS(status);
199                 TALLOC_FREE(frame);
200                 return NULL;
201         }
202
203         status = gensec_server_start(frame, settings, auth_context, &gensec);
204         if (!NT_STATUS_IS_OK(status)) {
205                 PyErr_SetNTSTATUS(status);
206                 TALLOC_FREE(frame);
207                 return NULL;
208         }
209
210         self = pytalloc_steal(type, gensec);
211         TALLOC_FREE(frame);
212
213         return self;
214 }
215
216 static PyObject *py_gensec_set_target_hostname(PyObject *self, PyObject *args)
217 {
218         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
219         char *target_hostname;
220         NTSTATUS status;
221
222         if (!PyArg_ParseTuple(args, "s", &target_hostname))
223                 return NULL;
224
225         status = gensec_set_target_hostname(security, target_hostname);
226         if (!NT_STATUS_IS_OK(status)) {
227                 PyErr_SetNTSTATUS(status);
228                 return NULL;
229         }
230         
231         Py_RETURN_NONE;
232 }
233
234 static PyObject *py_gensec_set_target_service(PyObject *self, PyObject *args)
235 {
236         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
237         char *target_service;
238         NTSTATUS status;
239
240         if (!PyArg_ParseTuple(args, "s", &target_service))
241                 return NULL;
242
243         status = gensec_set_target_service(security, target_service);
244         if (!NT_STATUS_IS_OK(status)) {
245                 PyErr_SetNTSTATUS(status);
246                 return NULL;
247         }
248         
249         Py_RETURN_NONE;
250 }
251
252 static PyObject *py_gensec_set_target_service_description(PyObject *self, PyObject *args)
253 {
254         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
255         char *target_service_description;
256         NTSTATUS status;
257
258         if (!PyArg_ParseTuple(args, "s", &target_service_description))
259                 return NULL;
260
261         status = gensec_set_target_service_description(security,
262                                                        target_service_description);
263         if (!NT_STATUS_IS_OK(status)) {
264                 PyErr_SetNTSTATUS(status);
265                 return NULL;
266         }
267
268         Py_RETURN_NONE;
269 }
270
271 static PyObject *py_gensec_set_credentials(PyObject *self, PyObject *args)
272 {
273         PyObject *py_creds = Py_None;
274         struct cli_credentials *creds;
275         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
276         NTSTATUS status;
277
278         if (!PyArg_ParseTuple(args, "O", &py_creds))
279                 return NULL;
280
281         creds = PyCredentials_AsCliCredentials(py_creds);
282         if (!creds) {
283                 PyErr_Format(PyExc_TypeError,
284                              "Expected samba.credentaials for credentials argument got  %s",
285                              talloc_get_name(pytalloc_get_ptr(py_creds)));
286                 return NULL;
287         }
288
289         status = gensec_set_credentials(security, creds);
290         if (!NT_STATUS_IS_OK(status)) {
291                 PyErr_SetNTSTATUS(status);
292                 return NULL;
293         }
294
295         Py_RETURN_NONE;
296 }
297
298 static PyObject *py_gensec_session_info(PyObject *self)
299 {
300         TALLOC_CTX *mem_ctx;
301         NTSTATUS status;
302         PyObject *py_session_info;
303         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
304         struct auth_session_info *info;
305         if (security->ops == NULL) {
306                 PyErr_SetString(PyExc_RuntimeError, "no mechanism selected");
307                 return NULL;
308         }
309         mem_ctx = talloc_new(NULL);
310
311         status = gensec_session_info(security, mem_ctx, &info);
312         if (NT_STATUS_IS_ERR(status)) {
313                 PyErr_SetNTSTATUS(status);
314                 return NULL;
315         }
316
317         py_session_info = py_return_ndr_struct("samba.dcerpc.auth", "session_info",
318                                                  info, info);
319         talloc_free(mem_ctx);
320         return py_session_info;
321 }
322
323 static PyObject *py_gensec_session_key(PyObject *self)
324 {
325         TALLOC_CTX *mem_ctx;
326         NTSTATUS status;
327         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
328         DATA_BLOB session_key = data_blob_null;
329         static PyObject *session_key_obj = NULL;
330
331         if (security->ops == NULL) {
332                 PyErr_SetString(PyExc_RuntimeError, "no mechanism selected");
333                 return NULL;
334         }
335         mem_ctx = talloc_new(NULL);
336
337         status = gensec_session_key(security, mem_ctx, &session_key);
338         if (!NT_STATUS_IS_OK(status)) {
339                 talloc_free(mem_ctx);
340                 PyErr_SetNTSTATUS(status);
341                 return NULL;
342         }
343
344         session_key_obj = PyBytes_FromStringAndSize((const char *)session_key.data,
345                                                      session_key.length);
346         talloc_free(mem_ctx);
347         return session_key_obj;
348 }
349
350 static PyObject *py_gensec_start_mech_by_name(PyObject *self, PyObject *args)
351 {
352         char *name;
353         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
354         NTSTATUS status;
355
356         if (!PyArg_ParseTuple(args, "s", &name))
357                 return NULL;
358
359         status = gensec_start_mech_by_name(security, name);
360         if (!NT_STATUS_IS_OK(status)) {
361                 PyErr_SetNTSTATUS(status);
362                 return NULL;
363         }
364
365         Py_RETURN_NONE;
366 }
367
368 static PyObject *py_gensec_start_mech_by_sasl_name(PyObject *self, PyObject *args)
369 {
370         char *sasl_name;
371         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
372         NTSTATUS status;
373
374         if (!PyArg_ParseTuple(args, "s", &sasl_name))
375                 return NULL;
376
377         status = gensec_start_mech_by_sasl_name(security, sasl_name);
378         if (!NT_STATUS_IS_OK(status)) {
379                 PyErr_SetNTSTATUS(status);
380                 return NULL;
381         }
382
383         Py_RETURN_NONE;
384 }
385
386 static PyObject *py_gensec_start_mech_by_authtype(PyObject *self, PyObject *args)
387 {
388         int authtype, level;
389         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
390         NTSTATUS status;
391         if (!PyArg_ParseTuple(args, "ii", &authtype, &level))
392                 return NULL;
393
394         status = gensec_start_mech_by_authtype(security, authtype, level);
395         if (!NT_STATUS_IS_OK(status)) {
396                 PyErr_SetNTSTATUS(status);
397                 return NULL;
398         }
399
400         Py_RETURN_NONE;
401 }
402
403 static PyObject *py_gensec_want_feature(PyObject *self, PyObject *args)
404 {
405         int feature;
406         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
407         /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
408         if (!PyArg_ParseTuple(args, "i", &feature))
409                 return NULL;
410
411         gensec_want_feature(security, feature);
412
413         Py_RETURN_NONE;
414 }
415
416 static PyObject *py_gensec_have_feature(PyObject *self, PyObject *args)
417 {
418         int feature;
419         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
420         /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
421         if (!PyArg_ParseTuple(args, "i", &feature))
422                 return NULL;
423
424         if (gensec_have_feature(security, feature)) {
425                 return Py_True;
426         } 
427         return Py_False;
428 }
429
430 static PyObject *py_gensec_set_max_update_size(PyObject *self, PyObject *args)
431 {
432         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
433         unsigned int max_update_size = 0;
434
435         if (!PyArg_ParseTuple(args, "I", &max_update_size))
436                 return NULL;
437
438         gensec_set_max_update_size(security, max_update_size);
439
440         Py_RETURN_NONE;
441 }
442
443 static PyObject *py_gensec_max_update_size(PyObject *self)
444 {
445         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
446         unsigned int max_update_size = gensec_max_update_size(security);
447
448         return PyInt_FromLong(max_update_size);
449 }
450
451 static PyObject *py_gensec_update(PyObject *self, PyObject *args)
452 {
453         NTSTATUS status;
454         TALLOC_CTX *mem_ctx;
455         DATA_BLOB in, out;
456         PyObject *ret, *py_in;
457         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
458         PyObject *finished_processing;
459
460         if (!PyArg_ParseTuple(args, "O", &py_in))
461                 return NULL;
462
463         mem_ctx = talloc_new(NULL);
464         if (!PyBytes_Check(py_in)) {
465                 PyErr_Format(PyExc_TypeError, "bytes expected");
466                 return NULL;
467         }
468
469         in.data = (uint8_t *)PyBytes_AsString(py_in);
470         in.length = PyBytes_Size(py_in);
471
472         status = gensec_update(security, mem_ctx, in, &out);
473
474         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)
475             && !NT_STATUS_IS_OK(status)) {
476                 PyErr_SetNTSTATUS(status);
477                 talloc_free(mem_ctx);
478                 return NULL;
479         }
480         ret = PyBytes_FromStringAndSize((const char *)out.data, out.length);
481         talloc_free(mem_ctx);
482
483         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
484                 finished_processing = Py_False;
485         } else {
486                 finished_processing = Py_True;
487         }
488
489         return PyTuple_Pack(2, finished_processing, ret);
490 }
491
492 static PyObject *py_gensec_wrap(PyObject *self, PyObject *args)
493 {
494         NTSTATUS status;
495
496         TALLOC_CTX *mem_ctx;
497         DATA_BLOB in, out;
498         PyObject *ret, *py_in;
499         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
500
501         if (!PyArg_ParseTuple(args, "O", &py_in))
502                 return NULL;
503
504         mem_ctx = talloc_new(NULL);
505
506         if (!PyBytes_Check(py_in)) {
507                 PyErr_Format(PyExc_TypeError, "bytes expected");
508                 return NULL;
509         }
510         in.data = (uint8_t *)PyBytes_AsString(py_in);
511         in.length = PyBytes_Size(py_in);
512
513         status = gensec_wrap(security, mem_ctx, &in, &out);
514
515         if (!NT_STATUS_IS_OK(status)) {
516                 PyErr_SetNTSTATUS(status);
517                 talloc_free(mem_ctx);
518                 return NULL;
519         }
520
521         ret = PyBytes_FromStringAndSize((const char *)out.data, out.length);
522         talloc_free(mem_ctx);
523         return ret;
524 }
525
526
527 static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args)
528 {
529         NTSTATUS status;
530
531         TALLOC_CTX *mem_ctx;
532         DATA_BLOB in, out;
533         PyObject *ret, *py_in;
534         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
535
536         if (!PyArg_ParseTuple(args, "O", &py_in))
537                 return NULL;
538
539         mem_ctx = talloc_new(NULL);
540
541         if (!PyBytes_Check(py_in)) {
542                 PyErr_Format(PyExc_TypeError, "bytes expected");
543                 return NULL;
544         }
545
546         in.data = (uint8_t *)PyBytes_AsString(py_in);
547         in.length = PyBytes_Size(py_in);
548
549         status = gensec_unwrap(security, mem_ctx, &in, &out);
550
551         if (!NT_STATUS_IS_OK(status)) {
552                 PyErr_SetNTSTATUS(status);
553                 talloc_free(mem_ctx);
554                 return NULL;
555         }
556
557         ret = PyBytes_FromStringAndSize((const char *)out.data, out.length);
558         talloc_free(mem_ctx);
559         return ret;
560 }
561
562 static PyObject *py_gensec_sig_size(PyObject *self, PyObject *args)
563 {
564         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
565         Py_ssize_t data_size = 0;
566         size_t sig_size = 0;
567
568         if (!PyArg_ParseTuple(args, "n", &data_size)) {
569                 return NULL;
570         }
571
572         sig_size = gensec_sig_size(security, data_size);
573
574         return PyLong_FromSize_t(sig_size);
575 }
576
577 static PyObject *py_gensec_sign_packet(PyObject *self, PyObject *args)
578 {
579         NTSTATUS status;
580         TALLOC_CTX *mem_ctx = NULL;
581         Py_ssize_t data_length = 0;
582         Py_ssize_t pdu_length = 0;
583         DATA_BLOB data, pdu, sig;
584         PyObject *py_sig;
585         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
586
587         if (!PyArg_ParseTuple(args, "z#z#", &data.data, &data_length, &pdu.data, &pdu_length)) {
588                 return NULL;
589         }
590         data.length = data_length;
591         pdu.length = pdu_length;
592
593         mem_ctx = talloc_new(NULL);
594
595         status = gensec_sign_packet(security, mem_ctx,
596                                     data.data, data.length,
597                                     pdu.data, pdu.length, &sig);
598         if (!NT_STATUS_IS_OK(status)) {
599                 PyErr_SetNTSTATUS(status);
600                 talloc_free(mem_ctx);
601                 return NULL;
602         }
603
604         py_sig = PyBytes_FromStringAndSize((const char *)sig.data, sig.length);
605         talloc_free(mem_ctx);
606         return py_sig;
607 }
608
609 static PyObject *py_gensec_check_packet(PyObject *self, PyObject *args)
610 {
611         NTSTATUS status;
612         Py_ssize_t data_length = 0;
613         Py_ssize_t pdu_length = 0;
614         Py_ssize_t sig_length = 0;
615         DATA_BLOB data, pdu, sig;
616         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
617
618         if (!PyArg_ParseTuple(args, "z#z#z#",
619                               &data.data, &data_length,
620                               &pdu.data, &pdu_length,
621                               &sig.data, &sig_length)) {
622                 return NULL;
623         }
624         data.length = data_length;
625         pdu.length = pdu_length;
626         sig.length = sig_length;
627
628         status = gensec_check_packet(security,
629                                      data.data, data.length,
630                                      pdu.data, pdu.length, &sig);
631         if (!NT_STATUS_IS_OK(status)) {
632                 PyErr_SetNTSTATUS(status);
633                 return NULL;
634         }
635
636         Py_RETURN_NONE;
637 }
638
639 static PyMethodDef py_gensec_security_methods[] = {
640         { "start_client", (PyCFunction)py_gensec_start_client, METH_VARARGS|METH_KEYWORDS|METH_CLASS, 
641                 "S.start_client(settings) -> gensec" },
642         { "start_server", (PyCFunction)py_gensec_start_server, METH_VARARGS|METH_KEYWORDS|METH_CLASS,
643                 "S.start_server(auth_ctx, settings) -> gensec" },
644         { "set_credentials", (PyCFunction)py_gensec_set_credentials, METH_VARARGS, 
645                 "S.start_client(credentials)" },
646         { "set_target_hostname", (PyCFunction)py_gensec_set_target_hostname, METH_VARARGS, 
647                 "S.start_target_hostname(target_hostname) \n This sets the Kerberos target hostname to obtain a ticket for." },
648         { "set_target_service", (PyCFunction)py_gensec_set_target_service, METH_VARARGS, 
649                 "S.start_target_service(target_service) \n This sets the Kerberos target service to obtain a ticket for.  The default value is 'host'" },
650         { "set_target_service_description", (PyCFunction)py_gensec_set_target_service_description, METH_VARARGS,
651                 "S.start_target_service_description(target_service_description) \n This description is set server-side and used in authentication and authorization logs.  The default value is that provided to set_target_service() or None."},
652         { "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS,
653                 "S.session_info() -> info" },
654         { "session_key", (PyCFunction)py_gensec_session_key, METH_NOARGS,
655                 "S.session_key() -> key" },
656         { "start_mech_by_name", (PyCFunction)py_gensec_start_mech_by_name, METH_VARARGS,
657                 "S.start_mech_by_name(name)" },
658         { "start_mech_by_sasl_name", (PyCFunction)py_gensec_start_mech_by_sasl_name, METH_VARARGS,
659                 "S.start_mech_by_sasl_name(name)" },
660         { "start_mech_by_authtype", (PyCFunction)py_gensec_start_mech_by_authtype, METH_VARARGS,
661                 "S.start_mech_by_authtype(authtype, level)" },
662         { "get_name_by_authtype", (PyCFunction)py_get_name_by_authtype, METH_VARARGS,
663                 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
664         { "want_feature", (PyCFunction)py_gensec_want_feature, METH_VARARGS,
665                 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
666         { "have_feature", (PyCFunction)py_gensec_have_feature, METH_VARARGS,
667                 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
668         { "set_max_update_size",  (PyCFunction)py_gensec_set_max_update_size, METH_VARARGS,
669                 "S.set_max_update_size(max_size) \n Some mechs can fragment update packets, needs to be use before the mech is started." },
670         { "max_update_size",  (PyCFunction)py_gensec_max_update_size, 0,
671                 "S.max_update_size() \n Return the current max_update_size." },
672         { "update",  (PyCFunction)py_gensec_update, METH_VARARGS,
673                 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance.  Repeat with new packets until finished is true or exception." },
674         { "wrap",  (PyCFunction)py_gensec_wrap, METH_VARARGS,
675                 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
676         { "unwrap",  (PyCFunction)py_gensec_unwrap, METH_VARARGS,
677                 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
678         { "sig_size",  (PyCFunction)py_gensec_sig_size, METH_VARARGS,
679                 "S.sig_size(data_size) -> sig_size\nSize of the DCERPC packet signature" },
680         { "sign_packet",  (PyCFunction)py_gensec_sign_packet, METH_VARARGS,
681                 "S.sign_packet(data, whole_pdu) -> sig\nSign a DCERPC packet." },
682         { "check_packet",  (PyCFunction)py_gensec_check_packet, METH_VARARGS,
683                 "S.check_packet(data, whole_pdu, sig)\nCheck a DCERPC packet." },
684         { NULL }
685 };
686
687 static struct PyModuleDef moduledef = {
688     PyModuleDef_HEAD_INIT,
689     .m_name = "gensec",
690     .m_doc = "Generic Security Interface.",
691     .m_size = -1,
692 };
693
694 static PyTypeObject Py_Security = {
695         .tp_name = "gensec.Security",
696         .tp_flags = Py_TPFLAGS_DEFAULT,
697         .tp_methods = py_gensec_security_methods,
698 };
699
700 MODULE_INIT_FUNC(gensec)
701 {
702         PyObject *m;
703
704         if (pytalloc_BaseObject_PyType_Ready(&Py_Security) < 0)
705                 return NULL;
706
707         m = PyModule_Create(&moduledef);
708         if (m == NULL)
709                 return NULL;
710
711         PyModule_AddObject(m, "FEATURE_SESSION_KEY",     PyInt_FromLong(GENSEC_FEATURE_SESSION_KEY));
712         PyModule_AddObject(m, "FEATURE_SIGN",            PyInt_FromLong(GENSEC_FEATURE_SIGN));
713         PyModule_AddObject(m, "FEATURE_SEAL",            PyInt_FromLong(GENSEC_FEATURE_SEAL));
714         PyModule_AddObject(m, "FEATURE_DCE_STYLE",       PyInt_FromLong(GENSEC_FEATURE_DCE_STYLE));
715         PyModule_AddObject(m, "FEATURE_ASYNC_REPLIES",   PyInt_FromLong(GENSEC_FEATURE_ASYNC_REPLIES));
716         PyModule_AddObject(m, "FEATURE_DATAGRAM_MODE",   PyInt_FromLong(GENSEC_FEATURE_DATAGRAM_MODE));
717         PyModule_AddObject(m, "FEATURE_SIGN_PKT_HEADER", PyInt_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER));
718         PyModule_AddObject(m, "FEATURE_NEW_SPNEGO",      PyInt_FromLong(GENSEC_FEATURE_NEW_SPNEGO));
719
720         Py_INCREF(&Py_Security);
721         PyModule_AddObject(m, "Security", (PyObject *)&Py_Security);
722
723         return m;
724 }