2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2010
6 Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "auth/credentials/pycredentials.h"
28 #include "libcli/security/security.h"
29 #include "lib/events/events.h"
30 #include "param/pyparam.h"
31 #include "auth/gensec/gensec.h"
32 #include "librpc/rpc/pyrpc_util.h"
33 #include "libcli/resolve/resolve.h"
34 #include "libcli/finddc.h"
35 #include "dsdb/samdb/samdb.h"
37 #include "librpc/rpc/pyrpc_util.h"
41 static void PyErr_SetDsExtendedError(enum drsuapi_DsExtendedError ext_err
, const char *error_description
)
43 PyObject
*error
= PyObject_GetAttrString(PyImport_ImportModule("samba"),
45 if (error_description
== NULL
) {
47 /* Copied out of ndr_drsuapi.c:ndr_print_drsuapi_DsExtendedError() */
48 case DRSUAPI_EXOP_ERR_NONE
:
49 error_description
= "DRSUAPI_EXOP_ERR_NONE";
51 case DRSUAPI_EXOP_ERR_SUCCESS
:
52 error_description
= "DRSUAPI_EXOP_ERR_SUCCESS";
54 case DRSUAPI_EXOP_ERR_UNKNOWN_OP
:
55 error_description
= "DRSUAPI_EXOP_ERR_UNKNOWN_OP";
57 case DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER
:
58 error_description
= "DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER";
60 case DRSUAPI_EXOP_ERR_UPDATE_ERR
:
61 error_description
= "DRSUAPI_EXOP_ERR_UPDATE_ERR";
63 case DRSUAPI_EXOP_ERR_EXCEPTION
:
64 error_description
= "DRSUAPI_EXOP_ERR_EXCEPTION";
66 case DRSUAPI_EXOP_ERR_UNKNOWN_CALLER
:
67 error_description
= "DRSUAPI_EXOP_ERR_UNKNOWN_CALLER";
69 case DRSUAPI_EXOP_ERR_RID_ALLOC
:
70 error_description
= "DRSUAPI_EXOP_ERR_RID_ALLOC";
72 case DRSUAPI_EXOP_ERR_FSMO_OWNER_DELETED
:
73 error_description
= "DRSUAPI_EXOP_ERR_FSMO_OWNER_DELETED";
75 case DRSUAPI_EXOP_ERR_FMSO_PENDING_OP
:
76 error_description
= "DRSUAPI_EXOP_ERR_FMSO_PENDING_OP";
78 case DRSUAPI_EXOP_ERR_MISMATCH
:
79 error_description
= "DRSUAPI_EXOP_ERR_MISMATCH";
81 case DRSUAPI_EXOP_ERR_COULDNT_CONTACT
:
82 error_description
= "DRSUAPI_EXOP_ERR_COULDNT_CONTACT";
84 case DRSUAPI_EXOP_ERR_FSMO_REFUSING_ROLES
:
85 error_description
= "DRSUAPI_EXOP_ERR_FSMO_REFUSING_ROLES";
87 case DRSUAPI_EXOP_ERR_DIR_ERROR
:
88 error_description
= "DRSUAPI_EXOP_ERR_DIR_ERROR";
90 case DRSUAPI_EXOP_ERR_FSMO_MISSING_SETTINGS
:
91 error_description
= "DRSUAPI_EXOP_ERR_FSMO_MISSING_SETTINGS";
93 case DRSUAPI_EXOP_ERR_ACCESS_DENIED
:
94 error_description
= "DRSUAPI_EXOP_ERR_ACCESS_DENIED";
96 case DRSUAPI_EXOP_ERR_PARAM_ERROR
:
97 error_description
= "DRSUAPI_EXOP_ERR_PARAM_ERROR";
101 PyErr_SetObject(error
,
102 Py_BuildValue(discard_const_p(char, "(i,s)"),
107 static PyObject
*py_net_join_member(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
109 struct libnet_Join_member r
;
114 const char *kwnames
[] = { "domain_name", "netbios_name", "level", "machinepass", NULL
};
118 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "ssi|z:Join", discard_const_p(char *, kwnames
),
119 &r
.in
.domain_name
, &r
.in
.netbios_name
,
121 &r
.in
.account_pass
)) {
126 mem_ctx
= talloc_new(self
->mem_ctx
);
127 if (mem_ctx
== NULL
) {
132 status
= libnet_Join_member(self
->libnet_ctx
, mem_ctx
, &r
);
133 if (NT_STATUS_IS_ERR(status
)) {
134 PyErr_SetNTSTATUS_and_string(status
,
137 : nt_errstr(status
));
138 talloc_free(mem_ctx
);
142 result
= Py_BuildValue("sss", r
.out
.join_password
,
143 dom_sid_string(mem_ctx
, r
.out
.domain_sid
),
146 talloc_free(mem_ctx
);
151 static const char py_net_join_member_doc
[] = "join_member(domain_name, netbios_name, level) -> (join_password, domain_sid, domain_name)\n\n" \
152 "Join the domain with the specified name.";
154 static PyObject
*py_net_change_password(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
156 union libnet_ChangePassword r
;
159 struct tevent_context
*ev
;
160 const char *kwnames
[] = { "newpassword", NULL
};
164 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s:change_password",
165 discard_const_p(char *, kwnames
),
166 &r
.generic
.in
.newpassword
)) {
170 r
.generic
.level
= LIBNET_CHANGE_PASSWORD_GENERIC
;
171 r
.generic
.in
.account_name
= cli_credentials_get_username(self
->libnet_ctx
->cred
);
172 r
.generic
.in
.domain_name
= cli_credentials_get_domain(self
->libnet_ctx
->cred
);
173 r
.generic
.in
.oldpassword
= cli_credentials_get_password(self
->libnet_ctx
->cred
);
175 /* FIXME: we really need to get a context from the caller or we may end
176 * up with 2 event contexts */
177 ev
= s4_event_context_init(NULL
);
179 mem_ctx
= talloc_new(ev
);
180 if (mem_ctx
== NULL
) {
185 status
= libnet_ChangePassword(self
->libnet_ctx
, mem_ctx
, &r
);
186 if (NT_STATUS_IS_ERR(status
)) {
187 PyErr_SetNTSTATUS_and_string(status
,
188 r
.generic
.out
.error_string
189 ? r
.generic
.out
.error_string
190 : nt_errstr(status
));
191 talloc_free(mem_ctx
);
195 talloc_free(mem_ctx
);
200 static const char py_net_change_password_doc
[] = "change_password(newpassword) -> True\n\n" \
201 "Change password for a user. You must supply credential with enough rights to do this.\n\n" \
202 "Sample usage is:\n" \
203 "net.change_password(newpassword=<new_password>)\n";
206 static PyObject
*py_net_set_password(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
208 union libnet_SetPassword r
;
211 struct tevent_context
*ev
;
212 const char *kwnames
[] = { "account_name", "domain_name", "newpassword", NULL
};
216 r
.generic
.level
= LIBNET_SET_PASSWORD_GENERIC
;
218 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sss:set_password",
219 discard_const_p(char *, kwnames
),
220 &r
.generic
.in
.account_name
,
221 &r
.generic
.in
.domain_name
,
222 &r
.generic
.in
.newpassword
)) {
226 /* FIXME: we really need to get a context from the caller or we may end
227 * up with 2 event contexts */
228 ev
= s4_event_context_init(NULL
);
230 mem_ctx
= talloc_new(ev
);
231 if (mem_ctx
== NULL
) {
236 status
= libnet_SetPassword(self
->libnet_ctx
, mem_ctx
, &r
);
237 if (NT_STATUS_IS_ERR(status
)) {
238 PyErr_SetNTSTATUS_and_string(status
,
239 r
.generic
.out
.error_string
240 ? r
.generic
.out
.error_string
241 : nt_errstr(status
));
242 talloc_free(mem_ctx
);
246 talloc_free(mem_ctx
);
251 static const char py_net_set_password_doc
[] = "set_password(account_name, domain_name, newpassword) -> True\n\n" \
252 "Set password for a user. You must supply credential with enough rights to do this.\n\n" \
253 "Sample usage is:\n" \
254 "net.set_password(account_name=account_name, domain_name=domain_name, newpassword=new_pass)\n";
257 static PyObject
*py_net_time(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
259 const char *kwnames
[] = { "server_name", NULL
};
260 union libnet_RemoteTOD r
;
267 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s",
268 discard_const_p(char *, kwnames
), &r
.generic
.in
.server_name
))
271 r
.generic
.level
= LIBNET_REMOTE_TOD_GENERIC
;
273 mem_ctx
= talloc_new(NULL
);
274 if (mem_ctx
== NULL
) {
279 status
= libnet_RemoteTOD(self
->libnet_ctx
, mem_ctx
, &r
);
280 if (!NT_STATUS_IS_OK(status
)) {
281 PyErr_SetNTSTATUS_and_string(status
,
282 r
.generic
.out
.error_string
283 ? r
.generic
.out
.error_string
284 : nt_errstr(status
));
285 talloc_free(mem_ctx
);
289 ZERO_STRUCT(timestr
);
290 tm
= localtime(&r
.generic
.out
.time
);
291 strftime(timestr
, sizeof(timestr
)-1, "%c %Z",tm
);
293 ret
= PyString_FromString(timestr
);
295 talloc_free(mem_ctx
);
300 static const char py_net_time_doc
[] = "time(server_name) -> timestr\n"
301 "Retrieve the remote time on a server";
303 static PyObject
*py_net_user_create(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
305 const char *kwnames
[] = { "username", NULL
};
308 struct libnet_CreateUser r
;
310 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s", discard_const_p(char *, kwnames
),
314 r
.in
.domain_name
= cli_credentials_get_domain(self
->libnet_ctx
->cred
);
316 mem_ctx
= talloc_new(NULL
);
317 if (mem_ctx
== NULL
) {
322 status
= libnet_CreateUser(self
->libnet_ctx
, mem_ctx
, &r
);
323 if (!NT_STATUS_IS_OK(status
)) {
324 PyErr_SetNTSTATUS_and_string(status
,
327 : nt_errstr(status
));
328 talloc_free(mem_ctx
);
332 talloc_free(mem_ctx
);
337 static const char py_net_create_user_doc
[] = "create_user(username)\n"
338 "Create a new user.";
340 static PyObject
*py_net_user_delete(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
342 const char *kwnames
[] = { "username", NULL
};
345 struct libnet_DeleteUser r
;
347 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s", discard_const_p(char *, kwnames
),
351 r
.in
.domain_name
= cli_credentials_get_domain(self
->libnet_ctx
->cred
);
353 mem_ctx
= talloc_new(NULL
);
354 if (mem_ctx
== NULL
) {
359 status
= libnet_DeleteUser(self
->libnet_ctx
, mem_ctx
, &r
);
360 if (!NT_STATUS_IS_OK(status
)) {
361 PyErr_SetNTSTATUS_and_string(status
,
364 : nt_errstr(status
));
365 talloc_free(mem_ctx
);
369 talloc_free(mem_ctx
);
374 static const char py_net_delete_user_doc
[] = "delete_user(username)\n"
377 struct replicate_state
{
379 dcerpc_InterfaceObject
*drs_pipe
;
380 struct libnet_BecomeDC_StoreChunk chunk
;
381 DATA_BLOB gensec_skey
;
382 struct libnet_BecomeDC_Partition partition
;
383 struct libnet_BecomeDC_Forest forest
;
384 struct libnet_BecomeDC_DestDSA dest_dsa
;
388 setup for replicate_chunk() calls
390 static PyObject
*py_net_replicate_init(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
392 const char *kwnames
[] = { "samdb", "lp", "drspipe", "invocation_id", NULL
};
393 PyObject
*py_ldb
, *py_lp
, *py_drspipe
, *py_invocation_id
;
394 struct ldb_context
*samdb
;
395 struct loadparm_context
*lp
;
396 struct replicate_state
*s
;
399 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OOOO",
400 discard_const_p(char *, kwnames
),
401 &py_ldb
, &py_lp
, &py_drspipe
,
402 &py_invocation_id
)) {
406 s
= talloc_zero(NULL
, struct replicate_state
);
409 lp
= lpcfg_from_py_object(s
, py_lp
);
411 PyErr_SetString(PyExc_TypeError
, "Expected lp object");
416 samdb
= pyldb_Ldb_AsLdbContext(py_ldb
);
418 PyErr_SetString(PyExc_TypeError
, "Expected ldb object");
422 if (!py_check_dcerpc_type(py_invocation_id
, "samba.dcerpc.misc", "GUID")) {
427 s
->dest_dsa
.invocation_id
= *pytalloc_get_type(py_invocation_id
, struct GUID
);
429 s
->drs_pipe
= (dcerpc_InterfaceObject
*)(py_drspipe
);
431 s
->vampire_state
= libnet_vampire_replicate_init(s
, samdb
, lp
);
432 if (s
->vampire_state
== NULL
) {
433 PyErr_SetString(PyExc_TypeError
, "Failed to initialise vampire_state");
438 status
= gensec_session_key(s
->drs_pipe
->pipe
->conn
->security_state
.generic_state
,
441 if (!NT_STATUS_IS_OK(status
)) {
442 char *error_string
= talloc_asprintf(s
,
443 "Unable to get session key from drspipe: %s",
445 PyErr_SetNTSTATUS_and_string(status
, error_string
);
450 s
->forest
.dns_name
= samdb_dn_to_dns_domain(s
, ldb_get_root_basedn(samdb
));
451 s
->forest
.root_dn_str
= ldb_dn_get_linearized(ldb_get_root_basedn(samdb
));
452 s
->forest
.config_dn_str
= ldb_dn_get_linearized(ldb_get_config_basedn(samdb
));
453 s
->forest
.schema_dn_str
= ldb_dn_get_linearized(ldb_get_schema_basedn(samdb
));
455 s
->chunk
.gensec_skey
= &s
->gensec_skey
;
456 s
->chunk
.partition
= &s
->partition
;
457 s
->chunk
.forest
= &s
->forest
;
458 s
->chunk
.dest_dsa
= &s
->dest_dsa
;
460 return pytalloc_CObject_FromTallocPtr(s
);
465 process one replication chunk
467 static PyObject
*py_net_replicate_chunk(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
469 const char *kwnames
[] = { "state", "level", "ctr",
470 "schema", "req_level", "req",
472 PyObject
*py_state
, *py_ctr
, *py_schema
= Py_None
, *py_req
= Py_None
;
473 struct replicate_state
*s
;
475 unsigned req_level
= 0;
476 WERROR (*chunk_handler
)(void *private_data
, const struct libnet_BecomeDC_StoreChunk
*c
);
478 enum drsuapi_DsExtendedError extended_ret
= DRSUAPI_EXOP_ERR_NONE
;
479 enum drsuapi_DsExtendedOperation exop
= DRSUAPI_EXOP_NONE
;
481 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OIO|OIO",
482 discard_const_p(char *, kwnames
),
483 &py_state
, &level
, &py_ctr
,
484 &py_schema
, &req_level
, &py_req
)) {
488 s
= talloc_get_type(PyCObject_AsVoidPtr(py_state
), struct replicate_state
);
490 PyErr_SetString(PyExc_TypeError
, "Expected replication_state");
496 if (!py_check_dcerpc_type(py_ctr
, "samba.dcerpc.drsuapi", "DsGetNCChangesCtr1")) {
499 s
->chunk
.ctr1
= pytalloc_get_ptr(py_ctr
);
500 if (s
->chunk
.ctr1
->naming_context
!= NULL
) {
501 s
->partition
.nc
= *s
->chunk
.ctr1
->naming_context
;
503 extended_ret
= s
->chunk
.ctr1
->extended_ret
;
504 s
->partition
.more_data
= s
->chunk
.ctr1
->more_data
;
505 s
->partition
.source_dsa_guid
= s
->chunk
.ctr1
->source_dsa_guid
;
506 s
->partition
.source_dsa_invocation_id
= s
->chunk
.ctr1
->source_dsa_invocation_id
;
507 s
->partition
.highwatermark
= s
->chunk
.ctr1
->new_highwatermark
;
510 if (!py_check_dcerpc_type(py_ctr
, "samba.dcerpc.drsuapi", "DsGetNCChangesCtr6")) {
513 s
->chunk
.ctr6
= pytalloc_get_ptr(py_ctr
);
514 if (s
->chunk
.ctr6
->naming_context
!= NULL
) {
515 s
->partition
.nc
= *s
->chunk
.ctr6
->naming_context
;
517 extended_ret
= s
->chunk
.ctr6
->extended_ret
;
518 s
->partition
.more_data
= s
->chunk
.ctr6
->more_data
;
519 s
->partition
.source_dsa_guid
= s
->chunk
.ctr6
->source_dsa_guid
;
520 s
->partition
.source_dsa_invocation_id
= s
->chunk
.ctr6
->source_dsa_invocation_id
;
521 s
->partition
.highwatermark
= s
->chunk
.ctr6
->new_highwatermark
;
524 PyErr_Format(PyExc_TypeError
, "Bad level %u in replicate_chunk", level
);
528 s
->chunk
.req5
= NULL
;
529 s
->chunk
.req8
= NULL
;
530 s
->chunk
.req10
= NULL
;
536 if (!py_check_dcerpc_type(py_req
, "samba.dcerpc.drsuapi", "DsGetNCChangesRequest5")) {
540 s
->chunk
.req5
= pytalloc_get_ptr(py_req
);
541 exop
= s
->chunk
.req5
->extended_op
;
544 if (!py_check_dcerpc_type(py_req
, "samba.dcerpc.drsuapi", "DsGetNCChangesRequest8")) {
548 s
->chunk
.req8
= pytalloc_get_ptr(py_req
);
549 exop
= s
->chunk
.req8
->extended_op
;
552 if (!py_check_dcerpc_type(py_req
, "samba.dcerpc.drsuapi", "DsGetNCChangesRequest10")) {
556 s
->chunk
.req10
= pytalloc_get_ptr(py_req
);
557 exop
= s
->chunk
.req10
->extended_op
;
560 PyErr_Format(PyExc_TypeError
, "Bad req_level %u in replicate_chunk", req_level
);
565 if (exop
!= DRSUAPI_EXOP_NONE
&& extended_ret
!= DRSUAPI_EXOP_ERR_SUCCESS
) {
566 PyErr_SetDsExtendedError(extended_ret
, NULL
);
570 s
->chunk
.req_level
= req_level
;
572 chunk_handler
= libnet_vampire_cb_store_chunk
;
574 if (!PyBool_Check(py_schema
)) {
575 PyErr_SetString(PyExc_TypeError
, "Expected boolean schema");
578 if (py_schema
== Py_True
) {
579 chunk_handler
= libnet_vampire_cb_schema_chunk
;
583 s
->chunk
.ctr_level
= level
;
585 werr
= chunk_handler(s
->vampire_state
, &s
->chunk
);
586 if (!W_ERROR_IS_OK(werr
)) {
588 = talloc_asprintf(NULL
,
589 "Failed to process 'chunk' of DRS replicated objects: %s",
591 PyErr_SetWERROR_and_string(werr
, error_string
);
592 TALLOC_FREE(error_string
);
601 find a DC given a domain name and server type
603 static PyObject
*py_net_finddc(py_net_Object
*self
, PyObject
*args
, PyObject
*kwargs
)
605 const char *domain
= NULL
, *address
= NULL
;
606 unsigned server_type
;
611 const char * const kwnames
[] = { "flags", "domain", "address", NULL
};
613 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "I|zz",
614 discard_const_p(char *, kwnames
),
615 &server_type
, &domain
, &address
)) {
619 mem_ctx
= talloc_new(self
->mem_ctx
);
621 io
= talloc_zero(mem_ctx
, struct finddcs
);
622 if (domain
!= NULL
) {
623 io
->in
.domain_name
= domain
;
625 if (address
!= NULL
) {
626 io
->in
.server_address
= address
;
628 io
->in
.minimum_dc_flags
= server_type
;
630 status
= finddcs_cldap(io
, io
,
631 lpcfg_resolve_context(self
->libnet_ctx
->lp_ctx
), self
->ev
);
632 if (NT_STATUS_IS_ERR(status
)) {
633 PyErr_SetNTSTATUS(status
);
634 talloc_free(mem_ctx
);
638 ret
= py_return_ndr_struct("samba.dcerpc.nbt", "NETLOGON_SAM_LOGON_RESPONSE_EX",
639 io
, &io
->out
.netlogon
.data
.nt5_ex
);
640 talloc_free(mem_ctx
);
646 static const char py_net_replicate_init_doc
[] = "replicate_init(samdb, lp, drspipe)\n"
647 "Setup for replicate_chunk calls.";
649 static const char py_net_replicate_chunk_doc
[] = "replicate_chunk(state, level, ctr, schema)\n"
650 "Process replication for one chunk";
652 static const char py_net_finddc_doc
[] = "finddc(flags=server_type, domain=None, address=None)\n"
653 "Find a DC with the specified 'server_type' bits. The 'domain' and/or 'address' have to be used as additional search criteria. Returns the whole netlogon struct";
655 static PyMethodDef net_obj_methods
[] = {
656 {"join_member", (PyCFunction
)py_net_join_member
, METH_VARARGS
|METH_KEYWORDS
, py_net_join_member_doc
},
657 {"change_password", (PyCFunction
)py_net_change_password
, METH_VARARGS
|METH_KEYWORDS
, py_net_change_password_doc
},
658 {"set_password", (PyCFunction
)py_net_set_password
, METH_VARARGS
|METH_KEYWORDS
, py_net_set_password_doc
},
659 {"time", (PyCFunction
)py_net_time
, METH_VARARGS
|METH_KEYWORDS
, py_net_time_doc
},
660 {"create_user", (PyCFunction
)py_net_user_create
, METH_VARARGS
|METH_KEYWORDS
, py_net_create_user_doc
},
661 {"delete_user", (PyCFunction
)py_net_user_delete
, METH_VARARGS
|METH_KEYWORDS
, py_net_delete_user_doc
},
662 {"replicate_init", (PyCFunction
)py_net_replicate_init
, METH_VARARGS
|METH_KEYWORDS
, py_net_replicate_init_doc
},
663 {"replicate_chunk", (PyCFunction
)py_net_replicate_chunk
, METH_VARARGS
|METH_KEYWORDS
, py_net_replicate_chunk_doc
},
664 {"finddc", (PyCFunction
)py_net_finddc
, METH_KEYWORDS
, py_net_finddc_doc
},
668 static void py_net_dealloc(py_net_Object
*self
)
670 talloc_free(self
->mem_ctx
);
674 static PyObject
*net_obj_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
676 PyObject
*py_creds
, *py_lp
= Py_None
;
677 const char *kwnames
[] = { "creds", "lp", "server", NULL
};
679 struct loadparm_context
*lp
;
680 const char *server_address
= NULL
;
682 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oz",
683 discard_const_p(char *, kwnames
), &py_creds
, &py_lp
,
687 ret
= PyObject_New(py_net_Object
, type
);
692 /* FIXME: we really need to get a context from the caller or we may end
693 * up with 2 event contexts */
694 ret
->ev
= s4_event_context_init(NULL
);
695 ret
->mem_ctx
= talloc_new(ret
->ev
);
697 lp
= lpcfg_from_py_object(ret
->mem_ctx
, py_lp
);
703 ret
->libnet_ctx
= libnet_context_init(ret
->ev
, lp
);
704 if (ret
->libnet_ctx
== NULL
) {
705 PyErr_SetString(PyExc_RuntimeError
, "Unable to initialize net");
710 ret
->libnet_ctx
->server_address
= server_address
;
712 ret
->libnet_ctx
->cred
= cli_credentials_from_py_object(py_creds
);
713 if (ret
->libnet_ctx
->cred
== NULL
) {
714 PyErr_SetString(PyExc_TypeError
, "Expected credentials object");
719 return (PyObject
*)ret
;
723 PyTypeObject py_net_Type
= {
724 PyObject_HEAD_INIT(NULL
) 0,
725 .tp_name
= "net.Net",
726 .tp_basicsize
= sizeof(py_net_Object
),
727 .tp_dealloc
= (destructor
)py_net_dealloc
,
728 .tp_methods
= net_obj_methods
,
729 .tp_new
= net_obj_new
,
736 if (PyType_Ready(&py_net_Type
) < 0)
739 m
= Py_InitModule3("net", NULL
, NULL
);
743 Py_INCREF(&py_net_Type
);
744 PyModule_AddObject(m
, "Net", (PyObject
*)&py_net_Type
);
745 PyModule_AddObject(m
, "LIBNET_JOINDOMAIN_AUTOMATIC", PyInt_FromLong(LIBNET_JOINDOMAIN_AUTOMATIC
));
746 PyModule_AddObject(m
, "LIBNET_JOINDOMAIN_SPECIFIED", PyInt_FromLong(LIBNET_JOINDOMAIN_SPECIFIED
));
747 PyModule_AddObject(m
, "LIBNET_JOIN_AUTOMATIC", PyInt_FromLong(LIBNET_JOIN_AUTOMATIC
));
748 PyModule_AddObject(m
, "LIBNET_JOIN_SPECIFIED", PyInt_FromLong(LIBNET_JOIN_SPECIFIED
));