Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/libnet/py_net.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33   Samba utility functions
    4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
    5    
     4   Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2010
     5   Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
     6
    67   This program is free software; you can redistribute it and/or modify
    78   it under the terms of the GNU General Public License as published by
    89   the Free Software Foundation; either version 3 of the License, or
    910   (at your option) any later version.
    10    
     11
    1112   This program is distributed in the hope that it will be useful,
    1213   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1314   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1415   GNU General Public License for more details.
    15    
     16
    1617   You should have received a copy of the GNU General Public License
    1718   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1819*/
    1920
     21#include <Python.h>
    2022#include "includes.h"
    21 #include <Python.h>
     23#include <ldb.h>
     24#include <pyldb.h>
    2225#include "libnet.h"
    2326#include "auth/credentials/pycredentials.h"
    2427#include "libcli/security/security.h"
    2528#include "lib/events/events.h"
    26 #include "param/param.h"
    27 
    28 /* FIXME: This prototype should be in param/pyparam.h */
    29 struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx);
    30 
    31 static struct libnet_context *py_net_ctx(PyObject *obj, struct tevent_context *ev, struct cli_credentials *creds)
    32 {
    33 /* FIXME: Use obj */
    34         struct libnet_context *libnet;
    35         libnet = libnet_context_init(ev, py_default_loadparm_context(NULL));
    36         if (!libnet) {
    37                 return NULL;
    38         }
    39         libnet->cred = creds;
    40         return libnet;
    41 }
    42 
    43 static PyObject *py_net_join(PyObject *cls, PyObject *args, PyObject *kwargs)
     29#include "param/pyparam.h"
     30#include "auth/gensec/gensec.h"
     31#include "librpc/rpc/pyrpc_util.h"
     32#include "libcli/finddc.h"
     33#include "libcli/resolve/resolve.h"
     34
     35void initnet(void);
     36
     37typedef struct {
     38        PyObject_HEAD
     39        TALLOC_CTX *mem_ctx;
     40        struct libnet_context *libnet_ctx;
     41        struct tevent_context *ev;
     42} py_net_Object;
     43
     44static PyObject *py_net_join(py_net_Object *self, PyObject *args, PyObject *kwargs)
    4445{
    4546        struct libnet_Join r;
     
    4748        PyObject *result;
    4849        TALLOC_CTX *mem_ctx;
     50        const char *kwnames[] = { "domain_name", "netbios_name", "join_type", "level", NULL };
     51
     52        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssii:Join", discard_const_p(char *, kwnames),
     53                                         &r.in.domain_name, &r.in.netbios_name,
     54                                         &r.in.join_type, &r.in.level))
     55                return NULL;
     56
     57        mem_ctx = talloc_new(self->mem_ctx);
     58        if (mem_ctx == NULL) {
     59                PyErr_NoMemory();
     60                return NULL;
     61        }
     62
     63        status = libnet_Join(self->libnet_ctx, mem_ctx, &r);
     64        if (NT_STATUS_IS_ERR(status)) {
     65                PyErr_SetString(PyExc_RuntimeError, r.out.error_string?r.out.error_string:nt_errstr(status));
     66                talloc_free(mem_ctx);
     67                return NULL;
     68        }
     69
     70        result = Py_BuildValue("sss", r.out.join_password,
     71                               dom_sid_string(mem_ctx, r.out.domain_sid),
     72                               r.out.domain_name);
     73
     74        talloc_free(mem_ctx);
     75
     76        return result;
     77}
     78
     79static const char py_net_join_doc[] = "join(domain_name, netbios_name, join_type, level) -> (join_password, domain_sid, domain_name)\n\n" \
     80"Join the domain with the specified name.";
     81
     82static PyObject *py_net_set_password(py_net_Object *self, PyObject *args, PyObject *kwargs)
     83{
     84        union libnet_SetPassword r;
     85        NTSTATUS status;
     86        PyObject *py_creds;
     87        TALLOC_CTX *mem_ctx;
    4988        struct tevent_context *ev;
    50         struct libnet_context *libnet_ctx;
    51         struct cli_credentials *creds;
    52         PyObject *py_creds;     
    53         const char *kwnames[] = { "domain_name", "netbios_name", "join_type", "level", "credentials", NULL };
    54 
    55         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssiiO:Join", discard_const_p(char *, kwnames),
    56                                          &r.in.domain_name, &r.in.netbios_name,
    57                                          &r.in.join_type, &r.in.level, &py_creds))
    58                 return NULL;
     89        const char *kwnames[] = { "account_name", "domain_name", "newpassword", "credentials", NULL };
     90
     91        r.generic.level = LIBNET_SET_PASSWORD_GENERIC;
     92
     93        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sssO:set_password", discard_const_p(char *, kwnames),
     94                                         &r.generic.in.account_name, &r.generic.in.domain_name,
     95                                         &r.generic.in.newpassword, &py_creds)) {
     96                return NULL;
     97        }
    5998
    6099        /* FIXME: we really need to get a context from the caller or we may end
    61100         * up with 2 event contexts */
    62101        ev = s4_event_context_init(NULL);
     102
    63103        mem_ctx = talloc_new(ev);
    64 
    65         creds = cli_credentials_from_py_object(py_creds);
    66         if (creds == NULL) {
     104        if (mem_ctx == NULL) {
     105                PyErr_NoMemory();
     106                return NULL;
     107        }
     108
     109        status = libnet_SetPassword(self->libnet_ctx, mem_ctx, &r);
     110        if (NT_STATUS_IS_ERR(status)) {
     111                PyErr_SetString(PyExc_RuntimeError,
     112                                r.generic.out.error_string?r.generic.out.error_string:nt_errstr(status));
     113                talloc_free(mem_ctx);
     114                return NULL;
     115        }
     116
     117        talloc_free(mem_ctx);
     118
     119        Py_RETURN_NONE;
     120}
     121
     122static const char py_net_set_password_doc[] = "set_password(account_name, domain_name, newpassword) -> True\n\n" \
     123"Set password for a user. You must supply credential with enough rights to do this.\n\n" \
     124"Sample usage is:\n" \
     125"net.set_password(account_name=<account_name>,\n" \
     126"                domain_name=domain_name,\n" \
     127"                newpassword=new_pass)\n";
     128
     129
     130static PyObject *py_net_export_keytab(py_net_Object *self, PyObject *args, PyObject *kwargs)
     131{
     132        struct libnet_export_keytab r;
     133        TALLOC_CTX *mem_ctx;
     134        const char *kwnames[] = { "keytab", NULL };
     135        NTSTATUS status;
     136
     137        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:export_keytab", discard_const_p(char *, kwnames),
     138                                         &r.in.keytab_name)) {
     139                return NULL;
     140        }
     141
     142        mem_ctx = talloc_new(self->mem_ctx);
     143        if (mem_ctx == NULL) {
     144                PyErr_NoMemory();
     145                return NULL;
     146        }
     147
     148        status = libnet_export_keytab(self->libnet_ctx, mem_ctx, &r);
     149        if (NT_STATUS_IS_ERR(status)) {
     150                PyErr_SetString(PyExc_RuntimeError,
     151                                r.out.error_string?r.out.error_string:nt_errstr(status));
     152                talloc_free(mem_ctx);
     153                return NULL;
     154        }
     155
     156        talloc_free(mem_ctx);
     157
     158        Py_RETURN_NONE;
     159}
     160
     161static const char py_net_export_keytab_doc[] = "export_keytab(keytab, name)\n\n"
     162"Export the DC keytab to a keytab file.";
     163
     164static PyObject *py_net_time(py_net_Object *self, PyObject *args, PyObject *kwargs)
     165{
     166        const char *kwnames[] = { "server_name", NULL };
     167        union libnet_RemoteTOD r;
     168        NTSTATUS status;
     169        TALLOC_CTX *mem_ctx;
     170        char timestr[64];
     171        PyObject *ret;
     172        struct tm *tm;
     173
     174        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s",
     175                discard_const_p(char *, kwnames), &r.generic.in.server_name))
     176                return NULL;
     177
     178        r.generic.level                 = LIBNET_REMOTE_TOD_GENERIC;
     179
     180        mem_ctx = talloc_new(NULL);
     181        if (mem_ctx == NULL) {
     182                PyErr_NoMemory();
     183                return NULL;
     184        }
     185
     186        status = libnet_RemoteTOD(self->libnet_ctx, mem_ctx, &r);
     187        if (!NT_STATUS_IS_OK(status)) {
     188                PyErr_SetString(PyExc_RuntimeError,
     189                                r.generic.out.error_string?r.generic.out.error_string:nt_errstr(status));
     190                talloc_free(mem_ctx);
     191                return NULL;
     192        }
     193
     194        ZERO_STRUCT(timestr);
     195        tm = localtime(&r.generic.out.time);
     196        strftime(timestr, sizeof(timestr)-1, "%c %Z",tm);
     197       
     198        ret = PyString_FromString(timestr);
     199
     200        talloc_free(mem_ctx);
     201
     202        return ret;
     203}
     204
     205static const char py_net_time_doc[] = "time(server_name) -> timestr\n"
     206"Retrieve the remote time on a server";
     207
     208static PyObject *py_net_user_create(py_net_Object *self, PyObject *args, PyObject *kwargs)
     209{
     210        const char *kwnames[] = { "username", NULL };
     211        NTSTATUS status;
     212        TALLOC_CTX *mem_ctx;
     213        struct libnet_CreateUser r;
     214
     215        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", discard_const_p(char *, kwnames),
     216                                                                         &r.in.user_name))
     217                return NULL;
     218
     219        r.in.domain_name = cli_credentials_get_domain(self->libnet_ctx->cred);
     220
     221        mem_ctx = talloc_new(NULL);
     222        if (mem_ctx == NULL) {
     223                PyErr_NoMemory();
     224                return NULL;
     225        }
     226
     227        status = libnet_CreateUser(self->libnet_ctx, mem_ctx, &r);
     228        if (!NT_STATUS_IS_OK(status)) {
     229                PyErr_SetString(PyExc_RuntimeError, r.out.error_string?r.out.error_string:nt_errstr(status));
     230                talloc_free(mem_ctx);
     231                return NULL;
     232        }
     233
     234        talloc_free(mem_ctx);
     235       
     236        Py_RETURN_NONE;
     237}
     238
     239static const char py_net_create_user_doc[] = "create_user(username)\n"
     240"Create a new user.";
     241
     242static PyObject *py_net_user_delete(py_net_Object *self, PyObject *args, PyObject *kwargs)
     243{
     244        const char *kwnames[] = { "username", NULL };
     245        NTSTATUS status;
     246        TALLOC_CTX *mem_ctx;
     247        struct libnet_DeleteUser r;
     248
     249        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", discard_const_p(char *, kwnames),
     250                                                                         &r.in.user_name))
     251                return NULL;
     252
     253        r.in.domain_name = cli_credentials_get_domain(self->libnet_ctx->cred);
     254
     255        mem_ctx = talloc_new(NULL);
     256        if (mem_ctx == NULL) {
     257                PyErr_NoMemory();
     258                return NULL;
     259        }
     260
     261        status = libnet_DeleteUser(self->libnet_ctx, mem_ctx, &r);
     262        if (!NT_STATUS_IS_OK(status)) {
     263                PyErr_SetString(PyExc_RuntimeError, r.out.error_string?r.out.error_string:nt_errstr(status));
     264                talloc_free(mem_ctx);
     265                return NULL;
     266        }
     267
     268        talloc_free(mem_ctx);
     269       
     270        Py_RETURN_NONE;
     271}
     272
     273static const char py_net_delete_user_doc[] = "delete_user(username)\n"
     274"Delete a user.";
     275
     276static PyObject *py_dom_sid_FromSid(struct dom_sid *sid)
     277{
     278        PyObject *mod_security, *dom_sid_Type;
     279
     280        mod_security = PyImport_ImportModule("samba.dcerpc.security");
     281        if (mod_security == NULL)
     282                return NULL;
     283
     284        dom_sid_Type = PyObject_GetAttrString(mod_security, "dom_sid");
     285        if (dom_sid_Type == NULL)
     286                return NULL;
     287
     288        return py_talloc_reference((PyTypeObject *)dom_sid_Type, sid);
     289}
     290
     291static PyObject *py_net_vampire(py_net_Object *self, PyObject *args, PyObject *kwargs)
     292{
     293        const char *kwnames[] = { "domain", "target_dir", NULL };
     294        NTSTATUS status;
     295        TALLOC_CTX *mem_ctx;
     296        PyObject *ret;
     297        struct libnet_Vampire r;
     298
     299        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|z", discard_const_p(char *, kwnames),
     300                                         &r.in.domain_name, &r.in.targetdir)) {
     301                return NULL;
     302        }
     303
     304        r.in.netbios_name  = lpcfg_netbios_name(self->libnet_ctx->lp_ctx);
     305        r.out.error_string = NULL;
     306
     307        mem_ctx = talloc_new(NULL);
     308        if (mem_ctx == NULL) {
     309                PyErr_NoMemory();
     310                return NULL;
     311        }
     312
     313        status = libnet_Vampire(self->libnet_ctx, mem_ctx, &r);
     314
     315        if (!NT_STATUS_IS_OK(status)) {
     316                PyErr_SetString(PyExc_RuntimeError,
     317                                r.out.error_string ? r.out.error_string : nt_errstr(status));
     318                talloc_free(mem_ctx);
     319                return NULL;
     320        }
     321
     322        ret = Py_BuildValue("(sO)", r.out.domain_name, py_dom_sid_FromSid(r.out.domain_sid));
     323
     324        talloc_free(mem_ctx);
     325
     326        return ret;
     327}
     328
     329struct replicate_state {
     330        void *vampire_state;
     331        dcerpc_InterfaceObject *drs_pipe;
     332        struct libnet_BecomeDC_StoreChunk chunk;
     333        DATA_BLOB gensec_skey;
     334        struct libnet_BecomeDC_Partition partition;
     335        struct libnet_BecomeDC_Forest forest;
     336        struct libnet_BecomeDC_DestDSA dest_dsa;
     337};
     338
     339/*
     340  setup for replicate_chunk() calls
     341 */
     342static PyObject *py_net_replicate_init(py_net_Object *self, PyObject *args, PyObject *kwargs)
     343{
     344        const char *kwnames[] = { "samdb", "lp", "drspipe", NULL };
     345        PyObject *py_ldb, *py_lp, *py_drspipe;
     346        struct ldb_context *samdb;
     347        struct loadparm_context *lp;
     348        struct replicate_state *s;
     349        NTSTATUS status;
     350
     351        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO",
     352                                         discard_const_p(char *, kwnames),
     353                                         &py_ldb, &py_lp, &py_drspipe)) {
     354                return NULL;
     355        }
     356
     357        s = talloc_zero(NULL, struct replicate_state);
     358        if (!s) return NULL;
     359
     360        lp = lpcfg_from_py_object(s, py_lp);
     361        if (lp == NULL) {
     362                PyErr_SetString(PyExc_TypeError, "Expected lp object");
     363                talloc_free(s);
     364                return NULL;
     365        }
     366
     367        samdb = PyLdb_AsLdbContext(py_ldb);
     368        if (samdb == NULL) {
     369                PyErr_SetString(PyExc_TypeError, "Expected ldb object");
     370                talloc_free(s);
     371                return NULL;
     372        }
     373
     374        s->drs_pipe = (dcerpc_InterfaceObject *)(py_drspipe);
     375
     376        s->vampire_state = libnet_vampire_replicate_init(s, samdb, lp);
     377        if (s->vampire_state == NULL) {
     378                PyErr_SetString(PyExc_TypeError, "Failed to initialise vampire_state");
     379                talloc_free(s);
     380                return NULL;
     381        }
     382
     383        status = gensec_session_key(s->drs_pipe->pipe->conn->security_state.generic_state,
     384                                    &s->gensec_skey);
     385        if (!NT_STATUS_IS_OK(status)) {
     386                PyErr_Format(PyExc_RuntimeError, "Unable to get session key from drspipe: %s",
     387                             nt_errstr(status));
     388                talloc_free(s);
     389                return NULL;
     390        }
     391
     392        s->forest.dns_name = lpcfg_dnsdomain(lp);
     393
     394        s->chunk.gensec_skey = &s->gensec_skey;
     395        s->chunk.partition = &s->partition;
     396        s->chunk.forest = &s->forest;
     397        s->chunk.dest_dsa = &s->dest_dsa;
     398
     399        return PyCObject_FromTallocPtr(s);
     400}
     401
     402
     403/*
     404  process one replication chunk
     405 */
     406static PyObject *py_net_replicate_chunk(py_net_Object *self, PyObject *args, PyObject *kwargs)
     407{
     408        const char *kwnames[] = { "state", "level", "ctr", "schema", NULL };
     409        PyObject *py_state, *py_ctr, *py_schema;
     410        struct replicate_state *s;
     411        unsigned level;
     412        NTSTATUS (*chunk_handler)(void *private_data, const struct libnet_BecomeDC_StoreChunk *c);
     413        NTSTATUS status;
     414
     415        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OIO|O",
     416                                         discard_const_p(char *, kwnames),
     417                                         &py_state, &level, &py_ctr, &py_schema)) {
     418                return NULL;
     419        }
     420
     421        s = talloc_get_type(PyCObject_AsVoidPtr(py_state), struct replicate_state);
     422        if (!s) {
     423                PyErr_SetString(PyExc_TypeError, "Expected replication_state");
     424                return NULL;
     425        }
     426
     427        switch (level) {
     428        case 1:
     429                if (!py_check_dcerpc_type(py_ctr, "samba.dcerpc.drsuapi", "DsGetNCChangesCtr1")) {
     430                        return NULL;
     431                }
     432                s->chunk.ctr1                         = py_talloc_get_ptr(py_ctr);
     433                s->partition.nc                       = *s->chunk.ctr1->naming_context;
     434                s->partition.more_data                = s->chunk.ctr1->more_data;
     435                s->partition.source_dsa_guid          = s->chunk.ctr1->source_dsa_guid;
     436                s->partition.source_dsa_invocation_id = s->chunk.ctr1->source_dsa_invocation_id;
     437                s->partition.highwatermark            = s->chunk.ctr1->new_highwatermark;
     438                break;
     439        case 6:
     440                if (!py_check_dcerpc_type(py_ctr, "samba.dcerpc.drsuapi", "DsGetNCChangesCtr6")) {
     441                        return NULL;
     442                }
     443                s->chunk.ctr6                         = py_talloc_get_ptr(py_ctr);
     444                s->partition.nc                       = *s->chunk.ctr6->naming_context;
     445                s->partition.more_data                = s->chunk.ctr6->more_data;
     446                s->partition.source_dsa_guid          = s->chunk.ctr6->source_dsa_guid;
     447                s->partition.source_dsa_invocation_id = s->chunk.ctr6->source_dsa_invocation_id;
     448                s->partition.highwatermark            = s->chunk.ctr6->new_highwatermark;
     449                break;
     450        default:
     451                PyErr_Format(PyExc_TypeError, "Bad level %u in replicate_chunk", level);
     452                return NULL;
     453        }
     454
     455        chunk_handler = libnet_vampire_cb_store_chunk;
     456        if (py_schema) {
     457                if (!PyBool_Check(py_schema)) {
     458                        PyErr_SetString(PyExc_TypeError, "Expected boolean schema");
     459                        return NULL;
     460                }
     461                if (py_schema == Py_True) {
     462                        chunk_handler = libnet_vampire_cb_schema_chunk;
     463                }
     464        }
     465
     466        s->chunk.ctr_level = level;
     467
     468        status = chunk_handler(s->vampire_state, &s->chunk);
     469        if (!NT_STATUS_IS_OK(status)) {
     470                PyErr_Format(PyExc_TypeError, "Failed to process chunk: %s", nt_errstr(status));
     471                return NULL;
     472        }
     473
     474        Py_RETURN_NONE;
     475}
     476
     477
     478/*
     479  find a DC given a domain name and server type
     480 */
     481static PyObject *py_net_finddc(py_net_Object *self, PyObject *args)
     482{
     483        const char *domain_name;
     484        unsigned server_type;
     485        NTSTATUS status;
     486        struct finddcs *io;
     487        TALLOC_CTX *mem_ctx;
     488        PyObject *ret;
     489
     490        if (!PyArg_ParseTuple(args, "sI", &domain_name, &server_type)) {
     491                return NULL;
     492        }
     493
     494        mem_ctx = talloc_new(self->mem_ctx);
     495
     496        io = talloc_zero(mem_ctx, struct finddcs);
     497        io->in.domain_name = domain_name;
     498        io->in.minimum_dc_flags = server_type;
     499
     500        status = finddcs_cldap(io, io,
     501                               lpcfg_resolve_context(self->libnet_ctx->lp_ctx), self->ev);
     502        if (NT_STATUS_IS_ERR(status)) {
     503                PyErr_SetString(PyExc_RuntimeError, nt_errstr(status));
     504                talloc_free(mem_ctx);
     505                return NULL;
     506        }
     507
     508        ret = py_return_ndr_struct("samba.dcerpc.nbt", "NETLOGON_SAM_LOGON_RESPONSE_EX",
     509                                   io, &io->out.netlogon.data.nt5_ex);
     510        talloc_free(mem_ctx);
     511
     512        return ret;
     513}
     514
     515
     516static const char py_net_vampire_doc[] = "vampire(domain, target_dir=None)\n"
     517                                         "Vampire a domain.";
     518
     519static const char py_net_replicate_init_doc[] = "replicate_init(samdb, lp, drspipe)\n"
     520                                         "Setup for replicate_chunk calls.";
     521
     522static const char py_net_replicate_chunk_doc[] = "replicate_chunk(state, level, ctr, schema)\n"
     523                                         "Process replication for one chunk";
     524
     525static const char py_net_finddc_doc[] = "finddc(domain, server_type)\n"
     526                                         "find a DC with the specified server_type bits. Return the DNS name";
     527
     528static PyMethodDef net_obj_methods[] = {
     529        {"join", (PyCFunction)py_net_join, METH_VARARGS|METH_KEYWORDS, py_net_join_doc},
     530        {"set_password", (PyCFunction)py_net_set_password, METH_VARARGS|METH_KEYWORDS, py_net_set_password_doc},
     531        {"export_keytab", (PyCFunction)py_net_export_keytab, METH_VARARGS|METH_KEYWORDS, py_net_export_keytab_doc},
     532        {"time", (PyCFunction)py_net_time, METH_VARARGS|METH_KEYWORDS, py_net_time_doc},
     533        {"create_user", (PyCFunction)py_net_user_create, METH_VARARGS|METH_KEYWORDS, py_net_create_user_doc},
     534        {"delete_user", (PyCFunction)py_net_user_delete, METH_VARARGS|METH_KEYWORDS, py_net_delete_user_doc},
     535        {"vampire", (PyCFunction)py_net_vampire, METH_VARARGS|METH_KEYWORDS, py_net_vampire_doc},
     536        {"replicate_init", (PyCFunction)py_net_replicate_init, METH_VARARGS|METH_KEYWORDS, py_net_replicate_init_doc},
     537        {"replicate_chunk", (PyCFunction)py_net_replicate_chunk, METH_VARARGS|METH_KEYWORDS, py_net_replicate_chunk_doc},
     538        {"finddc", (PyCFunction)py_net_finddc, METH_VARARGS, py_net_finddc_doc},
     539        { NULL }
     540};
     541
     542static void py_net_dealloc(py_net_Object *self)
     543{
     544        talloc_free(self->mem_ctx);
     545        PyObject_Del(self);
     546}
     547
     548static PyObject *net_obj_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     549{
     550        PyObject *py_creds, *py_lp = Py_None;
     551        const char *kwnames[] = { "creds", "lp", "server", NULL };
     552        py_net_Object *ret;
     553        struct loadparm_context *lp;
     554        const char *server_address = NULL;
     555
     556        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oz",
     557                                         discard_const_p(char *, kwnames), &py_creds, &py_lp,
     558                                         &server_address))
     559                return NULL;
     560
     561        ret = PyObject_New(py_net_Object, type);
     562        if (ret == NULL) {
     563                return NULL;
     564        }
     565
     566        /* FIXME: we really need to get a context from the caller or we may end
     567         * up with 2 event contexts */
     568        ret->ev = s4_event_context_init(NULL);
     569        ret->mem_ctx = talloc_new(ret->ev);
     570
     571        lp = lpcfg_from_py_object(ret->mem_ctx, py_lp);
     572        if (lp == NULL) {
     573                Py_DECREF(ret);
     574                return NULL;
     575        }
     576
     577        ret->libnet_ctx = libnet_context_init(ret->ev, lp);
     578        if (ret->libnet_ctx == NULL) {
     579                PyErr_SetString(PyExc_RuntimeError, "Unable to initialize net");
     580                Py_DECREF(ret);
     581                return NULL;
     582        }
     583
     584        ret->libnet_ctx->server_address = server_address;
     585
     586        ret->libnet_ctx->cred = cli_credentials_from_py_object(py_creds);
     587        if (ret->libnet_ctx->cred == NULL) {
    67588                PyErr_SetString(PyExc_TypeError, "Expected credentials object");
    68                 return NULL;
    69         }
    70 
    71         libnet_ctx = py_net_ctx(cls, ev, creds);
    72 
    73         status = libnet_Join(libnet_ctx, mem_ctx, &r);
    74         if (NT_STATUS_IS_ERR(status)) {
    75                 PyErr_SetString(PyExc_RuntimeError, r.out.error_string);
    76                 talloc_free(mem_ctx);
    77                 return NULL;
    78         }
    79 
    80         result = Py_BuildValue("sss", r.out.join_password,
    81                                dom_sid_string(mem_ctx, r.out.domain_sid),
    82                                r.out.domain_name);
    83 
    84         talloc_free(mem_ctx);
    85 
    86         if (result == NULL)
    87                 return NULL;
    88 
    89         return result;
    90 }
    91 
    92 static char py_net_join_doc[] = "join(domain_name, netbios_name, join_type, level) -> (join_password, domain_sid, domain_name)\n\n" \
    93 "Join the domain with the specified name.";
    94 
    95 static struct PyMethodDef net_methods[] = {
    96         {"Join", (PyCFunction)py_net_join, METH_VARARGS|METH_KEYWORDS, py_net_join_doc},
    97         {NULL }
     589                Py_DECREF(ret);
     590                return NULL;
     591        }
     592
     593        return (PyObject *)ret;
     594}
     595
     596
     597PyTypeObject py_net_Type = {
     598        PyObject_HEAD_INIT(NULL) 0,
     599        .tp_name = "net.Net",
     600        .tp_basicsize = sizeof(py_net_Object),
     601        .tp_dealloc = (destructor)py_net_dealloc,
     602        .tp_methods = net_obj_methods,
     603        .tp_new = net_obj_new,
    98604};
    99605
    100606void initnet(void)
    101607{
    102         Py_InitModule("net", net_methods);
    103 }
     608        PyObject *m;
     609
     610        if (PyType_Ready(&py_net_Type) < 0)
     611                return;
     612
     613        m = Py_InitModule3("net", NULL, NULL);
     614        if (m == NULL)
     615                return;
     616
     617        Py_INCREF(&py_net_Type);
     618        PyModule_AddObject(m, "Net", (PyObject *)&py_net_Type);
     619        PyModule_AddObject(m, "LIBNET_JOINDOMAIN_AUTOMATIC", PyInt_FromLong(LIBNET_JOINDOMAIN_AUTOMATIC));
     620        PyModule_AddObject(m, "LIBNET_JOINDOMAIN_SPECIFIED", PyInt_FromLong(LIBNET_JOINDOMAIN_SPECIFIED));
     621        PyModule_AddObject(m, "LIBNET_JOIN_AUTOMATIC", PyInt_FromLong(LIBNET_JOIN_AUTOMATIC));
     622        PyModule_AddObject(m, "LIBNET_JOIN_SPECIFIED", PyInt_FromLong(LIBNET_JOIN_SPECIFIED));
     623}
Note: See TracChangeset for help on using the changeset viewer.