Added enumerate trusted domains and check secret.
[samba.git] / source / python / py_winbind.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Python wrapper for winbind client functions.
5
6    Copyright (C) Tim Potter      2002
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "Python.h"
25
26 /* 
27  * Exceptions raised by this module 
28  */
29
30 PyObject *winbind_error;        /* A winbind call returned WINBINDD_ERROR */
31
32 /* Prototypes from common.h */
33
34 NSS_STATUS winbindd_request(int req_type, 
35                             struct winbindd_request *request,
36                             struct winbindd_response *response);
37
38 /*
39  * Name <-> SID conversion
40  */
41
42 /* Convert a name to a sid */
43
44 static PyObject *winbind_name_to_sid(PyObject *self, PyObject *args)
45
46 {
47         struct winbindd_request request;
48         struct winbindd_response response;
49         PyObject *result;
50         char *name, *p;
51
52         if (!PyArg_ParseTuple(args, "s", &name))
53                 return NULL;
54
55         ZERO_STRUCT(request);
56         ZERO_STRUCT(response);
57
58         /* FIXME: use winbind separator */
59
60         if ((p = strchr(name, '\\'))) {
61                 *p = 0;
62                 fstrcpy(request.data.name.dom_name, name);
63                 fstrcpy(request.data.name.name, p + 1);
64         } else {
65                 fstrcpy(request.data.name.dom_name, lp_workgroup());
66                 fstrcpy(request.data.name.name, name);
67         }
68
69         if (winbindd_request(WINBINDD_LOOKUPNAME, &request, &response)  
70             != NSS_STATUS_SUCCESS) {
71                 PyErr_SetString(winbind_error, "lookup failed");
72                 return NULL;
73         }
74
75         result = PyString_FromString(response.data.sid.sid);
76
77         return result;
78 }
79
80 /* Convert a sid to a name */
81
82 static PyObject *winbind_sid_to_name(PyObject *self, PyObject *args)
83 {
84         struct winbindd_request request;
85         struct winbindd_response response;
86         PyObject *result;
87         char *sid, *name;
88
89         if (!PyArg_ParseTuple(args, "s", &sid))
90                 return NULL;
91
92         ZERO_STRUCT(request);
93         ZERO_STRUCT(response);
94
95         fstrcpy(request.data.sid, sid);
96
97         if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response)  
98             != NSS_STATUS_SUCCESS) {
99                 PyErr_SetString(winbind_error, "lookup failed");
100                 return NULL;
101         }
102
103         /* FIXME: use actual winbind separator */
104
105         asprintf(&name, "%s%c%s", response.data.name.dom_name,
106                  '\\', response.data.name.name);
107
108         result = PyString_FromString(name);
109
110         free(name);
111
112         return result;
113 }
114
115 /*
116  * Enumerate users/groups
117  */
118
119 /* Enumerate domain users */
120
121 static PyObject *winbind_enum_domain_users(PyObject *self, PyObject *args)
122 {
123         struct winbindd_response response;
124         PyObject *result;
125
126         if (!PyArg_ParseTuple(args, ""))
127                 return NULL;
128
129         ZERO_STRUCT(response);
130
131         if (winbindd_request(WINBINDD_LIST_USERS, NULL, &response) 
132             != NSS_STATUS_SUCCESS) {
133                 PyErr_SetString(winbind_error, "lookup failed");
134                 return NULL;            
135         }
136
137         result = PyList_New(0);
138
139         if (response.extra_data) {
140                 char *extra_data = response.extra_data;
141                 fstring name;
142
143                 while (next_token(&extra_data, name, ",", sizeof(fstring)))
144                         PyList_Append(result, PyString_FromString(name));
145         }
146
147         return result;
148 }
149
150 /* Enumerate domain groups */
151
152 static PyObject *winbind_enum_domain_groups(PyObject *self, PyObject *args)
153 {
154         struct winbindd_response response;
155         PyObject *result = NULL;
156
157         if (!PyArg_ParseTuple(args, ""))
158                 return NULL;
159
160         ZERO_STRUCT(response);
161
162         if (winbindd_request(WINBINDD_LIST_GROUPS, NULL, &response) 
163             != NSS_STATUS_SUCCESS) {
164                 PyErr_SetString(winbind_error, "lookup failed");
165                 return NULL;            
166         }
167
168         result = PyList_New(0);
169
170         if (response.extra_data) {
171                 char *extra_data = response.extra_data;
172                 fstring name;
173
174                 while (next_token(&extra_data, name, ",", sizeof(fstring)))
175                         PyList_Append(result, PyString_FromString(name));
176         }
177
178         return result;
179 }
180
181 /*
182  * Miscellaneous domain related
183  */
184
185 /* Enumerate domain groups */
186
187 static PyObject *winbind_enum_trust_dom(PyObject *self, PyObject *args)
188 {
189         struct winbindd_response response;
190         PyObject *result = NULL;
191
192         if (!PyArg_ParseTuple(args, ""))
193                 return NULL;
194
195         ZERO_STRUCT(response);
196
197         if (winbindd_request(WINBINDD_LIST_TRUSTDOM, NULL, &response) 
198             != NSS_STATUS_SUCCESS) {
199                 PyErr_SetString(winbind_error, "lookup failed");
200                 return NULL;            
201         }
202
203         result = PyList_New(0);
204
205         if (response.extra_data) {
206                 char *extra_data = response.extra_data;
207                 fstring name;
208
209                 while (next_token(&extra_data, name, ",", sizeof(fstring)))
210                         PyList_Append(result, PyString_FromString(name));
211         }
212
213         return result;
214 }
215
216 /* Check machine account password */
217
218 static PyObject *winbind_check_secret(PyObject *self, PyObject *args)
219 {
220         struct winbindd_response response;
221
222         if (!PyArg_ParseTuple(args, ""))
223                 return NULL;
224
225         ZERO_STRUCT(response);
226
227         if (winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response) 
228             != NSS_STATUS_SUCCESS) {
229                 PyErr_SetString(winbind_error, "lookup failed");
230                 return NULL;            
231         }
232
233         return PyInt_FromLong(response.data.num_entries);
234 }
235
236 /*
237  * Return a dictionary consisting of all the winbind related smb.conf
238  * parameters.  This is stored in the module object.
239  */
240
241 static PyObject *winbind_config_dict(void)
242 {
243         PyObject *result;
244         uid_t ulow, uhi;
245         gid_t glow, ghi;
246         
247         if (!(result = PyDict_New()))
248                 return NULL;
249
250         /* Various string parameters */
251
252         PyDict_SetItemString(result, "workgroup", 
253                              PyString_FromString(lp_workgroup()));
254
255         PyDict_SetItemString(result, "separator", 
256                              PyString_FromString(lp_winbind_separator()));
257
258         PyDict_SetItemString(result, "template homedir", 
259                              PyString_FromString(lp_template_homedir()));
260
261         PyDict_SetItemString(result, "template shell", 
262                              PyString_FromString(lp_template_shell()));
263
264         /* Winbind uid/gid range */
265
266         if (lp_winbind_uid(&ulow, &uhi)) {
267                 PyDict_SetItemString(result, "uid low", PyInt_FromLong(ulow));
268                 PyDict_SetItemString(result, "uid high", PyInt_FromLong(uhi));
269         }
270
271         if (lp_winbind_gid(&glow, &ghi)) {
272                 PyDict_SetItemString(result, "gid low", PyInt_FromLong(glow));
273                 PyDict_SetItemString(result, "gid high", PyInt_FromLong(ghi));
274         }
275
276         return result;
277 }
278
279 /*
280  * Method dispatch table
281  */
282
283 static PyMethodDef winbind_methods[] = {
284
285         /* Name <-> SID conversion */
286
287         { "name_to_sid", winbind_name_to_sid, METH_VARARGS,
288           "Convert a name to a sid" },
289
290         { "sid_to_name", winbind_sid_to_name, METH_VARARGS,
291           "Convert a sid to a name" },
292
293         /* Enumerate users/groups */
294
295         { "enum_domain_users", winbind_enum_domain_users, METH_VARARGS,
296           "Enumerate domain users" },
297
298         { "enum_domain_groups", winbind_enum_domain_groups, METH_VARARGS,
299           "Enumerate domain groups" },
300
301         /* Miscellaneous */
302
303         { "check_secret", winbind_check_secret, METH_VARARGS,
304           "Check machine account password" },
305
306         { "enum_trust_dom", winbind_enum_trust_dom, METH_VARARGS,
307           "Enumerate trusted domains" },
308
309         { NULL }
310 };
311
312 /*
313  * Module initialisation 
314  */
315
316 void initwinbind(void)
317 {
318         PyObject *module, *dict;
319
320         /* Initialise module */
321
322         module = Py_InitModule("winbind", winbind_methods);
323         dict = PyModule_GetDict(module);
324
325         winbind_error = PyErr_NewException("winbind.error", NULL, NULL);
326         PyDict_SetItemString(dict, "error", winbind_error);
327
328         /* Do samba initialisation */
329
330         py_samba_init();
331
332         /* Insert configuration dictionary */
333
334         PyDict_SetItemString(dict, "config", winbind_config_dict());
335 }