summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorcvs2svn Import User <samba-bugs@samba.org>2003-02-18 05:05:16 +0000
committercvs2svn Import User <samba-bugs@samba.org>2003-02-18 05:05:16 +0000
commit059c4fd81db2b50cd9748577bd1d84e2acd9c330 (patch)
treeaf1b648f6a15aff07c96314be119be93c7f90dd8 /source3
parent737f82e3b3150c0d1f981d6d949978ea33af119c (diff)
parent8f9a17be892f87ab576f1824a7b6fe37abd59887 (diff)
downloadsamba-059c4fd81db2b50cd9748577bd1d84e2acd9c330.tar.gz
samba-059c4fd81db2b50cd9748577bd1d84e2acd9c330.tar.bz2
samba-059c4fd81db2b50cd9748577bd1d84e2acd9c330.zip
This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to be commit c31455779d7948e866fe1916425c3746134dea01)
Diffstat (limited to 'source3')
-rw-r--r--source3/libsmb/ntlmssp_parse.c303
-rw-r--r--source3/passdb/privileges.c341
-rw-r--r--source3/python/py_spoolss_common.c35
-rw-r--r--source3/python/py_srvsvc.c215
-rw-r--r--source3/python/py_srvsvc.h26
-rw-r--r--source3/python/py_srvsvc_conv.c43
-rw-r--r--source3/python/py_winbind.h30
7 files changed, 993 insertions, 0 deletions
diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c
new file mode 100644
index 0000000000..ac779a3906
--- /dev/null
+++ b/source3/libsmb/ntlmssp_parse.c
@@ -0,0 +1,303 @@
+/*
+ Unix SMB/CIFS implementation.
+ simple kerberos5/SPNEGO routines
+ Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Jim McDonough 2002
+ Copyright (C) Andrew Bartlett 2002-2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/*
+ this is a tiny msrpc packet generator. I am only using this to
+ avoid tying this code to a particular varient of our rpc code. This
+ generator is not general enough for all our rpc needs, its just
+ enough for the spnego/ntlmssp code
+
+ format specifiers are:
+
+ U = unicode string (input is unix string)
+ a = address (input is BOOL unicode, char *unix_string)
+ (1 byte type, 1 byte length, unicode/ASCII string, all inline)
+ A = ASCII string (input is unix string)
+ B = data blob (pointer + length)
+ b = data blob in header (pointer + length)
+ D
+ d = word (4 bytes)
+ C = constant ascii string
+ */
+BOOL msrpc_gen(DATA_BLOB *blob,
+ const char *format, ...)
+{
+ int i, n;
+ va_list ap;
+ char *s;
+ uint8 *b;
+ int head_size=0, data_size=0;
+ int head_ofs, data_ofs;
+ BOOL unicode;
+
+ /* first scan the format to work out the header and body size */
+ va_start(ap, format);
+ for (i=0; format[i]; i++) {
+ switch (format[i]) {
+ case 'U':
+ s = va_arg(ap, char *);
+ head_size += 8;
+ data_size += str_charnum(s) * 2;
+ break;
+ case 'A':
+ s = va_arg(ap, char *);
+ head_size += 8;
+ data_size += str_ascii_charnum(s);
+ break;
+ case 'a':
+ unicode = va_arg(ap, BOOL);
+ n = va_arg(ap, int);
+ s = va_arg(ap, char *);
+ if (unicode) {
+ data_size += (str_charnum(s) * 2) + 4;
+ } else {
+ data_size += (str_ascii_charnum(s)) + 4;
+ }
+ break;
+ case 'B':
+ b = va_arg(ap, uint8 *);
+ head_size += 8;
+ data_size += va_arg(ap, int);
+ break;
+ case 'b':
+ b = va_arg(ap, uint8 *);
+ head_size += va_arg(ap, int);
+ break;
+ case 'd':
+ n = va_arg(ap, int);
+ head_size += 4;
+ break;
+ case 'C':
+ s = va_arg(ap, char *);
+ head_size += str_charnum(s) + 1;
+ break;
+ }
+ }
+ va_end(ap);
+
+ /* allocate the space, then scan the format again to fill in the values */
+ *blob = data_blob(NULL, head_size + data_size);
+
+ head_ofs = 0;
+ data_ofs = head_size;
+
+ va_start(ap, format);
+ for (i=0; format[i]; i++) {
+ switch (format[i]) {
+ case 'U':
+ s = va_arg(ap, char *);
+ n = str_charnum(s);
+ SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
+ SSVAL(blob->data, head_ofs, n*2); head_ofs += 2;
+ SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
+ push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
+ data_ofs += n*2;
+ break;
+ case 'A':
+ s = va_arg(ap, char *);
+ n = str_ascii_charnum(s);
+ SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+ SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+ SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
+ push_string(NULL, blob->data+data_ofs, s, n, STR_ASCII|STR_NOALIGN);
+ data_ofs += n;
+ break;
+ case 'a':
+ unicode = va_arg(ap, BOOL);
+ n = va_arg(ap, int);
+ SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+ s = va_arg(ap, char *);
+ if (unicode) {
+ n = str_charnum(s);
+ SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
+ if (0 < n) {
+ push_string(NULL, blob->data+data_ofs, s, n*2,
+ STR_UNICODE|STR_NOALIGN);
+ }
+ data_ofs += n*2;
+ } else {
+ n = str_ascii_charnum(s);
+ SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+ if (0 < n) {
+ push_string(NULL, blob->data+data_ofs, s, n,
+ STR_ASCII|STR_NOALIGN);
+ }
+ data_ofs += n;
+ }
+ break;
+
+ case 'B':
+ b = va_arg(ap, uint8 *);
+ n = va_arg(ap, int);
+ SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+ SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+ SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
+ memcpy(blob->data+data_ofs, b, n);
+ data_ofs += n;
+ break;
+ case 'd':
+ n = va_arg(ap, int);
+ SIVAL(blob->data, head_ofs, n); head_ofs += 4;
+ break;
+ case 'b':
+ b = va_arg(ap, uint8 *);
+ n = va_arg(ap, int);
+ memcpy(blob->data + head_ofs, b, n);
+ head_ofs += n;
+ break;
+ case 'C':
+ s = va_arg(ap, char *);
+ head_ofs += push_string(NULL, blob->data+head_ofs, s, -1,
+ STR_ASCII|STR_TERMINATE);
+ break;
+ }
+ }
+ va_end(ap);
+
+ return True;
+}
+
+
+/* a helpful macro to avoid running over the end of our blob */
+#define NEED_DATA(amount) \
+if ((head_ofs + amount) > blob->length) { \
+ return False; \
+}
+
+/*
+ this is a tiny msrpc packet parser. This the the partner of msrpc_gen
+
+ format specifiers are:
+
+ U = unicode string (output is unix string)
+ A = ascii string
+ B = data blob
+ b = data blob in header
+ d = word (4 bytes)
+ C = constant ascii string
+ */
+
+BOOL msrpc_parse(const DATA_BLOB *blob,
+ const char *format, ...)
+{
+ int i;
+ va_list ap;
+ char **ps, *s;
+ DATA_BLOB *b;
+ size_t head_ofs = 0;
+ uint16 len1, len2;
+ uint32 ptr;
+ uint32 *v;
+ pstring p;
+
+ va_start(ap, format);
+ for (i=0; format[i]; i++) {
+ switch (format[i]) {
+ case 'U':
+ NEED_DATA(8);
+ len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+
+ /* make sure its in the right format - be strict */
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+ if (len1 & 1) {
+ /* if odd length and unicode */
+ return False;
+ }
+
+ ps = va_arg(ap, char **);
+ if (0 < len1) {
+ pull_string(NULL, p, blob->data + ptr, sizeof(p),
+ len1,
+ STR_UNICODE|STR_NOALIGN);
+ (*ps) = smb_xstrdup(p);
+ } else {
+ (*ps) = smb_xstrdup("");
+ }
+ break;
+ case 'A':
+ NEED_DATA(8);
+ len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+
+ /* make sure its in the right format - be strict */
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+
+ ps = va_arg(ap, char **);
+ if (0 < len1) {
+ pull_string(NULL, p, blob->data + ptr, sizeof(p),
+ len1,
+ STR_ASCII|STR_NOALIGN);
+ (*ps) = smb_xstrdup(p);
+ } else {
+ (*ps) = smb_xstrdup("");
+ }
+ break;
+ case 'B':
+ NEED_DATA(8);
+ len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+ /* make sure its in the right format - be strict */
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+ b = (DATA_BLOB *)va_arg(ap, void *);
+ *b = data_blob(blob->data + ptr, len1);
+ break;
+ case 'b':
+ b = (DATA_BLOB *)va_arg(ap, void *);
+ len1 = va_arg(ap, unsigned);
+ /* make sure its in the right format - be strict */
+ NEED_DATA(len1);
+ *b = data_blob(blob->data + head_ofs, len1);
+ head_ofs += len1;
+ break;
+ case 'd':
+ v = va_arg(ap, uint32 *);
+ NEED_DATA(4);
+ *v = IVAL(blob->data, head_ofs); head_ofs += 4;
+ break;
+ case 'C':
+ s = va_arg(ap, char *);
+ head_ofs += pull_string(NULL, p, blob->data+head_ofs, sizeof(p),
+ blob->length - head_ofs,
+ STR_ASCII|STR_TERMINATE);
+ if (strcmp(s, p) != 0) {
+ return False;
+ }
+ break;
+ }
+ }
+ va_end(ap);
+
+ return True;
+}
+
diff --git a/source3/passdb/privileges.c b/source3/passdb/privileges.c
new file mode 100644
index 0000000000..688053674b
--- /dev/null
+++ b/source3/passdb/privileges.c
@@ -0,0 +1,341 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * default privileges backend for passdb
+ *
+ * Copyright (C) Andrew Tridgell 2003
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+/*
+ this is a local implementation of a privileges backend, with
+ privileges stored in a tdb. Most passdb implementations will
+ probably use this backend, although some (such as pdb_ldap) will
+ store the privileges in another manner.
+
+ The basic principle is that the backend should store a list of SIDs
+ associated with each right, where a right is a string name such as
+ 'SeTakeOwnershipPrivilege'. The SIDs can be of any type, and do not
+ need to belong to the local domain.
+
+ The way this is used is that certain places in the code which
+ require access control will ask the privileges backend 'does this
+ user have the following privilege'. The 'user' will be a NT_TOKEN,
+ which is essentially just a list of SIDs. If any of those SIDs are
+ listed in the list of SIDs for that privilege then the answer will
+ be 'yes'. That will usually mean that the user gets unconditional
+ access to that functionality, regradless of any ACLs. In this way
+ privileges act in a similar fashion to unix setuid bits.
+*/
+
+/*
+ The terms 'right' and 'privilege' are used interchangably in this
+ file. This follows MSDN convention where the LSA calls are calls on
+ 'rights', which really means privileges. My apologies for the
+ confusion.
+*/
+
+
+/* 15 seconds seems like an ample time for timeouts on the privileges db */
+#define LOCK_TIMEOUT 15
+
+
+/* the tdb handle for the privileges database */
+static TDB_CONTEXT *tdb;
+
+
+/* initialise the privilege database */
+BOOL privilege_init(void)
+{
+ tdb = tdb_open_log(lock_path("privilege.tdb"), 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0600);
+ if (!tdb) {
+ DEBUG(0,("Failed to open privilege database\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/*
+ lock the record for a particular privilege (write lock)
+*/
+static NTSTATUS privilege_lock_right(const char *right)
+{
+ if (tdb_lock_bystring(tdb, right, LOCK_TIMEOUT) != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ unlock the record for a particular privilege (write lock)
+*/
+static void privilege_unlock_right(const char *right)
+{
+ tdb_unlock_bystring(tdb, right);
+}
+
+
+/*
+ return a list of SIDs that have a particular right
+*/
+NTSTATUS privilege_enum_account_with_right(const char *right,
+ uint32 *count,
+ DOM_SID **sids)
+{
+ TDB_DATA data;
+ char *p;
+ int i;
+
+ if (!tdb) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ data = tdb_fetch_by_string(tdb, right);
+ if (!data.dptr) {
+ *count = 0;
+ *sids = NULL;
+ return NT_STATUS_OK;
+ }
+
+ /* count them */
+ for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) {
+ p += strlen(p) + 1;
+ }
+ *count = i;
+
+ /* allocate and parse */
+ *sids = malloc(sizeof(DOM_SID) * *count);
+ if (! *sids) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) {
+ if (!string_to_sid(&(*sids)[i], p)) {
+ free(data.dptr);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ p += strlen(p) + 1;
+ }
+
+ free(data.dptr);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ set what accounts have a given right - this is an internal interface
+*/
+static NTSTATUS privilege_set_accounts_with_right(const char *right,
+ uint32 count,
+ DOM_SID *sids)
+{
+ TDB_DATA data;
+ char *p;
+ int i;
+
+ if (!tdb) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ /* allocate the maximum size that we might use */
+ data.dptr = malloc(count * ((MAXSUBAUTHS*11) + 30));
+ if (!data.dptr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ p = data.dptr;
+
+ for (i=0;i<count;i++) {
+ sid_to_string(p, &sids[i]);
+ p += strlen(p) + 1;
+ }
+
+ data.dsize = PTR_DIFF(p, data.dptr);
+
+ if (tdb_store_by_string(tdb, right, data, TDB_REPLACE) != 0) {
+ free(data.dptr);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ free(data.dptr);
+ return NT_STATUS_OK;
+}
+
+
+/*
+ add a SID to the list of SIDs for a right
+*/
+NTSTATUS privilege_add_account_right(const char *right,
+ DOM_SID *sid)
+{
+ NTSTATUS status;
+ DOM_SID *current_sids;
+ uint32 current_count;
+ int i;
+
+ status = privilege_lock_right(right);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = privilege_enum_account_with_right(right, &current_count, &current_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ privilege_unlock_right(right);
+ return status;
+ }
+
+ /* maybe that SID is already listed? this is not an error */
+ for (i=0;i<current_count;i++) {
+ if (sid_equal(&current_sids[i], sid)) {
+ privilege_unlock_right(right);
+ free(current_sids);
+ return NT_STATUS_OK;
+ }
+ }
+
+ /* add it in */
+ current_sids = Realloc(current_sids, sizeof(current_sids[0]) * (current_count+1));
+ if (!current_sids) {
+ privilege_unlock_right(right);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ sid_copy(&current_sids[current_count], sid);
+ current_count++;
+
+ status = privilege_set_accounts_with_right(right, current_count, current_sids);
+
+ free(current_sids);
+ privilege_unlock_right(right);
+
+ return status;
+}
+
+
+/*
+ remove a SID from the list of SIDs for a right
+*/
+NTSTATUS privilege_remove_account_right(const char *right,
+ DOM_SID *sid)
+{
+ NTSTATUS status;
+ DOM_SID *current_sids;
+ uint32 current_count;
+ int i;
+
+ status = privilege_lock_right(right);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = privilege_enum_account_with_right(right, &current_count, &current_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ privilege_unlock_right(right);
+ return status;
+ }
+
+ for (i=0;i<current_count;i++) {
+ if (sid_equal(&current_sids[i], sid)) {
+ /* found it - so remove it */
+ if (current_count-i > 1) {
+ memmove(&current_sids[i], &current_sids[i+1],
+ sizeof(current_sids[0]) * ((current_count-i)-1));
+ }
+ current_count--;
+ status = privilege_set_accounts_with_right(right,
+ current_count,
+ current_sids);
+ free(current_sids);
+ privilege_unlock_right(right);
+ return status;
+ }
+ }
+
+ /* removing a right that you don't have is not an error */
+
+ safe_free(current_sids);
+ privilege_unlock_right(right);
+ return NT_STATUS_OK;
+}
+
+
+/*
+ an internal function for checking if a SID has a right
+*/
+static BOOL privilege_sid_has_right(DOM_SID *sid, const char *right)
+{
+ NTSTATUS status;
+ uint32 count;
+ DOM_SID *sids;
+ int i;
+
+ status = privilege_enum_account_with_right(right, &count, &sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+ for (i=0;i<count;i++) {
+ if (sid_equal(sid, &sids[i])) {
+ free(sids);
+ return True;
+ }
+ }
+
+ safe_free(sids);
+ return False;
+}
+
+/*
+ list the rights for an account. This involves traversing the database
+*/
+NTSTATUS privilege_enum_account_rights(DOM_SID *sid,
+ uint32 *count,
+ char ***rights)
+{
+ TDB_DATA key, nextkey;
+ char *right;
+
+ if (!tdb) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ *rights = NULL;
+ *count = 0;
+
+ for (key = tdb_firstkey(tdb); key.dptr; key = nextkey) {
+ nextkey = tdb_nextkey(tdb, key);
+
+ right = key.dptr;
+
+ if (privilege_sid_has_right(sid, right)) {
+ (*rights) = (char **)Realloc(*rights,sizeof(char *) * ((*count)+1));
+ if (! *rights) {
+ safe_free(nextkey.dptr);
+ free(key.dptr);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*rights)[*count] = strdup(right);
+ (*count)++;
+ }
+
+ free(key.dptr);
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source3/python/py_spoolss_common.c b/source3/python/py_spoolss_common.c
new file mode 100644
index 0000000000..f34d2ac6c7
--- /dev/null
+++ b/source3/python/py_spoolss_common.c
@@ -0,0 +1,35 @@
+/*
+ Python wrappers for DCERPC/SMB client routines.
+
+ Copyright (C) Tim Potter, 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "python/py_spoolss.h"
+
+PyObject *new_spoolss_policy_hnd_object(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, POLICY_HND *pol)
+{
+ spoolss_policy_hnd_object *o;
+
+ o = PyObject_New(spoolss_policy_hnd_object, &spoolss_policy_hnd_type);
+
+ o->cli = cli;
+ o->mem_ctx = mem_ctx;
+ memcpy(&o->pol, pol, sizeof(POLICY_HND));
+
+ return (PyObject*)o;
+}
diff --git a/source3/python/py_srvsvc.c b/source3/python/py_srvsvc.c
new file mode 100644
index 0000000000..8ec2430285
--- /dev/null
+++ b/source3/python/py_srvsvc.c
@@ -0,0 +1,215 @@
+/*
+ Python wrappers for DCERPC/SMB client routines.
+
+ Copyright (C) Tim Potter, 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "python/py_srvsvc.h"
+
+/* Exceptions this module can raise */
+
+PyObject *srvsvc_error, *srvsvc_werror;
+
+static struct const_vals {
+ char *name;
+ uint32 value;
+} module_const_vals[] = {
+ { "SV_TYPE_WORKSTATION", SV_TYPE_WORKSTATION },
+ { "SV_TYPE_SERVER", SV_TYPE_SERVER },
+ { "SV_TYPE_SQLSERVER", SV_TYPE_SQLSERVER },
+ { "SV_TYPE_DOMAIN_CTRL", SV_TYPE_DOMAIN_CTRL },
+ { "SV_TYPE_DOMAIN_BAKCTRL", SV_TYPE_DOMAIN_BAKCTRL },
+ { "SV_TYPE_TIME_SOURCE", SV_TYPE_TIME_SOURCE },
+ { "SV_TYPE_AFP", SV_TYPE_AFP },
+ { "SV_TYPE_NOVELL", SV_TYPE_NOVELL },
+ { "SV_TYPE_DOMAIN_MEMBER", SV_TYPE_DOMAIN_MEMBER },
+ { "SV_TYPE_PRINTQ_SERVER", SV_TYPE_PRINTQ_SERVER },
+ { "SV_TYPE_DIALIN_SERVER", SV_TYPE_DIALIN_SERVER },
+ { "SV_TYPE_SERVER_UNIX", SV_TYPE_SERVER_UNIX },
+ { "SV_TYPE_NT", SV_TYPE_NT },
+ { "SV_TYPE_WFW", SV_TYPE_WFW },
+ { "SV_TYPE_SERVER_MFPN", SV_TYPE_SERVER_MFPN },
+ { "SV_TYPE_SERVER_NT", SV_TYPE_SERVER_NT },
+ { "SV_TYPE_POTENTIAL_BROWSER", SV_TYPE_POTENTIAL_BROWSER },
+ { "SV_TYPE_BACKUP_BROWSER", SV_TYPE_BACKUP_BROWSER },
+ { "SV_TYPE_MASTER_BROWSER", SV_TYPE_MASTER_BROWSER },
+ { "SV_TYPE_DOMAIN_MASTER", SV_TYPE_DOMAIN_MASTER },
+ { "SV_TYPE_SERVER_OSF", SV_TYPE_SERVER_OSF },
+ { "SV_TYPE_SERVER_VMS", SV_TYPE_SERVER_VMS },
+ { "SV_TYPE_WIN95_PLUS", SV_TYPE_WIN95_PLUS },
+ { "SV_TYPE_DFS_SERVER", SV_TYPE_DFS_SERVER },
+ { "SV_TYPE_ALTERNATE_XPORT", SV_TYPE_ALTERNATE_XPORT },
+ { "SV_TYPE_LOCAL_LIST_ONLY", SV_TYPE_LOCAL_LIST_ONLY },
+ { "SV_TYPE_DOMAIN_ENUM", SV_TYPE_DOMAIN_ENUM },
+ { NULL },
+};
+
+static void const_init(PyObject *dict)
+{
+ struct const_vals *tmp;
+ PyObject *obj;
+
+ for (tmp = module_const_vals; tmp->name; tmp++) {
+ obj = PyInt_FromLong(tmp->value);
+ PyDict_SetItemString(dict, tmp->name, obj);
+ Py_DECREF(obj);
+ }
+}
+
+/* NetServerGetInfo */
+
+PyObject *srvsvc_netservergetinfo(PyObject *self, PyObject *args,
+ PyObject *kw)
+{
+ static char *kwlist[] = { "server", "level", "creds", NULL };
+ char *unc_name, *server, *errstr;
+ PyObject *creds = NULL, *result = NULL;
+ struct cli_state *cli;
+ TALLOC_CTX *mem_ctx = NULL;
+ uint32 level;
+ SRV_INFO_CTR ctr;
+ WERROR status;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "si|O", kwlist, &unc_name, &level, &creds))
+ return NULL;
+
+ if (unc_name[0] != '\\' || unc_name[1] != '\\') {
+ PyErr_SetString(PyExc_ValueError, "UNC name required");
+ return NULL;
+ }
+
+ server = strdup(unc_name + 2);
+
+ if (strchr(server, '\\')) {
+ char *c = strchr(server, '\\');
+ *c = 0;
+ }
+
+ if (creds && creds != Py_None && !PyDict_Check(creds)) {
+ PyErr_SetString(PyExc_TypeError,
+ "credentials must be dictionary or None");
+ return NULL;
+ }
+
+ if (!(cli = open_pipe_creds(server, creds, PI_SRVSVC, &errstr))) {
+ PyErr_SetString(srvsvc_error, errstr);
+ free(errstr);
+ goto done;
+ }
+
+ if (!(mem_ctx = talloc_init("srvsvc_netservergetinfo"))) {
+ PyErr_SetString(srvsvc_error,
+ "unable to init talloc context\n");
+ goto done;
+ }
+
+ ZERO_STRUCT(ctr);
+
+ status = cli_srvsvc_net_srv_get_info(cli, mem_ctx, level, &ctr);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetObject(srvsvc_error, py_werror_tuple(status));
+ goto done;
+ }
+
+ if (level != ctr.switch_value) {
+ PyErr_SetString(srvsvc_error, "container level value wrong");
+ goto done;
+ }
+
+ switch(level) {
+ case 101:
+ py_from_SRV_INFO_101(&result, &ctr.srv.sv101);
+ break;
+ }
+
+ Py_INCREF(result);
+
+done:
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+
+ return result;
+}
+
+/*
+ * Module initialisation
+ */
+
+static PyMethodDef srvsvc_methods[] = {
+ { "netservergetinfo", (PyCFunction)srvsvc_netservergetinfo,
+ METH_VARARGS | METH_KEYWORDS,
+ "Retrieve information about a particular server." },
+
+ { "setup_logging", (PyCFunction)py_setup_logging,
+ METH_VARARGS | METH_KEYWORDS,
+ "Set up debug logging.
+
+Initialises Samba's debug logging system. One argument is expected which
+is a boolean specifying whether debugging is interactive and sent to stdout
+or logged to a file.
+
+Example:
+
+>>> srvsvc.setup_logging(interactive = 1)" },
+
+ { "get_debuglevel", (PyCFunction)get_debuglevel,
+ METH_VARARGS,
+ "Set the current debug level.
+
+Example:
+
+>>> srvsvc.get_debuglevel()
+0" },
+
+ { "set_debuglevel", (PyCFunction)set_debuglevel,
+ METH_VARARGS,
+ "Get the current debug level.
+
+Example:
+
+>>> srvsvc.set_debuglevel(10)" },
+
+ { NULL }
+};
+
+void initsrvsvc(void)
+{
+ PyObject *module, *dict;
+
+ /* Initialise module */
+
+ module = Py_InitModule("srvsvc", srvsvc_methods);
+ dict = PyModule_GetDict(module);
+
+ /* Exceptions we can raise */
+
+ srvsvc_error = PyErr_NewException("srvsvc.error", NULL, NULL);
+ PyDict_SetItemString(dict, "error", srvsvc_error);
+
+ srvsvc_werror = PyErr_NewException("srvsvc.werror", NULL, NULL);
+ PyDict_SetItemString(dict, "werror", srvsvc_werror);
+
+ /* Initialise constants */
+
+ const_init(dict);
+
+ /* Do samba initialisation */
+
+ py_samba_init();
+}
diff --git a/source3/python/py_srvsvc.h b/source3/python/py_srvsvc.h
new file mode 100644
index 0000000000..b440c32e13
--- /dev/null
+++ b/source3/python/py_srvsvc.h
@@ -0,0 +1,26 @@
+/*
+ Python wrappers for DCERPC/SMB client routines.
+
+ Copyright (C) Tim Potter, 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _PY_SRVSVC_H
+#define _PY_SRVSVC_H
+
+#include "python/py_common.h"
+
+#endif /* _PY_SRVSVC_H */
diff --git a/source3/python/py_srvsvc_conv.c b/source3/python/py_srvsvc_conv.c
new file mode 100644
index 0000000000..de43f070ed
--- /dev/null
+++ b/source3/python/py_srvsvc_conv.c
@@ -0,0 +1,43 @@
+/*
+ Python wrappers for DCERPC/SMB client routines.
+
+ Copyright (C) Tim Potter, 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "python/py_srvsvc.h"
+#include "python/py_conv.h"
+
+static struct pyconv py_SRV_INFO_101[] = {
+ { "platform_id", PY_UINT32, offsetof(SRV_INFO_101, platform_id) },
+ { "major_version", PY_UINT32, offsetof(SRV_INFO_101, ver_major) },
+ { "minor_version", PY_UINT32, offsetof(SRV_INFO_101, ver_minor) },
+ { "server_type", PY_UINT32, offsetof(SRV_INFO_101, srv_type) },
+ { "name", PY_UNISTR2, offsetof(SRV_INFO_101, uni_name) },
+ { "comment", PY_UNISTR2, offsetof(SRV_INFO_101, uni_comment) },
+ { NULL }
+};
+
+BOOL py_from_SRV_INFO_101(PyObject **dict, SRV_INFO_101 *info)
+{
+ PyObject *obj;
+
+ *dict = from_struct(info, py_SRV_INFO_101);
+
+ PyDict_SetItemString(*dict, "level", PyInt_FromLong(101));
+
+ return True;
+}
diff --git a/source3/python/py_winbind.h b/source3/python/py_winbind.h
new file mode 100644
index 0000000000..10927ea6c8
--- /dev/null
+++ b/source3/python/py_winbind.h
@@ -0,0 +1,30 @@
+/*
+ Python wrappers for DCERPC/SMB client routines.
+
+ Copyright (C) Tim Potter, 2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _PY_WINBIND_H
+#define _PY_WINBIND_H
+
+#include "python/py_common.h"
+
+/* The following definitions are from py_winbind_conv.c */
+
+BOOL py_from_winbind_passwd(PyObject **dict, struct winbindd_response *response);
+
+#endif /* _PY_WINBIND_H */