This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
authorcvs2svn Import User <samba-bugs@samba.org>
Tue, 18 Feb 2003 05:05:16 +0000 (05:05 +0000)
committercvs2svn Import User <samba-bugs@samba.org>
Tue, 18 Feb 2003 05:05:16 +0000 (05:05 +0000)
source3/libsmb/ntlmssp_parse.c [new file with mode: 0644]
source3/passdb/privileges.c [new file with mode: 0644]
source3/python/py_spoolss_common.c [new file with mode: 0644]
source3/python/py_srvsvc.c [new file with mode: 0644]
source3/python/py_srvsvc.h [new file with mode: 0644]
source3/python/py_srvsvc_conv.c [new file with mode: 0644]
source3/python/py_winbind.h [new file with mode: 0644]

diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c
new file mode 100644 (file)
index 0000000..ac779a3
--- /dev/null
@@ -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 (file)
index 0000000..6880536
--- /dev/null
@@ -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 (file)
index 0000000..f34d2ac
--- /dev/null
@@ -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 (file)
index 0000000..8ec2430
--- /dev/null
@@ -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 (file)
index 0000000..b440c32
--- /dev/null
@@ -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 (file)
index 0000000..de43f07
--- /dev/null
@@ -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 (file)
index 0000000..10927ea
--- /dev/null
@@ -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 */