Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
[obnox/samba/samba-obnox.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 "includes.h"
20 #include <Python.h>
21 #include "param/param.h"
22 #include "param/pyparam.h"
23 #include "auth/gensec/gensec.h"
24 #include "libcli/util/pyerrors.h"
25 #include "scripting/python/modules.h"
26 #include "pytalloc.h"
27 #include <tevent.h>
28
29 #ifndef Py_RETURN_NONE
30 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
31 #endif
32
33 static PyObject *py_get_name_by_authtype(PyObject *self, PyObject *args)
34 {
35         int type;
36         const char *name;
37         struct gensec_security *security;
38
39         if (!PyArg_ParseTuple(args, "i", &type))
40                 return NULL;
41
42         security = (struct gensec_security *)py_talloc_get_ptr(self);
43
44         name = gensec_get_name_by_authtype(security, type);
45         if (name == NULL)
46                 Py_RETURN_NONE;
47
48         return PyString_FromString(name);
49 }
50
51 static struct gensec_settings *settings_from_object(TALLOC_CTX *mem_ctx, PyObject *object)
52 {
53         struct gensec_settings *s;
54         PyObject *py_hostname, *py_lp_ctx;
55
56         if (!PyDict_Check(object)) {
57                 PyErr_SetString(PyExc_ValueError, "settings should be a dictionary");
58                 return NULL;
59         }
60
61         s = talloc_zero(mem_ctx, struct gensec_settings);
62         if (!s) return NULL;
63
64         py_hostname = PyDict_GetItemString(object, "target_hostname");
65         if (!py_hostname) {
66                 PyErr_SetString(PyExc_ValueError, "settings.target_hostname not found");
67                 return NULL;
68         }
69
70         py_lp_ctx = PyDict_GetItemString(object, "lp_ctx");
71         if (!py_lp_ctx) {
72                 PyErr_SetString(PyExc_ValueError, "settings.lp_ctx not found");
73                 return NULL;
74         }
75         
76         s->target_hostname = PyString_AsString(py_hostname);
77         s->lp_ctx = lp_from_py_object(py_lp_ctx);
78         s->iconv_convenience = py_iconv_convenience(s);
79         return s;
80 }
81
82 static PyObject *py_gensec_start_client(PyTypeObject *type, PyObject *args, PyObject *kwargs)
83 {
84         NTSTATUS status;
85         py_talloc_Object *self;
86         struct gensec_settings *settings;
87         const char *kwnames[] = { "settings", NULL };
88         PyObject *py_settings;
89         struct tevent_context *ev;
90
91         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", discard_const_p(char *, kwnames), &py_settings))
92                 return NULL;
93
94         self = (py_talloc_Object*)type->tp_alloc(type, 0);
95         if (self == NULL) {
96                 PyErr_NoMemory();
97                 return NULL;
98         }
99         self->talloc_ctx = talloc_new(NULL);
100         if (self->talloc_ctx == NULL) {
101                 PyErr_NoMemory();
102                 return NULL;
103         }
104
105         settings = settings_from_object(self->talloc_ctx, py_settings);
106         if (settings == NULL) {
107                 PyObject_DEL(self);
108                 return NULL;
109         }
110         
111         ev = tevent_context_init(self->talloc_ctx);
112         if (ev == NULL) {
113                 PyErr_NoMemory();
114                 PyObject_Del(self);
115                 return NULL;
116         }
117
118         status = gensec_init(settings->lp_ctx);
119         if (!NT_STATUS_IS_OK(status)) {
120                 PyErr_SetNTSTATUS(status);
121                 PyObject_DEL(self);
122                 return NULL;
123         }
124
125         status = gensec_client_start(self->talloc_ctx, 
126                 (struct gensec_security **)&self->ptr, ev, settings);
127         if (!NT_STATUS_IS_OK(status)) {
128                 PyErr_SetNTSTATUS(status);
129                 PyObject_DEL(self);
130                 return NULL;
131         }
132         return (PyObject *)self;
133 }
134
135 static PyObject *py_gensec_session_info(PyObject *self)
136 {
137         NTSTATUS status;
138         struct gensec_security *security = (struct gensec_security *)py_talloc_get_ptr(self);
139         struct auth_session_info *info;
140         if (security->ops == NULL) {
141                 PyErr_SetString(PyExc_ValueError, "gensec not fully initialised - ask Andrew");
142                 return NULL;
143         }
144         status = gensec_session_info(security, &info);
145         if (NT_STATUS_IS_ERR(status)) {
146                 PyErr_SetNTSTATUS(status);
147                 return NULL;
148         }
149
150         /* FIXME */
151         Py_RETURN_NONE;
152 }
153
154 static PyMethodDef py_gensec_security_methods[] = {
155         { "start_client", (PyCFunction)py_gensec_start_client, METH_VARARGS|METH_KEYWORDS|METH_CLASS, 
156                 "S.start_client(settings) -> gensec" },
157 /*      { "start_server", (PyCFunction)py_gensec_start_server, METH_VARARGS|METH_KEYWORDS|METH_CLASS, 
158                 "S.start_server(auth_ctx, settings) -> gensec" },*/
159         { "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS,
160                 "S.session_info() -> info" },
161         { "get_name_by_authtype", (PyCFunction)py_get_name_by_authtype, METH_VARARGS,
162                 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
163         { NULL }
164 };
165
166 static PyTypeObject Py_Security = {
167         .tp_name = "Security",
168         .tp_flags = Py_TPFLAGS_DEFAULT,
169         .tp_methods = py_gensec_security_methods,
170         .tp_basicsize = sizeof(py_talloc_Object),
171         .tp_dealloc = py_talloc_dealloc,
172 };
173
174 void initgensec(void)
175 {
176         PyObject *m;
177
178         if (PyType_Ready(&Py_Security) < 0)
179                 return;
180
181         m = Py_InitModule3("gensec", NULL, "Generic Security Interface.");
182         if (m == NULL)
183                 return;
184
185         Py_INCREF(&Py_Security);
186         PyModule_AddObject(m, "Security", (PyObject *)&Py_Security);
187 }