summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorcvs2svn Import User <samba-bugs@samba.org>2003-04-13 13:50:46 +0000
committercvs2svn Import User <samba-bugs@samba.org>2003-04-13 13:50:46 +0000
commit381649916ecbaddefbb6ee0e6137b7cc73eb54b1 (patch)
tree445e00d6b22193f3d2e6a2e826eaf305c74b6f44 /source
parent675333350a645cfe209127bfd040b81c2fc42f58 (diff)
parent8b75c925b9a237e967a92f17a9b85562c1da8733 (diff)
downloadsamba-381649916ecbaddefbb6ee0e6137b7cc73eb54b1.tar.gz
samba-381649916ecbaddefbb6ee0e6137b7cc73eb54b1.tar.xz
samba-381649916ecbaddefbb6ee0e6137b7cc73eb54b1.zip
This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
Diffstat (limited to 'source')
-rw-r--r--source/groupdb/.cvsignore2
-rw-r--r--source/include/authdata.h152
-rw-r--r--source/include/fake_file.h46
-rw-r--r--source/include/ntquotas.h97
-rw-r--r--source/include/rpc_echo.h74
-rw-r--r--source/libads/authdata.c614
-rw-r--r--source/libsmb/clifsinfo.c76
-rw-r--r--source/rpc_client/cli_echo.c187
-rw-r--r--source/rpc_parse/parse_echo.c166
-rw-r--r--source/rpc_server/srv_echo.c137
-rw-r--r--source/rpc_server/srv_echo_nt.c78
-rw-r--r--source/rpcclient/cmd_echo.c157
-rwxr-xr-xsource/stf/smbcontrol.py238
-rw-r--r--source/stf/unicodenames.py33
-rw-r--r--source/torture/t_push_ucs2.c54
-rw-r--r--source/torture/t_strcmp.c32
-rw-r--r--source/utils/smbcquotas.c545
17 files changed, 2688 insertions, 0 deletions
diff --git a/source/groupdb/.cvsignore b/source/groupdb/.cvsignore
new file mode 100644
index 00000000000..22beab949c5
--- /dev/null
+++ b/source/groupdb/.cvsignore
@@ -0,0 +1,2 @@
+.po
+.po32
diff --git a/source/include/authdata.h b/source/include/authdata.h
new file mode 100644
index 00000000000..0798b72bdf9
--- /dev/null
+++ b/source/include/authdata.h
@@ -0,0 +1,152 @@
+/*
+ Unix SMB/CIFS implementation.
+ Kerberos authorization data
+ Copyright (C) Jim McDonough 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 _AUTHDATA_H
+#define _AUTHDATA_H
+
+#include "rpc_misc.h"
+
+#define PAC_TYPE_LOGON_INFO 1
+#define PAC_TYPE_SERVER_CHECKSUM 6
+#define PAC_TYPE_PRIVSVR_CHECKSUM 7
+#define PAC_TYPE_UNKNOWN_10 10
+
+typedef struct unknown_type_10 {
+ NTTIME unknown_time;
+ uint16 len;
+ uint16 *username; /* might not be null terminated, so not UNISTR */
+} UNKNOWN_TYPE_10;
+
+typedef struct pac_signature_data {
+ uint32 type;
+ uint8 *signature;
+} PAC_SIGNATURE_DATA;
+
+typedef struct group_membership {
+ uint32 rid;
+ uint32 attrs;
+} GROUP_MEMBERSHIP;
+
+typedef struct group_membership_array {
+ uint32 count;
+ GROUP_MEMBERSHIP *group_membership;
+} GROUP_MEMBERSHIP_ARRAY;
+
+typedef struct krb_sid_and_attrs {
+ uint32 sid_ptr;
+ uint32 attrs;
+ DOM_SID2 *sid;
+} KRB_SID_AND_ATTRS;
+
+typedef struct krb_sid_and_attr_array {
+ uint32 count;
+ KRB_SID_AND_ATTRS *krb_sid_and_attrs;
+} KRB_SID_AND_ATTR_ARRAY;
+
+
+/* This is awfully similar to a samr_user_info_23, but not identical.
+ Many of the field names have been swiped from there, because it is
+ so similar that they are likely the same, but many have been verified.
+ Some are in a different order, though... */
+typedef struct pac_logon_info {
+ NTTIME logon_time; /* logon time */
+ NTTIME logoff_time; /* logoff time */
+ NTTIME kickoff_time; /* kickoff time */
+ NTTIME pass_last_set_time; /* password last set time */
+ NTTIME pass_can_change_time; /* password can change time */
+ NTTIME pass_must_change_time; /* password must change time */
+
+ UNIHDR hdr_user_name; /* user name unicode string header */
+ UNIHDR hdr_full_name; /* user's full name unicode string header */
+ UNIHDR hdr_logon_script; /* these last 4 appear to be in a different */
+ UNIHDR hdr_profile_path; /* order than in the info23 */
+ UNIHDR hdr_home_dir;
+ UNIHDR hdr_dir_drive;
+
+ uint16 logon_count; /* number of times user has logged onto domain */
+ uint16 reserved12;
+
+ uint32 user_rid;
+ uint32 group_rid;
+ uint32 group_count;
+ uint32 group_membership_ptr;
+ uint32 user_flags;
+
+ uint32 reserved13[4];
+ UNIHDR hdr_dom_controller;
+ UNIHDR hdr_dom_name;
+
+ uint32 ptr_dom_sid;
+
+ uint32 reserved16[2];
+ uint32 reserved17; /* looks like it may be acb_info */
+ uint32 reserved18[7];
+
+ uint32 sid_count;
+ uint32 ptr_extra_sids;
+
+ uint32 ptr_res_group_dom_sid;
+ uint32 res_group_count;
+ uint32 ptr_res_groups;
+
+ UNISTR2 uni_user_name; /* user name unicode string header */
+ UNISTR2 uni_full_name; /* user's full name unicode string header */
+ UNISTR2 uni_logon_script; /* these last 4 appear to be in a different*/
+ UNISTR2 uni_profile_path; /* order than in the info23 */
+ UNISTR2 uni_home_dir;
+ UNISTR2 uni_dir_drive;
+ UNISTR2 uni_dom_controller;
+ UNISTR2 uni_dom_name;
+ DOM_SID2 dom_sid;
+ GROUP_MEMBERSHIP_ARRAY groups;
+ KRB_SID_AND_ATTR_ARRAY extra_sids;
+ DOM_SID2 res_group_dom_sid;
+ GROUP_MEMBERSHIP_ARRAY res_groups;
+
+} PAC_LOGON_INFO;
+
+typedef struct pac_info_ctr
+{
+ union
+ {
+ PAC_LOGON_INFO *logon_info;
+ PAC_SIGNATURE_DATA *srv_cksum;
+ PAC_SIGNATURE_DATA *privsrv_cksum;
+ UNKNOWN_TYPE_10 *type_10;
+ } pac;
+} PAC_INFO_CTR;
+
+typedef struct pac_info_hdr {
+ uint32 type;
+ uint32 size;
+ uint32 offset;
+ uint32 offsethi;
+ PAC_INFO_CTR *ctr;
+} PAC_INFO_HDR;
+
+typedef struct pac_data {
+ uint32 num_buffers;
+ uint32 version;
+ PAC_INFO_HDR *pac_info_hdr_ptr;
+} PAC_DATA;
+
+
+#endif
diff --git a/source/include/fake_file.h b/source/include/fake_file.h
new file mode 100644
index 00000000000..3fe60072e9e
--- /dev/null
+++ b/source/include/fake_file.h
@@ -0,0 +1,46 @@
+/*
+ Unix SMB/CIFS implementation.
+ FAKE FILE suppport, for faking up special files windows want access to
+ Copyright (C) Stefan (metze) Metzmacher 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 _FAKE_FILE_H
+#define _FAKE_FILE_H
+
+enum FAKE_FILE_TYPE {
+ FAKE_FILE_TYPE_NONE = 0,
+ FAKE_FILE_TYPE_QUOTA
+};
+
+#define FAKE_FILE_NAME_QUOTA "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"
+
+typedef struct _FAKE_FILE_HANDLE {
+ enum FAKE_FILE_TYPE type;
+ TALLOC_CTX *mem_ctx;
+ void *pd; /* for private data */
+ void (*free_pd)(void **pd); /* free private_data */
+} FAKE_FILE_HANDLE;
+
+typedef struct _FAKE_FILE {
+ const char *name;
+ enum FAKE_FILE_TYPE type;
+ void *(*init_pd)(TALLOC_CTX *men_ctx);
+ void (*free_pd)(void **pd);
+} FAKE_FILE;
+
+
+#endif /* _FAKE_FILE_H */
diff --git a/source/include/ntquotas.h b/source/include/ntquotas.h
new file mode 100644
index 00000000000..1425e59bb84
--- /dev/null
+++ b/source/include/ntquotas.h
@@ -0,0 +1,97 @@
+/*
+ Unix SMB/CIFS implementation.
+ NT QUOTA code constants
+ Copyright (C) Stefan (metze) Metzmacher 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 _NTQUOTAS_H
+#define _NTQUOTAS_H
+
+/*
+ * details for Quota Flags:
+ *
+ * 0x20 Log Limit: log if the user exceeds his Hard Quota
+ * 0x10 Log Warn: log if the user exceeds his Soft Quota
+ * 0x02 Deny Disk: deny disk access when the user exceeds his Hard Quota
+ * 0x01 Enable Quotas: enable quota for this fs
+ *
+ */
+
+#define QUOTAS_ENABLED 0x0001
+#define QUOTAS_DENY_DISK 0x0002
+#define QUOTAS_LOG_VIOLATIONS 0x0004
+#define CONTENT_INDEX_DISABLED 0x0008
+#define QUOTAS_LOG_THRESHOLD 0x0010
+#define QUOTAS_LOG_LIMIT 0x0020
+#define LOG_VOLUME_THRESHOLD 0x0040
+#define LOG_VOLUME_LIMIT 0x0080
+#define QUOTAS_INCOMPLETE 0x0100
+#define QUOTAS_REBUILDING 0x0200
+#define QUOTAS_0400 0x0400
+#define QUOTAS_0800 0x0800
+#define QUOTAS_1000 0x1000
+#define QUOTAS_2000 0x2000
+#define QUOTAS_4000 0x4000
+#define QUOTAS_8000 0x8000
+
+#define SMB_NTQUOTAS_NO_LIMIT ((SMB_BIG_UINT)(-1))
+#define SMB_NTQUOTAS_NO_ENTRY ((SMB_BIG_UINT)(-2))
+#define SMB_NTQUOTAS_NO_SPACE ((SMB_BIG_UINT)(0))
+#define SMB_NTQUOTAS_1_B (SMB_BIG_UINT)0x0000000000000001
+#define SMB_NTQUOTAS_1KB (SMB_BIG_UINT)0x0000000000000400
+#define SMB_NTQUOTAS_1MB (SMB_BIG_UINT)0x0000000000100000
+#define SMB_NTQUOTAS_1GB (SMB_BIG_UINT)0x0000000040000000
+#define SMB_NTQUOTAS_1TB (SMB_BIG_UINT)0x0000010000000000
+#define SMB_NTQUOTAS_1PB (SMB_BIG_UINT)0x0004000000000000
+#define SMB_NTQUOTAS_1EB (SMB_BIG_UINT)0x1000000000000000
+
+enum SMB_QUOTA_TYPE {
+ SMB_INVALID_QUOTA_TYPE = -1,
+ SMB_USER_FS_QUOTA_TYPE = 1,
+ SMB_USER_QUOTA_TYPE = 2,
+ SMB_GROUP_FS_QUOTA_TYPE = 3,/* not used yet */
+ SMB_GROUP_QUOTA_TYPE = 4 /* not in use yet, maybe for disk_free queries */
+};
+
+typedef struct _SMB_NTQUOTA_STRUCT {
+ enum SMB_QUOTA_TYPE qtype;
+ SMB_BIG_UINT usedspace;
+ SMB_BIG_UINT softlim;
+ SMB_BIG_UINT hardlim;
+ enum SMB_QUOTA_TYPE qflags;
+ DOM_SID sid;
+} SMB_NTQUOTA_STRUCT;
+
+typedef struct _SMB_NTQUOTA_LIST {
+ struct _SMB_NTQUOTA_LIST *prev,*next;
+ TALLOC_CTX *mem_ctx;
+ uid_t uid;
+ SMB_NTQUOTA_STRUCT *quotas;
+} SMB_NTQUOTA_LIST;
+
+typedef struct _SMB_NTQUOTA_HANDLE {
+ BOOL valid;
+ SMB_NTQUOTA_LIST *quota_list;
+ SMB_NTQUOTA_LIST *tmp_list;
+} SMB_NTQUOTA_HANDLE;
+
+#define CHECK_NTQUOTA_HANDLE_OK(fsp,conn) (FNUM_OK(fsp,conn) &&\
+ (fsp)->fake_file_handle &&\
+ ((fsp)->fake_file_handle->type == FAKE_FILE_TYPE_QUOTA) &&\
+ (fsp)->fake_file_handle->pd)
+
+#endif /*_NTQUOTAS_H */
diff --git a/source/include/rpc_echo.h b/source/include/rpc_echo.h
new file mode 100644
index 00000000000..8fa389cf569
--- /dev/null
+++ b/source/include/rpc_echo.h
@@ -0,0 +1,74 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Samba rpcecho definitions.
+
+ 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 _RPC_ECHO_H
+#define _RPC_ECHO_H
+
+#define ECHO_ADD_ONE 0x00
+#define ECHO_DATA 0x01
+#define ECHO_SINK_DATA 0x02
+#define ECHO_SOURCE_DATA 0x03
+
+typedef struct echo_q_add_one
+{
+ uint32 request;
+} ECHO_Q_ADD_ONE;
+
+typedef struct echo_r_add_one
+{
+ uint32 response;
+} ECHO_R_ADD_ONE;
+
+typedef struct echo_q_echo_data
+{
+ uint32 size;
+ char *data;
+} ECHO_Q_ECHO_DATA;
+
+typedef struct echo_r_echo_data
+{
+ uint32 size;
+ char *data;
+} ECHO_R_ECHO_DATA;
+
+typedef struct echo_q_source_data
+{
+ uint32 size;
+} ECHO_Q_SOURCE_DATA;
+
+typedef struct echo_r_source_data
+{
+ uint32 size;
+ char *data;
+} ECHO_R_SOURCE_DATA;
+
+typedef struct echo_q_sink_data
+{
+ uint32 size;
+ char *data;
+} ECHO_Q_SINK_DATA;
+
+typedef struct echo_r_sink_data
+{
+} ECHO_R_SINK_DATA;
+
+#endif
diff --git a/source/libads/authdata.c b/source/libads/authdata.c
new file mode 100644
index 00000000000..c554a02e90e
--- /dev/null
+++ b/source/libads/authdata.c
@@ -0,0 +1,614 @@
+/*
+ Unix SMB/CIFS implementation.
+ kerberos authorization data (PAC) utility library
+ Copyright (C) Jim McDonough 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"
+
+#ifdef HAVE_KRB5
+
+static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data)
+{
+ DATA_BLOB pac_contents;
+ ASN1_DATA data;
+ int data_type;
+
+ asn1_load(&data, *auth_data);
+ asn1_start_tag(&data, ASN1_SEQUENCE(0));
+ asn1_start_tag(&data, ASN1_SEQUENCE(0));
+ asn1_start_tag(&data, ASN1_CONTEXT(0));
+ asn1_read_Integer(&data, &data_type);
+ asn1_end_tag(&data);
+ asn1_start_tag(&data, ASN1_CONTEXT(1));
+ asn1_read_OctetString(&data, &pac_contents);
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+ return pac_contents;
+}
+
+static BOOL pac_io_unknown_type_10(const char *desc, UNKNOWN_TYPE_10 *type_10,
+ prs_struct *ps, int depth)
+{
+ if (NULL == type_10)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_unknown_type_10");
+ depth++;
+
+ if (!smb_io_time("unknown_time", &type_10->unknown_time, ps, depth))
+ return False;
+
+ if (!prs_uint16("len", ps, depth, &type_10->len))
+ return False;
+
+ if (UNMARSHALLING(ps) && type_10->len) {
+ type_10->username = (uint16 *) prs_alloc_mem(ps, type_10->len);
+ if (!type_10->username) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+
+ if (!prs_uint16s(True, "name", ps, depth, type_10->username,
+ (type_10->len / sizeof(uint16))))
+ return False;
+
+ return True;
+
+}
+
+
+static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
+ prs_struct *ps, int depth)
+{
+ if (NULL == sid_and_attr)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_krb_sids");
+ depth++;
+
+ if (UNMARSHALLING(ps)) {
+ sid_and_attr->sid =
+ (DOM_SID2 * ) prs_alloc_mem(ps, sizeof(DOM_SID2));
+ if (!sid_and_attr->sid) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+
+ if(!smb_io_dom_sid2("sid", sid_and_attr->sid, ps, depth))
+ return False;
+
+ return True;
+}
+
+
+static BOOL pac_io_krb_attrs(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
+ prs_struct *ps, int depth)
+{
+ if (NULL == sid_and_attr)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_krb_attrs");
+ depth++;
+
+ if (!prs_uint32("sid_ptr", ps, depth, &sid_and_attr->sid_ptr))
+ return False;
+ if (!prs_uint32("attrs", ps, depth, &sid_and_attr->attrs))
+ return False;
+
+ return True;
+}
+
+static BOOL pac_io_krb_sid_and_attr_array(const char *desc,
+ KRB_SID_AND_ATTR_ARRAY *array,
+ uint32 num,
+ prs_struct *ps, int depth)
+{
+ int i;
+
+ if (NULL == array)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_krb_sid_and_attr_array");
+ depth++;
+
+
+ if (!prs_uint32("count", ps, depth, &array->count))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ array->krb_sid_and_attrs = (KRB_SID_AND_ATTRS *)
+ prs_alloc_mem(ps, sizeof(KRB_SID_AND_ATTRS) * num);
+ if (!array->krb_sid_and_attrs) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+
+ for (i=0; i<num; i++) {
+ if (!pac_io_krb_attrs(desc,
+ &array->krb_sid_and_attrs[i],
+ ps, depth))
+ return False;
+
+ }
+ for (i=0; i<num; i++) {
+ if (!pac_io_krb_sids(desc,
+ &array->krb_sid_and_attrs[i],
+ ps, depth))
+ return False;
+
+ }
+
+ return True;
+
+}
+
+static BOOL pac_io_group_membership(const char *desc,
+ GROUP_MEMBERSHIP *membership,
+ prs_struct *ps, int depth)
+{
+ if (NULL == membership)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_group_membership");
+ depth++;
+
+ if (!prs_uint32("rid", ps, depth, &membership->rid))
+ return False;
+ if (!prs_uint32("attrs", ps, depth, &membership->attrs))
+ return False;
+
+ return True;
+}
+
+
+static BOOL pac_io_group_membership_array(const char *desc,
+ GROUP_MEMBERSHIP_ARRAY *array,
+ uint32 num,
+ prs_struct *ps, int depth)
+{
+ int i;
+
+ if (NULL == array)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_group_membership_array");
+ depth++;
+
+
+ if (!prs_uint32("count", ps, depth, &array->count))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ array->group_membership = (GROUP_MEMBERSHIP *)
+ prs_alloc_mem(ps, sizeof(GROUP_MEMBERSHIP) * num);
+ if (!array->group_membership) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+
+ for (i=0; i<num; i++) {
+ if (!pac_io_group_membership(desc,
+ &array->group_membership[i],
+ ps, depth))
+ return False;
+
+ }
+
+ return True;
+
+}
+
+static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info,
+ prs_struct *ps, int depth)
+{
+ uint32 garbage;
+ if (NULL == info)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_pac_logon_info");
+ depth++;
+
+ if (!prs_uint32("unknown", ps, depth, &garbage))
+ return False;
+ if (!prs_uint32("unknown", ps, depth, &garbage))
+ return False;
+ if (!prs_uint32("bufferlen", ps, depth, &garbage))
+ return False;
+ if (!prs_uint32("bufferlenhi", ps, depth, &garbage))
+ return False;
+ if (!prs_uint32("pointer", ps, depth, &garbage))
+ return False;
+
+ if (!smb_io_time("logon_time", &info->logon_time, ps, depth))
+ return False;
+ if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth))
+ return False;
+ if (!smb_io_time("kickoff_time", &info->kickoff_time, ps, depth))
+ return False;
+ if (!smb_io_time("pass_last_set_time", &info->pass_last_set_time,
+ ps, depth))
+ return False;
+ if (!smb_io_time("pass_can_change_time", &info->pass_can_change_time,
+ ps, depth))
+ return False;
+ if (!smb_io_time("pass_must_change_time", &info->pass_must_change_time,
+ ps, depth))
+ return False;
+
+ if (!smb_io_unihdr("hdr_user_name", &info->hdr_user_name, ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_full_name", &info->hdr_full_name, ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_logon_script", &info->hdr_logon_script,
+ ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_profile_path", &info->hdr_profile_path,
+ ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_home_dir", &info->hdr_home_dir, ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_dir_drive", &info->hdr_dir_drive, ps, depth))
+ return False;
+
+ if (!prs_uint16("logon_count", ps, depth, &info->logon_count))
+ return False;
+ if (!prs_uint16("reserved12", ps, depth, &info->reserved12))
+ return False;
+ if (!prs_uint32("user_rid", ps, depth, &info->user_rid))
+ return False;
+ if (!prs_uint32("group_rid", ps, depth, &info->group_rid))
+ return False;
+ if (!prs_uint32("group_count", ps, depth, &info->group_count))
+ return False;
+ /* I haven't seen this contain anything yet, but when it does
+ we will have to make sure we decode the contents in the middle
+ all the unistr2s ... */
+ if (!prs_uint32("group_mem_ptr", ps, depth,
+ &info->group_membership_ptr))
+ return False;
+ if (!prs_uint32("user_flags", ps, depth, &info->user_flags))
+ return False;
+
+ if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0]))
+ return False;
+ if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1]))
+ return False;
+ if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2]))
+ return False;
+ if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3]))
+ return False;
+
+ if (!smb_io_unihdr("hdr_dom_controller",
+ &info->hdr_dom_controller, ps, depth))
+ return False;
+ if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth))
+ return False;
+
+ /* this should be followed, but just get ptr for now */
+ if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid))
+ return False;
+
+ if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0]))
+ return False;
+ if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1]))
+ return False;
+
+ /* might be acb_info */
+ if (!prs_uint32("reserved17", ps, depth, &info->reserved17))
+ return False;
+
+
+ if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0]))
+ return False;
+ if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1]))
+ return False;
+ if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2]))
+ return False;
+ if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3]))
+ return False;
+ if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4]))
+ return False;
+ if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5]))
+ return False;
+ if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6]))
+ return False;
+
+ if (!prs_uint32("sid_count", ps, depth, &info->sid_count))
+ return False;
+ if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids))
+ return False;
+ if (!prs_uint32("ptr_res_group_dom_sid", ps, depth,
+ &info->ptr_res_group_dom_sid))
+ return False;
+ if (!prs_uint32("res_group_count", ps, depth, &info->res_group_count))
+ return False;
+ if (!prs_uint32("ptr_res_groups", ps, depth, &info->ptr_res_groups))
+ return False;
+
+ if(!smb_io_unistr2("uni_user_name", &info->uni_user_name,
+ info->hdr_user_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_full_name", &info->uni_full_name,
+ info->hdr_full_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_logon_script", &info->uni_logon_script,
+ info->hdr_logon_script.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_profile_path", &info->uni_profile_path,
+ info->hdr_profile_path.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_home_dir", &info->uni_home_dir,
+ info->hdr_home_dir.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_dir_drive", &info->uni_dir_drive,
+ info->hdr_dir_drive.buffer, ps, depth))
+ return False;
+
+ if (info->group_membership_ptr) {
+ if (!pac_io_group_membership_array("group membership",
+ &info->groups,
+ info->group_count,
+ ps, depth))
+ return False;
+ }
+
+
+ if(!smb_io_unistr2("uni_dom_controller", &info->uni_dom_controller,
+ info->hdr_dom_controller.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_dom_name", &info->uni_dom_name,
+ info->hdr_dom_name.buffer, ps, depth))
+ return False;
+
+ if(info->ptr_dom_sid)
+ if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
+ return False;
+
+
+ if (info->sid_count && info->ptr_extra_sids)
+ if (!pac_io_krb_sid_and_attr_array("extra_sids",
+ &info->extra_sids,
+ info->sid_count,
+ ps, depth))
+ return False;
+
+ if (info->ptr_res_group_dom_sid)
+ if (!smb_io_dom_sid2("res_group_dom_sid",
+ &info->res_group_dom_sid, ps, depth))
+ return False;
+
+ if (info->ptr_res_groups)
+ if (!pac_io_group_membership_array("res group membership",
+ &info->res_groups,
+ info->res_group_count,
+ ps, depth))
+ return False;
+
+ return True;
+}
+
+
+static BOOL pac_io_pac_signature_data(const char *desc,
+ PAC_SIGNATURE_DATA *data, uint32 length,
+ prs_struct *ps, int depth)
+{
+ uint32 siglen = length - sizeof(uint32);
+ if (NULL == data)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_pac_signature_data");
+ depth++;
+
+ if (!prs_uint32("type", ps, depth, &data->type))
+ return False;
+ if (UNMARSHALLING(ps)) {
+ data->signature = prs_alloc_mem(ps, siglen);
+ if (!data->signature) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+ if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen))
+ return False;
+
+ return True;
+}
+
+static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
+ prs_struct *ps, int depth)
+{
+ if (NULL == hdr)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr");
+ depth++;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (hdr->offset != prs_offset(ps)) {
+ DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n",
+ hdr->offset, prs_offset(ps)));
+ prs_set_offset(ps, hdr->offset);
+ }
+
+ if (UNMARSHALLING(ps) && hdr->size > 0) {
+ hdr->ctr = (PAC_INFO_CTR *)
+ prs_alloc_mem(ps, sizeof(PAC_INFO_CTR));
+ if (!hdr->ctr) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ }
+
+ switch(hdr->type) {
+ case PAC_TYPE_LOGON_INFO:
+ DEBUG(5, ("PAC_TYPE_LOGON_INFO\n"));
+ if (UNMARSHALLING(ps))
+ hdr->ctr->pac.logon_info = (PAC_LOGON_INFO *)
+ prs_alloc_mem(ps, sizeof(PAC_LOGON_INFO));
+ if (!hdr->ctr->pac.logon_info) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info,
+ ps, depth))
+ return False;
+ break;
+
+ case PAC_TYPE_SERVER_CHECKSUM:
+ DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n"));
+ if (UNMARSHALLING(ps))
+ hdr->ctr->pac.srv_cksum = (PAC_SIGNATURE_DATA *)
+ prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA));
+ if (!hdr->ctr->pac.srv_cksum) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum,
+ hdr->size, ps, depth))
+ return False;
+ break;
+
+ case PAC_TYPE_PRIVSVR_CHECKSUM:
+ DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n"));
+ if (UNMARSHALLING(ps))
+ hdr->ctr->pac.privsrv_cksum = (PAC_SIGNATURE_DATA *)
+ prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA));
+ if (!hdr->ctr->pac.privsrv_cksum) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ if (!pac_io_pac_signature_data(desc,
+ hdr->ctr->pac.privsrv_cksum,
+ hdr->size, ps, depth))
+ return False;
+ break;
+
+ case PAC_TYPE_UNKNOWN_10:
+ DEBUG(5, ("PAC_TYPE_UNKNOWN_10\n"));
+ if (UNMARSHALLING(ps))
+ hdr->ctr->pac.type_10 = (UNKNOWN_TYPE_10 *)
+ prs_alloc_mem(ps, sizeof(UNKNOWN_TYPE_10));
+ if (!hdr->ctr->pac.type_10) {
+ DEBUG(3, ("No memory available\n"));
+ return False;
+ }
+ if (!pac_io_unknown_type_10(desc, hdr->ctr->pac.type_10,
+ ps, depth))
+ return False;
+ break;
+
+ default:
+ /* dont' know, so we need to skip it */
+ DEBUG(3, ("unknown PAC type %d\n", hdr->type));
+ prs_set_offset(ps, prs_offset(ps) + hdr->size);
+ }
+
+ return True;
+}
+
+static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr,
+ prs_struct *ps, int depth)
+{
+ if (NULL == hdr)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_pac_info_hdr");
+ depth++;
+
+ if (!prs_align(ps))
+ return False;
+ if (!prs_uint32("type", ps, depth, &hdr->type))
+ return False;
+ if (!prs_uint32("size", ps, depth, &hdr->size))
+ return False;
+ if (!prs_uint32("offset", ps, depth, &hdr->offset))
+ return False;
+ if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi))
+ return False;
+
+ return True;
+}
+
+static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data,
+ prs_struct *ps, int depth)
+{
+ int i;
+
+ if (NULL == data)
+ return False;
+
+ prs_debug(ps, depth, desc, "pac_io_pac_data");
+ depth++;
+
+ if (!prs_align(ps))
+ return False;
+ if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers))
+ return False;
+ if (!prs_uint32("version", ps, depth, &data->version))
+ return False;
+
+ if (UNMARSHALLING(ps) && data->num_buffers > 0) {
+ if ((data->pac_info_hdr_ptr = (PAC_INFO_HDR *)
+ prs_alloc_mem(ps, sizeof(PAC_INFO_HDR) *
+ data->num_buffers)) == NULL) {
+ return False;
+ }
+ }
+
+ for (i=0; i<data->num_buffers; i++) {
+ if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps,
+ depth))
+ return False;
+ }
+
+ for (i=0; i<data->num_buffers; i++) {
+ if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i],
+ ps, depth))
+ return False;
+ }
+
+ return True;
+}
+
+PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx)
+{
+ DATA_BLOB pac_data_blob = unwrap_pac(auth_data);
+ prs_struct ps;
+ PAC_DATA *pac_data;
+
+ DEBUG(5,("dump_pac_data\n"));
+ prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL);
+ prs_copy_data_in(&ps, pac_data_blob.data, pac_data_blob.length);
+ prs_set_offset(&ps, 0);
+
+ pac_data = (PAC_DATA *) talloc_zero(ctx, sizeof(PAC_DATA));
+ pac_io_pac_data("pac data", pac_data, &ps, 0);
+
+ prs_mem_free(&ps);
+
+ return pac_data;
+}
+
+#endif
diff --git a/source/libsmb/clifsinfo.c b/source/libsmb/clifsinfo.c
new file mode 100644
index 00000000000..00fe189e9a9
--- /dev/null
+++ b/source/libsmb/clifsinfo.c
@@ -0,0 +1,76 @@
+/*
+ Unix SMB/CIFS implementation.
+ FS info functions
+ Copyright (C) Stefan (metze) Metzmacher 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"
+
+
+BOOL cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr)
+{
+ BOOL ret = False;
+ uint16 setup;
+ char param[2];
+ char *rparam=NULL, *rdata=NULL;
+ unsigned int rparam_count=0, rdata_count=0;
+
+ if (!cli||!fs_attr)
+ smb_panic("cli_get_fs_attr_info() called with NULL Pionter!");
+
+ setup = TRANSACT2_QFSINFO;
+
+ SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL,
+ 0, 0,
+ &setup, 1, 0,
+ param, 2, 0,
+ NULL, 0, 560)) {
+ goto cleanup;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &rparam_count,
+ &rdata, &rdata_count)) {
+ goto cleanup;
+ }
+
+ if (cli_is_error(cli)) {
+ ret = False;
+ goto cleanup;
+ } else {
+ ret = True;
+ }
+
+ if (rdata_count < 12) {
+ goto cleanup;
+ }
+
+ *fs_attr = IVAL(rdata,0);
+
+ /* todo: but not yet needed
+ * return the other stuff
+ */
+
+cleanup:
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+
+ return ret;
+}
diff --git a/source/rpc_client/cli_echo.c b/source/rpc_client/cli_echo.c
new file mode 100644
index 00000000000..03a4ab36ee0
--- /dev/null
+++ b/source/rpc_client/cli_echo.c
@@ -0,0 +1,187 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ RPC pipe client
+
+ 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 "includes.h"
+
+NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 request, uint32 *response)
+{
+ prs_struct qbuf, rbuf;
+ ECHO_Q_ADD_ONE q;
+ ECHO_R_ADD_ONE r;
+ BOOL result = False;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Marshall data and send request */
+
+ init_echo_q_add_one(&q, request);
+
+ if (!echo_io_q_add_one("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, ECHO_ADD_ONE, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!echo_io_r_add_one("", &r, &rbuf, 0))
+ goto done;
+
+ if (response)
+ *response = r.response;
+
+ result = True;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 size, char *in_data, char **out_data)
+{
+ prs_struct qbuf, rbuf;
+ ECHO_Q_ECHO_DATA q;
+ ECHO_R_ECHO_DATA r;
+ BOOL result = False;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Marshall data and send request */
+
+ init_echo_q_echo_data(&q, size, in_data);
+
+ if (!echo_io_q_echo_data("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, ECHO_DATA, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!echo_io_r_echo_data("", &r, &rbuf, 0))
+ goto done;
+
+ result = True;
+
+ if (out_data) {
+ *out_data = talloc(mem_ctx, size);
+ memcpy(*out_data, r.data, size);
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 size, char *in_data)
+{
+ prs_struct qbuf, rbuf;
+ ECHO_Q_SINK_DATA q;
+ ECHO_R_SINK_DATA r;
+ BOOL result = False;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Marshall data and send request */
+
+ init_echo_q_sink_data(&q, size, in_data);
+
+ if (!echo_io_q_sink_data("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, ECHO_SINK_DATA, &qbuf, &rbuf)) {
+ goto done;
+ }
+
+ /* Unmarshall response */
+
+ if (!echo_io_r_sink_data("", &r, &rbuf, 0)) {
+ goto done;
+ }
+
+ result = True;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 size, char **out_data)
+{
+ prs_struct qbuf, rbuf;
+ ECHO_Q_SOURCE_DATA q;
+ ECHO_R_SOURCE_DATA r;
+ BOOL result = False;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Marshall data and send request */
+
+ init_echo_q_source_data(&q, size);
+
+ if (!echo_io_q_source_data("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, ECHO_SOURCE_DATA, &qbuf, &rbuf)) {
+ goto done;
+ }
+
+ /* Unmarshall response */
+
+ if (!echo_io_r_source_data("", &r, &rbuf, 0)) {
+ goto done;
+ }
+
+ result = True;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
diff --git a/source/rpc_parse/parse_echo.c b/source/rpc_parse/parse_echo.c
new file mode 100644
index 00000000000..67f9ad772ee
--- /dev/null
+++ b/source/rpc_parse/parse_echo.c
@@ -0,0 +1,166 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * RPC Pipe client / server 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 "includes.h"
+#include "nterr.h"
+#include "rpc_parse.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_PARSE
+
+void init_echo_q_add_one(ECHO_Q_ADD_ONE *q_d, uint32 request)
+{
+ q_d->request = request;
+}
+
+BOOL echo_io_q_add_one(const char *desc, ECHO_Q_ADD_ONE *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("request", ps, 0, &q_d->request))
+ return False;
+
+ return True;
+}
+
+BOOL echo_io_r_add_one(const char *desc, ECHO_R_ADD_ONE *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("response", ps, 0, &q_d->response))
+ return False;
+
+ return True;
+}
+
+
+void init_echo_q_echo_data(ECHO_Q_ECHO_DATA *q_d, uint32 size, char *data)
+{
+ q_d->size = size;
+ q_d->data = data;
+}
+
+BOOL echo_io_q_echo_data(const char *desc, ECHO_Q_ECHO_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("size", ps, depth, &q_d->size))
+ return False;
+
+ if (!prs_uint32("size", ps, depth, &q_d->size))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ q_d->data = prs_alloc_mem(ps, q_d->size);
+
+ if (!q_d->data)
+ return False;
+ }
+
+ if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+ return False;
+
+ return True;
+}
+
+BOOL echo_io_r_echo_data(const char *desc, ECHO_R_ECHO_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("size", ps, 0, &q_d->size))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ q_d->data = prs_alloc_mem(ps, q_d->size);
+
+ if (!q_d->data)
+ return False;
+ }
+
+ if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+ return False;
+
+ return True;
+}
+
+void init_echo_q_sink_data(ECHO_Q_SINK_DATA *q_d, uint32 size, char *data)
+{
+ q_d->size = size;
+ q_d->data = data;
+}
+
+BOOL echo_io_q_sink_data(const char *desc, ECHO_Q_SINK_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("size", ps, depth, &q_d->size))
+ return False;
+
+ if (!prs_uint32("size", ps, depth, &q_d->size))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ q_d->data = prs_alloc_mem(ps, q_d->size);
+
+ if (!q_d->data)
+ return False;
+ }
+
+ if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+ return False;
+
+ return True;
+}
+
+BOOL echo_io_r_sink_data(const char *desc, ECHO_R_SINK_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ return True;
+}
+
+void init_echo_q_source_data(ECHO_Q_SOURCE_DATA *q_d, uint32 size)
+{
+ q_d->size = size;
+}
+
+BOOL echo_io_q_source_data(const char *desc, ECHO_Q_SOURCE_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("size", ps, depth, &q_d->size))
+ return False;
+
+ return True;
+}
+
+BOOL echo_io_r_source_data(const char *desc, ECHO_R_SOURCE_DATA *q_d,
+ prs_struct *ps, int depth)
+{
+ if (!prs_uint32("size", ps, 0, &q_d->size))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ q_d->data = prs_alloc_mem(ps, q_d->size);
+
+ if (!q_d->data)
+ return False;
+ }
+
+ if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+ return False;
+
+ return True;
+}
diff --git a/source/rpc_server/srv_echo.c b/source/rpc_server/srv_echo.c
new file mode 100644
index 00000000000..dcd8dd0c53b
--- /dev/null
+++ b/source/rpc_server/srv_echo.c
@@ -0,0 +1,137 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines for rpcecho
+ * 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.
+ */
+
+/* This is the interface to the rpcecho pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#ifdef DEVELOPER
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static BOOL api_add_one(pipes_struct *p)
+{
+ ECHO_Q_ADD_ONE q_u;
+ ECHO_R_ADD_ONE r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!echo_io_q_add_one("", &q_u, data, 0))
+ return False;
+
+ _echo_add_one(p, &q_u, &r_u);
+
+ if(!echo_io_r_add_one("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+static BOOL api_echo_data(pipes_struct *p)
+{
+ ECHO_Q_ECHO_DATA q_u;
+ ECHO_R_ECHO_DATA r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!echo_io_q_echo_data("", &q_u, data, 0))
+ return False;
+
+ _echo_data(p, &q_u, &r_u);
+
+ if(!echo_io_r_echo_data("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+static BOOL api_source_data(pipes_struct *p)
+{
+ ECHO_Q_SOURCE_DATA q_u;
+ ECHO_R_SOURCE_DATA r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!echo_io_q_source_data("", &q_u, data, 0))
+ return False;
+
+ _source_data(p, &q_u, &r_u);
+
+ if(!echo_io_r_source_data("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+static BOOL api_sink_data(pipes_struct *p)
+{
+ ECHO_Q_SINK_DATA q_u;
+ ECHO_R_SINK_DATA r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!echo_io_q_sink_data("", &q_u, data, 0))
+ return False;
+
+ _sink_data(p, &q_u, &r_u);
+
+ if(!echo_io_r_sink_data("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+\pipe\rpcecho commands
+********************************************************************/
+
+int rpc_echo_init(void)
+{
+ struct api_struct api_echo_cmds[] = {
+ {"ADD_ONE", ECHO_ADD_ONE, api_add_one },
+ {"ECHO_DATA", ECHO_DATA, api_echo_data },
+ {"SOURCE_DATA", ECHO_SOURCE_DATA, api_source_data },
+ {"SINK_DATA", ECHO_SINK_DATA, api_sink_data },
+ };
+
+ return rpc_pipe_register_commands(
+ "rpcecho", "rpcecho", api_echo_cmds,
+ sizeof(api_echo_cmds) / sizeof(struct api_struct));
+}
+
+#endif /* DEVELOPER */
diff --git a/source/rpc_server/srv_echo_nt.c b/source/rpc_server/srv_echo_nt.c
new file mode 100644
index 00000000000..ddb76b3a21e
--- /dev/null
+++ b/source/rpc_server/srv_echo_nt.c
@@ -0,0 +1,78 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines for rpcecho
+ * 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.
+ */
+
+/* This is the interface to the rpcecho pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#ifdef DEVELOPER
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/* Add one to the input and return it */
+
+void _echo_add_one(pipes_struct *p, ECHO_Q_ADD_ONE *q_u, ECHO_R_ADD_ONE *r_u)
+{
+ DEBUG(10, ("_echo_add_one\n"));
+
+ r_u->response = q_u->request + 1;
+}
+
+/* Echo back an array of data */
+
+void _echo_data(pipes_struct *p, ECHO_Q_ECHO_DATA *q_u,
+ ECHO_R_ECHO_DATA *r_u)
+{
+ DEBUG(10, ("_echo_data\n"));
+
+ r_u->data = talloc(p->mem_ctx, q_u->size);
+ r_u->size = q_u->size;
+ memcpy(r_u->data, q_u->data, q_u->size);
+}
+
+/* Sink an array of data */
+
+void _sink_data(pipes_struct *p, ECHO_Q_SINK_DATA *q_u,
+ ECHO_R_SINK_DATA *r_u)
+{
+ DEBUG(10, ("_sink_data\n"));
+
+ /* My that was some yummy data! */
+}
+
+/* Source an array of data */
+
+void _source_data(pipes_struct *p, ECHO_Q_SOURCE_DATA *q_u,
+ ECHO_R_SOURCE_DATA *r_u)
+{
+ uint32 i;
+
+ DEBUG(10, ("_source_data\n"));
+
+ r_u->data = talloc(p->mem_ctx, q_u->size);
+ r_u->size = q_u->size;
+
+ for (i = 0; i < r_u->size; i++)
+ r_u->data[i] = i & 0xff;
+}
+
+#endif /* DEVELOPER */
diff --git a/source/rpcclient/cmd_echo.c b/source/rpcclient/cmd_echo.c
new file mode 100644
index 00000000000..79ba744a55a
--- /dev/null
+++ b/source/rpcclient/cmd_echo.c
@@ -0,0 +1,157 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ 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 "includes.h"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 request = 1, response;
+ NTSTATUS result;
+
+ if (argc > 2) {
+ printf("Usage: %s [num]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ request = atoi(argv[1]);
+
+ result = cli_echo_add_one(cli, mem_ctx, request, &response);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("%d + 1 = %d\n", request, response);
+
+done:
+ return result;
+}
+
+static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ char *in_data = NULL, *out_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+ in_data = malloc(size);
+
+ for (i = 0; i < size; i++)
+ in_data[i] = i & 0xff;
+
+ result = cli_echo_data(cli, mem_ctx, size, in_data, &out_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < size; i++) {
+ if (in_data[i] != out_data[i]) {
+ printf("mismatch at offset %d, %d != %d\n",
+ i, in_data[i], out_data[i]);
+ }
+ }
+
+done:
+ SAFE_FREE(in_data);
+
+ return result;
+}
+
+static NTSTATUS cmd_echo_source_data(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ char *out_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+
+ result = cli_echo_source_data(cli, mem_ctx, size, &out_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < size; i++) {
+ if (out_data && out_data[i] != (i & 0xff)) {
+ printf("mismatch at offset %d, %d != %d\n",
+ i, out_data[i], i & 0xff);
+ }
+ }
+
+done:
+ return result;
+}
+
+static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ char *in_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+ in_data = malloc(size);
+
+ for (i = 0; i < size; i++)
+ in_data[i] = i & 0xff;
+
+ result = cli_echo_sink_data(cli, mem_ctx, size, in_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+done:
+ SAFE_FREE(in_data);
+
+ return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set echo_commands[] = {
+
+ { "ECHO" },
+
+ { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one, NULL, PI_ECHO, "Add one to a number", "" },
+ { "echodata", RPC_RTYPE_NTSTATUS, cmd_echo_data, NULL, PI_ECHO, "Echo data", "" },
+ { "sinkdata", RPC_RTYPE_NTSTATUS, cmd_echo_sink_data, NULL, PI_ECHO, "Sink data", "" },
+ { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, "Source data", "" },
+ { NULL }
+};
diff --git a/source/stf/smbcontrol.py b/source/stf/smbcontrol.py
new file mode 100755
index 00000000000..30c331819c7
--- /dev/null
+++ b/source/stf/smbcontrol.py
@@ -0,0 +1,238 @@
+#!/usr/bin/python
+#
+# Test for smbcontrol command line argument handling.
+#
+
+import comfychair
+
+class NoArgs(comfychair.TestCase):
+ """Test no arguments produces usage message."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol", expectedResult = 1)
+ self.assert_re_match("Usage: smbcontrol", out[1])
+
+class OneArg(comfychair.TestCase):
+ """Test single argument produces usage message."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol foo", expectedResult = 1)
+ self.assert_re_match("Usage: smbcontrol", out[1])
+
+class SmbdDest(comfychair.TestCase):
+ """Test the broadcast destination 'smbd'."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol smbd noop")
+
+class NmbdDest(comfychair.TestCase):
+ """Test the destination 'nmbd'."""
+ def runtest(self):
+ # We need a way to start/stop/whatever nmbd
+ raise comfychair.NotRunError, "not implemented"
+
+class PidDest(comfychair.TestCase):
+ """Test a pid number destination'."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol 1234 noop")
+
+class SelfDest(comfychair.TestCase):
+ """Test the destination 'self'."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol self noop")
+
+class WinbinddDest(comfychair.TestCase):
+ """Test the destination 'winbindd'."""
+ def runtest(self):
+ # We need a way to start/stop/whatever winbindd
+ raise comfychair.NotRunError, "not implemented"
+
+class BadDest(comfychair.TestCase):
+ """Test a bad destination."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol foo noop", expectedResult = 1)
+
+class BadCmd(comfychair.TestCase):
+ """Test a bad command."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol self spottyfoot", expectedResult = 1)
+ self.assert_re_match("smbcontrol: unknown command", out[1]);
+
+class NoArgCmdTest(comfychair.TestCase):
+ """A test class that tests a command with no argument."""
+ def runtest(self):
+ self.require_root()
+ out = self.runcmd("smbcontrol self %s" % self.cmd)
+ out = self.runcmd("smbcontrol self %s spottyfoot" % self.cmd,
+ expectedResult = 1)
+
+class ForceElection(NoArgCmdTest):
+ """Test a force-election message."""
+ def setup(self):
+ self.cmd = "force-election"
+
+class SamSync(NoArgCmdTest):
+ """Test a samsync message."""
+ def setup(self):
+ self.cmd = "samsync"
+
+class SamRepl(NoArgCmdTest):
+ """Test a samrepl message."""
+ def setup(self):
+ self.cmd = "samrepl"
+
+class DmallocChanged(NoArgCmdTest):
+ """Test a dmalloc-changed message."""
+ def setup(self):
+ self.cmd = "dmalloc-log-changed"
+
+class DmallocMark(NoArgCmdTest):
+ """Test a dmalloc-mark message."""
+ def setup(self):
+ self.cmd = "dmalloc-mark"
+
+class Shutdown(NoArgCmdTest):
+ """Test a shutdown message."""
+ def setup(self):
+ self.cmd = "shutdown"
+
+class Ping(NoArgCmdTest):
+ """Test a ping message."""
+ def setup(self):
+ self.cmd = "ping"
+
+class Debuglevel(NoArgCmdTest):
+ """Test a debuglevel message."""
+ def setup(self):
+ self.cmd = "debuglevel"
+
+class OneArgCmdTest(comfychair.TestCase):
+ """A test class that tests a command with one argument."""
+ def runtest(self):
+ self.require_root()
+ out = self.runcmd("smbcontrol self %s spottyfoot" % self.cmd)
+ out = self.runcmd("smbcontrol self %s" % self.cmd, expectedResult = 1)
+
+class DrvUpgrade(OneArgCmdTest):
+ """Test driver upgrade message."""
+ def setup(self):
+ self.cmd = "drvupgrade"
+
+class CloseShare(OneArgCmdTest):
+ """Test close share message."""
+ def setup(self):
+ self.cmd = "close-share"
+
+class Debug(OneArgCmdTest):
+ """Test a debug message."""
+ def setup(self):
+ self.cmd = "debug"
+
+class PrintNotify(comfychair.TestCase):
+ """Test print notification commands."""
+ def runtest(self):
+
+ # No subcommand
+
+ out = self.runcmd("smbcontrol self printnotify", expectedResult = 1)
+ self.assert_re_match("Must specify subcommand", out[1]);
+
+ # Invalid subcommand name
+
+ out = self.runcmd("smbcontrol self printnotify spottyfoot",
+ expectedResult = 1)
+ self.assert_re_match("Invalid subcommand", out[1]);
+
+ # Queue commands
+
+ for cmd in ["queuepause", "queueresume"]:
+
+ out = self.runcmd("smbcontrol self printnotify %s" % cmd,
+ expectedResult = 1)
+ self.assert_re_match("Usage:", out[1])
+
+ out = self.runcmd("smbcontrol self printnotify %s spottyfoot"
+ % cmd)
+
+ # Job commands
+
+ for cmd in ["jobpause", "jobresume", "jobdelete"]:
+
+ out = self.runcmd("smbcontrol self printnotify %s" % cmd,
+ expectedResult = 1)
+ self.assert_re_match("Usage:", out[1])
+
+ out = self.runcmd("smbcontrol self printnotify %s spottyfoot"
+ % cmd, expectedResult = 1)
+ self.assert_re_match("Usage:", out[1])
+
+ out = self.runcmd("smbcontrol self printnotify %s spottyfoot 123"
+ % cmd)
+
+ # Printer properties
+
+ out = self.runcmd("smbcontrol self printnotify printer",
+ expectedResult = 1)
+ self.assert_re_match("Usage", out[1])
+
+ out = self.runcmd("smbcontrol self printnotify printer spottyfoot",
+ expectedResult = 1)
+ self.assert_re_match("Usage", out[1])
+
+ for cmd in ["comment", "port", "driver"]:
+
+ out = self.runcmd("smbcontrol self printnotify printer spottyfoot "
+ "%s" % cmd, expectedResult = 1)
+ self.assert_re_match("Usage", out[1])
+
+ out = self.runcmd("smbcontrol self printnotify printer spottyfoot "
+ "%s value" % cmd)
+
+class Profile(comfychair.TestCase):
+ """Test setting the profiling level."""
+ def runtest(self):
+ self.require_root()
+ out = self.runcmd("smbcontrol self profile", expectedResult = 1)
+ self.assert_re_match("Usage", out[1])
+
+ out = self.runcmd("smbcontrol self profile spottyfoot",
+ expectedResult = 1)
+ self.assert_re_match("Unknown", out[1])
+
+ for cmd in ["off", "count", "on", "flush"]:
+ out = self.runcmd("smbcontrol self profile %s" % cmd)
+
+class ProfileLevel(comfychair.TestCase):
+ """Test requesting the current profiling level."""
+ def runtest(self):
+ self.require_root()
+ out = self.runcmd("smbcontrol self profilelevel spottyfoot",
+ expectedResult = 1)
+ self.assert_re_match("Usage", out[1])
+
+ out = self.runcmd("smbcontrol self profilelevel")
+
+class TimeoutArg(comfychair.TestCase):
+ """Test the --timeout argument."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol --timeout 5 self noop")
+ out = self.runcmd("smbcontrol --timeout spottyfoot self noop",
+ expectedResult = 1)
+
+class ConfigFileArg(comfychair.TestCase):
+ """Test the --configfile argument."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol --configfile /dev/null self noop")
+
+class BogusArg(comfychair.TestCase):
+ """Test a bogus command line argument."""
+ def runtest(self):
+ out = self.runcmd("smbcontrol --bogus self noop", expectedResult = 1)
+
+tests = [NoArgs, OneArg, SmbdDest, NmbdDest, WinbinddDest, PidDest,
+ SelfDest, BadDest, BadCmd, Debug, ForceElection, SamSync,
+ SamRepl, DmallocMark, DmallocChanged, Shutdown, DrvUpgrade,
+ CloseShare, Ping, Debuglevel, PrintNotify, Profile, ProfileLevel,
+ TimeoutArg, ConfigFileArg, BogusArg]
+
+# Handle execution of this file as a main program
+
+if __name__ == '__main__':
+ comfychair.main(tests)
diff --git a/source/stf/unicodenames.py b/source/stf/unicodenames.py
new file mode 100644
index 00000000000..d4100cb7f90
--- /dev/null
+++ b/source/stf/unicodenames.py
@@ -0,0 +1,33 @@
+#! /usr/bin/python
+
+# Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+
+"""
+Defines symbolic names for a few UNICODE characters, to make test
+source code more readable on machines that don't have all the
+necessary fonts.
+
+You can do "import *" on this file safely.
+"""
+
+LATIN_CAPITAL_LETTER_N_WITH_TILDE = u'\u004e'
+LATIN_CAPITAL_LETTER_O_WITH_DIARESIS = u'\u00d6'
+LATIN_SMALL_LETTER_O_WITH_DIARESIS = u'\u00f6'
+
+KATAKANA_LETTER_A = u'\u30a2'
diff --git a/source/torture/t_push_ucs2.c b/source/torture/t_push_ucs2.c
new file mode 100644
index 00000000000..8bfc6f7ad9e
--- /dev/null
+++ b/source/torture/t_push_ucs2.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2003 by Martin Pool
+ * Copyright (C) 2003 by Andrew Bartlett
+ *
+ * Test harness for push_ucs2
+ */
+
+#include "includes.h"
+
+static int check_push_ucs2(const char *orig)
+{
+ smb_ucs2_t *dest = NULL;
+ char *orig2 = NULL;
+ int ret;
+
+ push_ucs2_allocate(&dest, orig);
+ pull_ucs2_allocate(&orig2, dest);
+ ret = strcmp(orig, orig2);
+ if (ret) {
+ fprintf(stderr, "orig: %s\n", orig);
+ fprintf(stderr, "orig (UNIX -> UCS2 -> UNIX): %s\n", orig2);
+ }
+
+ SAFE_FREE(dest);
+ SAFE_FREE(orig2);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, ret = 0;
+ int count = 1;
+
+ /* Needed to initialize character set */
+ lp_load("/dev/null", True, False, False);
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s STRING1 [COUNT]\n"
+ "Checks that a string translated UNIX->UCS2->UNIX is unchanged\n"
+ "Should be always 0\n",
+ argv[0]);
+ return 2;
+ }
+ if (argc >= 3)
+ count = atoi(argv[2]);
+
+ for (i = 0; ((i < count) && (!ret)); i++)
+ ret = check_push_ucs2(argv[1]);
+
+ printf("%d\n", ret);
+
+ return 0;
+}
diff --git a/source/torture/t_strcmp.c b/source/torture/t_strcmp.c
new file mode 100644
index 00000000000..bc8640ee550
--- /dev/null
+++ b/source/torture/t_strcmp.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2003 by Martin Pool
+ *
+ * Test harness for StrCaseCmp
+ */
+
+#include "includes.h"
+
+int main(int argc, char *argv[])
+{
+ int i, ret;
+ int iters = 1;
+
+ /* Needed to initialize character set */
+ lp_load("/dev/null", True, False, False);
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s STRING1 STRING2 [ITERS]\n"
+ "Compares two strings, prints the results of StrCaseCmp\n",
+ argv[0]);
+ return 2;
+ }
+ if (argc >= 4)
+ iters = atoi(argv[3]);
+
+ for (i = 0; i < iters; i++)
+ ret = StrCaseCmp(argv[1], argv[2]);
+
+ printf("%d\n", ret);
+
+ return 0;
+}
diff --git a/source/utils/smbcquotas.c b/source/utils/smbcquotas.c
new file mode 100644
index 00000000000..c5d0aa869bf
--- /dev/null
+++ b/source/utils/smbcquotas.c
@@ -0,0 +1,545 @@
+/*
+ Unix SMB/CIFS implementation.
+ QUOTA get/set utility
+
+ Copyright (C) Andrew Tridgell 2000
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jeremy Allison 2000
+ Copyright (C) Stefan (metze) Metzmacher 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"
+
+static pstring server;
+
+/* numeric is set when the user wants numeric SIDs and ACEs rather
+ than going via LSA calls to resolve them */
+static BOOL numeric;
+static BOOL verbose;
+
+enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA};
+enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
+
+static struct cli_state *cli_ipc = NULL;
+static POLICY_HND pol;
+static BOOL got_policy_hnd;
+
+static struct cli_state *connect_one(const char *share);
+
+/* Open cli connection and policy handle */
+
+static BOOL cli_open_policy_hnd(void)
+{
+ /* Initialise cli LSA connection */
+
+ if (!cli_ipc) {
+ cli_ipc = connect_one("IPC$");
+ if (!cli_nt_session_open (cli_ipc, PI_LSARPC)) {
+ return False;
+ }
+ }
+
+ /* Open policy handle */
+
+ if (!got_policy_hnd) {
+
+ /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
+ but NT sends 0x2000000 so we might as well do it too. */
+
+ if (!NT_STATUS_IS_OK(cli_lsa_open_policy(cli_ipc, cli_ipc->mem_ctx, True,
+ GENERIC_EXECUTE_ACCESS, &pol))) {
+ return False;
+ }
+
+ got_policy_hnd = True;
+ }
+
+ return True;
+}
+
+/* convert a SID to a string, either numeric or username/group */
+static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric)
+{
+ char **domains = NULL;
+ char **names = NULL;
+ uint32 *types = NULL;
+
+ sid_to_string(str, sid);
+
+ if (_numeric) return;
+
+ /* Ask LSA to convert the sid to a name */
+
+ if (!cli_open_policy_hnd() ||
+ !NT_STATUS_IS_OK(cli_lsa_lookup_sids(cli_ipc, cli_ipc->mem_ctx,
+ &pol, 1, sid, &domains,
+ &names, &types)) ||
+ !domains || !domains[0] || !names || !names[0]) {
+ return;
+ }
+
+ /* Converted OK */
+
+ slprintf(str, sizeof(fstring) - 1, "%s%s%s",
+ domains[0], lp_winbind_separator(),
+ names[0]);
+
+}
+
+/* convert a string to a SID, either numeric or username/group */
+static BOOL StringToSid(DOM_SID *sid, const char *str)
+{
+ uint32 *types = NULL;
+ DOM_SID *sids = NULL;
+ BOOL result = True;
+
+ if (strncmp(str, "S-", 2) == 0) {
+ return string_to_sid(sid, str);
+ }
+
+ if (!cli_open_policy_hnd() ||
+ !NT_STATUS_IS_OK(cli_lsa_lookup_names(cli_ipc, cli_ipc->mem_ctx,
+ &pol, 1, &str, &sids,
+ &types))) {
+ result = False;
+ goto done;
+ }
+
+ sid_copy(sid, &sids[0]);
+ done:
+
+ return result;
+}
+
+#define QUOTA_GET 1
+#define QUOTA_SETLIM 2
+#define QUOTA_SETFLAGS 3
+#define QUOTA_LIST 4
+
+enum {PARSE_FLAGS,PARSE_LIM};
+
+static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA_TYPE *qtype, int *cmd, SMB_NTQUOTA_STRUCT *pqt)
+{
+ char *p = set_str,*p2;
+ int todo;
+ BOOL stop = False;
+ BOOL enable = False;
+ BOOL deny = False;
+
+ if (strncasecmp(set_str,"UQLIM:",6)==0) {
+ p += 6;
+ *qtype = SMB_USER_QUOTA_TYPE;
+ *cmd = QUOTA_SETLIM;
+ todo = PARSE_LIM;
+ if ((p2=strstr(p,":"))==NULL) {
+ return -1;
+ }
+
+ *p2 = '\0';
+ p2++;
+
+ fstrcpy(username_str,p);
+ p = p2;
+ } else if (strncasecmp(set_str,"FSQLIM:",7)==0) {
+ p +=7;
+ *qtype = SMB_USER_FS_QUOTA_TYPE;
+ *cmd = QUOTA_SETLIM;
+ todo = PARSE_LIM;
+ } else if (strncasecmp(set_str,"FSQFLAGS:",9)==0) {
+ p +=9;
+ todo = PARSE_FLAGS;
+ *qtype = SMB_USER_FS_QUOTA_TYPE;
+ *cmd = QUOTA_SETFLAGS;
+ } else {
+ return -1;
+ }
+
+ switch (todo) {
+ case PARSE_LIM:
+#if defined(HAVE_LONGLONG)
+ if (sscanf(p,"%llu/%llu",&pqt->softlim,&pqt->hardlim)!=2) {
+#else
+ if (sscanf(p,"%lu/%lu",&pqt->softlim,&pqt->hardlim)!=2) {
+#endif
+ return -1;
+ }
+
+ break;
+ case PARSE_FLAGS:
+ while (!stop) {
+
+ if ((p2=strstr(p,"/"))==NULL) {
+ stop = True;
+ } else {
+ *p2 = '\0';
+ p2++;
+ }
+
+ if (strncasecmp(p,"QUOTA_ENABLED",13)==0) {
+ enable = True;
+ } else if (strncasecmp(p,"DENY_DISK",9)==0) {
+ deny = True;
+ } else if (strncasecmp(p,"LOG_SOFTLIMIT",13)==0) {
+ pqt->qflags |= QUOTAS_LOG_THRESHOLD;
+ } else if (strncasecmp(p,"LOG_HARDLIMIT",13)==0) {
+ pqt->qflags |= QUOTAS_LOG_LIMIT;
+ } else {
+ return -1;
+ }
+
+ p=p2;
+ }
+
+ if (deny) {
+ pqt->qflags |= QUOTAS_DENY_DISK;
+ } else if (enable) {
+ pqt->qflags |= QUOTAS_ENABLED;
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+static int do_quota(struct cli_state *cli, enum SMB_QUOTA_TYPE qtype, uint16 cmd, pstring username_str, SMB_NTQUOTA_STRUCT *pqt)
+{
+ uint32 fs_attrs = 0;
+ int quota_fnum = 0;
+ SMB_NTQUOTA_LIST *qtl = NULL;
+ SMB_NTQUOTA_STRUCT qt;
+ ZERO_STRUCT(qt);
+
+ if (!cli_get_fs_attr_info(cli, &fs_attrs)) {
+ d_printf("Failed to get the filesystem attributes %s.\n",
+ cli_errstr(cli));
+ return -1;
+ }
+
+ if (!(fs_attrs & FILE_VOLUME_QUOTAS)) {
+ d_printf("Quotas are not supported by the server.\n");
+ return 0;
+ }
+
+ if (!cli_get_quota_handle(cli, &quota_fnum)) {
+ d_printf("Failed to open \\%s %s.\n",
+ FAKE_FILE_NAME_QUOTA,cli_errstr(cli));
+ return -1;
+ }
+
+ switch(qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if (!StringToSid(&qt.sid, username_str)) {
+ d_printf("StringToSid() failed for [%s]\n",username_str);
+ return -1;
+ }
+
+ switch(cmd) {
+ case QUOTA_GET:
+ if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_user_quota %s\n",
+ cli_errstr(cli),username_str);
+ return -1;
+ }
+ dump_ntquota(&qt,verbose,numeric,SidToString);
+ break;
+ case QUOTA_SETLIM:
+ pqt->sid = qt.sid;
+ if (!cli_set_user_quota(cli, quota_fnum, pqt)) {
+ d_printf("%s cli_set_user_quota %s\n",
+ cli_errstr(cli),username_str);
+ return -1;
+ }
+ if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_user_quota %s\n",
+ cli_errstr(cli),username_str);
+ return -1;
+ }
+ dump_ntquota(&qt,verbose,numeric,SidToString);
+ break;
+ case QUOTA_LIST:
+ if (!cli_list_user_quota(cli, quota_fnum, &qtl)) {
+ d_printf("%s cli_set_user_quota %s\n",
+ cli_errstr(cli),username_str);
+ return -1;
+ }
+ dump_ntquota_list(&qtl,verbose,numeric,SidToString);
+ free_ntquota_list(&qtl);
+ break;
+ default:
+ d_printf("Unknown Error\n");
+ return -1;
+ }
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ switch(cmd) {
+ case QUOTA_GET:
+ if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ dump_ntquota(&qt,True,numeric,NULL);
+ break;
+ case QUOTA_SETLIM:
+ if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ qt.softlim = pqt->softlim;
+ qt.hardlim = pqt->hardlim;
+ if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_set_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ dump_ntquota(&qt,True,numeric,NULL);
+ break;
+ case QUOTA_SETFLAGS:
+ if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ qt.qflags = pqt->qflags;
+ if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_set_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
+ d_printf("%s cli_get_fs_quota_info\n",
+ cli_errstr(cli));
+ return -1;
+ }
+ dump_ntquota(&qt,True,numeric,NULL);
+ break;
+ default:
+ d_printf("Unknown Error\n");
+ return -1;
+ }
+ break;
+ default:
+ d_printf("Unknown Error\n");
+ return -1;
+ }
+
+ cli_close(cli, quota_fnum);
+
+ return 0;
+}
+
+/*****************************************************
+return a connection to a server
+*******************************************************/
+static struct cli_state *connect_one(const char *share)
+{
+ struct cli_state *c;
+ struct in_addr ip;
+ NTSTATUS nt_status;
+ zero_ip(&ip);
+
+ if (!cmdline_auth_info.got_pass) {
+ char *pass = getpass("Password: ");
+ if (pass) {
+ pstrcpy(cmdline_auth_info.password, pass);
+ cmdline_auth_info.got_pass = True;
+ }
+ }
+
+ if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
+ &ip, 0,
+ share, "?????",
+ cmdline_auth_info.username, lp_workgroup(),
+ cmdline_auth_info.password, 0, NULL))) {
+ return c;
+ } else {
+ DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
+ return NULL;
+ }
+}
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc, const char *argv[])
+{
+ char *share;
+ int opt;
+ int result;
+ int todo = 0;
+ pstring username_str = {0};
+ pstring path = {0};
+ pstring set_str = {0};
+ enum SMB_QUOTA_TYPE qtype;
+ int cmd = 0;
+ BOOL test_args = False;
+ struct cli_state *cli;
+ BOOL fix_user = False;
+ SMB_NTQUOTA_STRUCT qt;
+ poptContext pc;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "user", 'u', POPT_ARG_STRING, NULL, 'u', "Show quotas for user", "user" },
+ { "list", 'L', POPT_ARG_NONE, NULL, 'L', "List user quotas" },
+ { "fs", 'F', POPT_ARG_NONE, NULL, 'F', "Show filesystem quotas" },
+ { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls\n\
+SETSTRING:\n\
+UQLIM:<username>/<softlimit>/<hardlimit> for user quotas\n\
+FSQLIM:<softlimit>/<hardlimit> for filesystem defaults\n\
+FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
+ { "numeric", 'n', POPT_ARG_NONE, &numeric, True, "Don't resolve sids or limits to names" },
+ { "verbose", 'v', POPT_ARG_NONE, &verbose, True, "be verbose" },
+ { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"},
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CREDENTIALS
+ { NULL }
+ };
+
+ ZERO_STRUCT(qt);
+
+ setlinebuf(stdout);
+
+ dbf = x_stderr;
+
+ fault_setup(NULL);
+
+ setup_logging(argv[0],True);
+
+
+ lp_load(dyn_CONFIGFILE,True,False,False);
+ load_interfaces();
+
+ pc = poptGetContext("smbcquotas", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "//server1/share1");
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'L':
+ if (todo != 0) {
+ d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
+ exit(EXIT_PARSE_ERROR);
+ }
+ todo = LIST_QUOTA;
+ break;
+
+ case 'F':
+ if (todo != 0) {
+ d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
+ exit(EXIT_PARSE_ERROR);
+ }
+ todo = FS_QUOTA;
+ break;
+
+ case 'u':
+ if (todo != 0) {
+ d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
+ exit(EXIT_PARSE_ERROR);
+ }
+ pstrcpy(username_str,poptGetOptArg(pc));
+ todo = USER_QUOTA;
+ fix_user = True;
+ break;
+
+ case 'S':
+ if (todo != 0) {
+ d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
+ exit(EXIT_PARSE_ERROR);
+ }
+ pstrcpy(set_str,poptGetOptArg(pc));
+ todo = SET_QUOTA;
+ break;
+ }
+ }
+
+ if (todo == 0)
+ todo = USER_QUOTA;
+
+ if (!fix_user)
+ pstrcpy(username_str,cmdline_auth_info.username);
+
+ /* Make connection to server */
+ if(!poptPeekArg(pc)) {
+ poptPrintUsage(pc, stderr, 0);
+ exit(EXIT_PARSE_ERROR);
+ }
+
+ pstrcpy(path, poptGetArg(pc));
+
+ all_string_sub(path,"/","\\",0);
+
+ pstrcpy(server,path+2);
+ share = strchr_m(server,'\\');
+ if (!share) {
+ share = strchr_m(server,'/');
+ if (!share) {
+ printf("Invalid argument: %s\n", share);
+ exit(EXIT_PARSE_ERROR);
+ }
+ }
+
+ *share = 0;
+ share++;
+
+ if (todo == SET_QUOTA) {
+ if (parse_quota_set(set_str, username_str, &qtype, &cmd, &qt)) {
+ printf("Invalid argument: -S %s\n", set_str);
+ exit(EXIT_PARSE_ERROR);
+ }
+ }
+
+ if (!test_args) {
+ cli = connect_one(share);
+ if (!cli) {
+ exit(EXIT_FAILED);
+ }
+ } else {
+ exit(EXIT_OK);
+ }
+
+
+ /* Perform requested action */
+
+ switch (todo) {
+ case FS_QUOTA:
+ result = do_quota(cli,SMB_USER_FS_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
+ break;
+ case LIST_QUOTA:
+ result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_LIST, username_str, NULL);
+ break;
+ case USER_QUOTA:
+ result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
+ break;
+ case SET_QUOTA:
+ result = do_quota(cli, qtype, cmd, username_str, &qt);
+ break;
+ default:
+
+ result = EXIT_FAILED;
+ break;
+ }
+
+ return result;
+}
+