Migrate 'net export keytab' to python.
[kai/samba.git] / source4 / libnet / py_net.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
5    Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <Python.h>
22 #include "includes.h"
23 #include "libnet.h"
24 #include "auth/credentials/pycredentials.h"
25 #include "libcli/security/security.h"
26 #include "lib/events/events.h"
27 #include "param/param.h"
28
29 /* FIXME: This prototype should be in param/pyparam.h */
30 struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx);
31
32 static struct libnet_context *py_net_ctx(PyObject *obj, struct tevent_context *ev, struct cli_credentials *creds)
33 {
34 /* FIXME: Use obj */
35         struct libnet_context *libnet;
36         libnet = libnet_context_init(ev, py_default_loadparm_context(NULL));
37         if (!libnet) {
38                 return NULL;
39         }
40         libnet->cred = creds;
41         return libnet;
42 }
43
44 static PyObject *py_net_join(PyObject *cls, PyObject *args, PyObject *kwargs)
45 {
46         struct libnet_Join r;
47         NTSTATUS status;
48         PyObject *result;
49         TALLOC_CTX *mem_ctx;
50         struct tevent_context *ev;
51         struct libnet_context *libnet_ctx;
52         struct cli_credentials *creds;
53         PyObject *py_creds;     
54         const char *kwnames[] = { "domain_name", "netbios_name", "join_type", "level", "credentials", NULL };
55
56         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssiiO:Join", discard_const_p(char *, kwnames), 
57                                          &r.in.domain_name, &r.in.netbios_name, 
58                                          &r.in.join_type, &r.in.level, &py_creds))
59                 return NULL;
60
61         /* FIXME: we really need to get a context from the caller or we may end
62          * up with 2 event contexts */
63         ev = s4_event_context_init(NULL);
64         mem_ctx = talloc_new(ev);
65
66         creds = cli_credentials_from_py_object(py_creds);
67         if (creds == NULL) {
68                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
69                 talloc_free(mem_ctx);
70                 return NULL;
71         }
72
73         libnet_ctx = py_net_ctx(cls, ev, creds);
74         if (libnet_ctx == NULL) {
75                 PyErr_SetString(PyExc_RuntimeError, "Unable to initialize libnet");
76                 talloc_free(mem_ctx);
77                 return NULL;
78         }
79
80         status = libnet_Join(libnet_ctx, mem_ctx, &r);
81         if (NT_STATUS_IS_ERR(status)) {
82                 PyErr_SetString(PyExc_RuntimeError, r.out.error_string);
83                 talloc_free(mem_ctx);
84                 return NULL;
85         }
86
87         result = Py_BuildValue("sss", r.out.join_password,
88                                dom_sid_string(mem_ctx, r.out.domain_sid),
89                                r.out.domain_name);
90
91         talloc_free(mem_ctx);
92
93         return result;
94 }
95
96 static const char py_net_join_doc[] = "join(domain_name, netbios_name, join_type, level) -> (join_password, domain_sid, domain_name)\n\n" \
97 "Join the domain with the specified name.";
98
99 static PyObject *py_net_set_password(PyObject *cls, PyObject *args, PyObject *kwargs)
100 {
101         union libnet_SetPassword r;
102         NTSTATUS status;
103         PyObject *py_creds;
104         TALLOC_CTX *mem_ctx;
105         struct tevent_context *ev;
106         struct libnet_context *libnet_ctx;
107         struct cli_credentials *creds;
108         const char *kwnames[] = { "account_name", "domain_name", "newpassword", "credentials", NULL };
109
110         r.generic.level = LIBNET_SET_PASSWORD_GENERIC;
111
112         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sssO:set_password", discard_const_p(char *, kwnames),
113                                          &r.generic.in.account_name, &r.generic.in.domain_name,
114                                          &r.generic.in.newpassword, &py_creds)) {
115                 return NULL;
116         }
117
118         /* FIXME: we really need to get a context from the caller or we may end
119          * up with 2 event contexts */
120         ev = s4_event_context_init(NULL);
121         mem_ctx = talloc_new(ev);
122
123         creds = cli_credentials_from_py_object(py_creds);
124         if (creds == NULL) {
125                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
126                 return NULL;
127         }
128
129         libnet_ctx = py_net_ctx(cls, ev, creds);
130
131         status = libnet_SetPassword(libnet_ctx, mem_ctx, &r);
132         if (NT_STATUS_IS_ERR(status)) {
133                 PyErr_SetString(PyExc_RuntimeError, r.generic.out.error_string);
134                 talloc_free(mem_ctx);
135                 return NULL;
136         }
137
138         talloc_free(mem_ctx);
139
140         Py_RETURN_NONE;
141 }
142
143 static const char py_net_set_password_doc[] = "set_password(account_name, domain_name, newpassword) -> True\n\n" \
144 "Set password for a user. You must supply credential with enough rights to do this.\n\n" \
145 "Sample usage is:\n" \
146 "creds = samba.credentials.Credentials()\n" \
147 "creds.set_username('admin_user')\n" \
148 "creds.set_domain('domain_name')\n" \
149 "creds.set_password('pass')\n\n" \
150 "net.set_password(account_name=<account_name>,\n" \
151 "                domain_name=creds.get_domain(),\n" \
152 "                newpassword=new_pass,\n" \
153 "                credentials=creds)\n";
154
155
156 static PyObject *py_net_export_keytab(PyObject *cls, PyObject *args, PyObject *kwargs)
157 {
158         struct libnet_export_keytab r;
159         struct tevent_context *ev;
160         TALLOC_CTX *mem_ctx;
161         const char *kwnames[] = { "keytab", "creds", NULL };
162         struct libnet_context *libnet_ctx;
163         PyObject *py_creds;
164         struct cli_credentials *creds;
165         NTSTATUS status;
166
167         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO:export_keytab", discard_const_p(char *, kwnames),
168                                          &r.in.keytab_name, &py_creds)) {
169                 return NULL;
170         }
171
172         creds = cli_credentials_from_py_object(py_creds);
173         if (creds == NULL) {
174                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
175                 return NULL;
176         }
177
178         /* FIXME: we really need to get a context from the caller or we may end
179          * up with 2 event contexts */
180         ev = s4_event_context_init(NULL);
181         mem_ctx = talloc_new(ev);
182
183         libnet_ctx = py_net_ctx(cls, ev, creds);
184
185         status = libnet_export_keytab(libnet_ctx, mem_ctx, &r);
186         if (NT_STATUS_IS_ERR(status)) {
187                 PyErr_SetString(PyExc_RuntimeError, r.out.error_string);
188                 talloc_free(mem_ctx);
189                 return NULL;
190         }
191
192         talloc_free(mem_ctx);
193
194         Py_RETURN_NONE;
195 }
196
197 static const char py_net_export_keytab_doc[] = "export_keytab(keytab, name)\n\n"
198 "Export the DC keytab to a keytab file.";
199
200 static struct PyMethodDef net_methods[] = {
201         {"join", (PyCFunction)py_net_join, METH_VARARGS|METH_KEYWORDS, py_net_join_doc},
202         {"set_password", (PyCFunction)py_net_set_password, METH_VARARGS|METH_KEYWORDS, py_net_set_password_doc},
203         {"export_keytab", (PyCFunction)py_net_export_keytab, METH_VARARGS|METH_KEYWORDS, py_net_export_keytab_doc},
204         {NULL }
205 };
206
207 void initnet(void)
208 {
209         Py_InitModule3("net", net_methods, NULL);
210 }