summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn Import User <samba-bugs@samba.org>2003-10-09 20:59:39 +0000
committercvs2svn Import User <samba-bugs@samba.org>2003-10-09 20:59:39 +0000
commit57e99bfb967ce068308d70cf08ec11598ea9750c (patch)
treeb43aeddcdad083cf88244135d5ca4b10d58120f3
parent9e6ee436d798556c560f375396049944b684c8ab (diff)
parentcd3e4882fcf2437f4140557608e671284d0e92b4 (diff)
downloadsamba-57e99bfb967ce068308d70cf08ec11598ea9750c.tar.gz
This commit was manufactured by cvs2svn to create branch
'SAMBA_3_0_RELEASE'.
-rw-r--r--source/lib/privileges.c345
-rw-r--r--source/lib/secace.c285
-rw-r--r--source/lib/secacl.c118
-rw-r--r--source/lib/secdesc.c522
-rwxr-xr-xsource/po/genmsg40
-rw-r--r--source/po/nl.msg593
-rw-r--r--source/tests/sysquotas.c94
7 files changed, 1997 insertions, 0 deletions
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
new file mode 100644
index 00000000000..1c23d9e40e5
--- /dev/null
+++ b/source/lib/privileges.c
@@ -0,0 +1,345 @@
+/*
+ Unix SMB/CIFS implementation.
+ Privileges handling functions
+ Copyright (C) Jean François Micouleau 1998-2001
+ Copyright (C) Simo Sorce 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"
+
+/* defines */
+
+#define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0)
+#define NTSTATUS_CHECK(err, label, str1, str2) do { if (!NT_STATUS_IS_OK(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0)
+
+/****************************************************************************
+ Check if a user is a mapped group.
+
+ This function will check if the group SID is mapped onto a
+ system managed gid or onto a winbind manged sid.
+ In the first case it will be threated like a mapped group
+ and the backend should take the member list with a getgrgid
+ and ignore any user that have been possibly set into the group
+ object.
+
+ In the second case, the group is a fully SAM managed group
+ served back to the system through winbind. In this case the
+ members of a Local group are "unrolled" to cope with the fact
+ that unix cannot contain groups inside groups.
+ The backend MUST never call any getgr* / getpw* function or
+ loops with winbind may happen.
+ ****************************************************************************/
+
+#if 0
+NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid)
+{
+ NTSTATUS result;
+ gid_t id;
+
+ /* look if mapping exist, do not make idmap alloc an uid if SID is not found */
+ result = idmap_get_gid_from_sid(&id, sid, False);
+ if (NT_STATUS_IS_OK(result)) {
+ *mapped = gid_is_in_winbind_range(id);
+ } else {
+ *mapped = False;
+ }
+
+ return result;
+}
+#endif
+
+/****************************************************************************
+ duplicate alloc luid_attr
+ ****************************************************************************/
+NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la)
+{
+ NTSTATUS ret;
+
+ *new_la = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR));
+ ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr");
+
+ (*new_la)->luid.high = old_la->luid.high;
+ (*new_la)->luid.low = old_la->luid.low;
+ (*new_la)->attr = old_la->attr;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/****************************************************************************
+ initialise a privilege list
+ ****************************************************************************/
+NTSTATUS init_privilege(PRIVILEGE_SET **priv_set)
+{
+ NTSTATUS ret;
+ TALLOC_CTX *mem_ctx = talloc_init("privilege set");
+ ALLOC_CHECK(mem_ctx, ret, done, "init_privilege");
+
+ *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET));
+ ALLOC_CHECK(*priv_set, ret, done, "init_privilege");
+
+ (*priv_set)->mem_ctx = mem_ctx;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set)
+{
+ NTSTATUS ret;
+
+ *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET));
+ ALLOC_CHECK(*priv_set, ret, done, "init_privilege");
+
+ (*priv_set)->mem_ctx = mem_ctx;
+ (*priv_set)->ext_ctx = True;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+void reset_privilege(PRIVILEGE_SET *priv_set)
+{
+ priv_set->count = 0;
+ priv_set->control = 0;
+ priv_set->set = NULL;
+}
+
+void destroy_privilege(PRIVILEGE_SET **priv_set)
+{
+ reset_privilege(*priv_set);
+ if (!((*priv_set)->ext_ctx))
+ /* mem_ctx is local, destroy it */
+ talloc_destroy((*priv_set)->mem_ctx);
+ *priv_set = NULL;
+}
+
+/****************************************************************************
+ add a privilege to a privilege array
+ ****************************************************************************/
+NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+{
+ NTSTATUS ret;
+ LUID_ATTR *new_set;
+
+ /* check if the privilege is not already in the list */
+ if (NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ /* we can allocate memory to add the new privilege */
+
+ new_set = (LUID_ATTR *)talloc_realloc(priv_set->mem_ctx, priv_set->set, (priv_set->count + 1) * (sizeof(LUID_ATTR)));
+ ALLOC_CHECK(new_set, ret, done, "add_privilege");
+
+ new_set[priv_set->count].luid.high = set.luid.high;
+ new_set[priv_set->count].luid.low = set.luid.low;
+ new_set[priv_set->count].attr = set.attr;
+
+ priv_set->count++;
+ priv_set->set = new_set;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/****************************************************************************
+ add all the privileges to a privilege array
+ ****************************************************************************/
+NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set)
+{
+ NTSTATUS result = NT_STATUS_OK;
+ LUID_ATTR set;
+
+ set.attr = 0;
+ set.luid.high = 0;
+
+ /* TODO: set a proper list of privileges */
+ set.luid.low = SE_PRIV_ADD_USERS;
+ result = add_privilege(priv_set, set);
+ NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege");
+
+ set.luid.low = SE_PRIV_ADD_MACHINES;
+ result = add_privilege(priv_set, set);
+ NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege");
+
+ set.luid.low = SE_PRIV_PRINT_OPERATOR;
+ result = add_privilege(priv_set, set);
+ NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege");
+
+done:
+ return result;
+}
+
+/****************************************************************************
+ check if the privilege list is empty
+ ****************************************************************************/
+NTSTATUS check_empty_privilege(PRIVILEGE_SET *priv_set)
+{
+ if (!priv_set)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if (priv_set->count == 0)
+ return NT_STATUS_OK;
+
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+/****************************************************************************
+ check if the privilege is in the privilege list
+ ****************************************************************************/
+NTSTATUS check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+{
+ int i;
+
+ if (!priv_set)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ /* if the list is empty, obviously we can't have it */
+ if (NT_STATUS_IS_OK(check_empty_privilege(priv_set)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ for (i = 0; i < priv_set->count; i++) {
+ LUID_ATTR *cur_set;
+
+ cur_set = &priv_set->set[i];
+ /* check only the low and high part. Checking the attr field has no meaning */
+ if ( (cur_set->luid.low == set.luid.low) &&
+ (cur_set->luid.high == set.luid.high) ) {
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+/****************************************************************************
+ remove a privilege from a privilege array
+ ****************************************************************************/
+NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+{
+ NTSTATUS ret;
+ LUID_ATTR *new_set;
+ LUID_ATTR *old_set;
+ int i,j;
+
+ if (!priv_set)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ /* check if the privilege is in the list */
+ if (!NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ /* special case if it's the only privilege in the list */
+ if (priv_set->count == 1) {
+ reset_privilege(priv_set);
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * the privilege is there, create a new list,
+ * and copy the other privileges
+ */
+
+ old_set = priv_set->set;
+
+ new_set = (LUID_ATTR *)talloc(priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR)));
+ ALLOC_CHECK(new_set, ret, done, "remove_privilege");
+
+ for (i=0, j=0; i < priv_set->count; i++) {
+ if ( (old_set[i].luid.low == set.luid.low) &&
+ (old_set[i].luid.high == set.luid.high) ) {
+ continue;
+ }
+
+ new_set[j].luid.low = old_set[i].luid.low;
+ new_set[j].luid.high = old_set[i].luid.high;
+ new_set[j].attr = old_set[i].attr;
+
+ j++;
+ }
+
+ if (j != priv_set->count - 1) {
+ DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n"));
+ DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ /* ok everything is fine */
+
+ priv_set->count--;
+ priv_set->set = new_set;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/****************************************************************************
+ duplicates a privilege array
+ the new privilege set must be passed inited
+ (use init_privilege or init_priv_with_ctx)
+ ****************************************************************************/
+NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set)
+{
+ NTSTATUS ret;
+ LUID_ATTR *new_set;
+ LUID_ATTR *old_set;
+ int i;
+
+ if (!new_priv_set || !priv_set)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ /* special case if there are no privileges in the list */
+ if (priv_set->count == 0) {
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * create a new list,
+ * and copy the other privileges
+ */
+
+ old_set = priv_set->set;
+
+ new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR)));
+ ALLOC_CHECK(new_set, ret, done, "dup_priv_set");
+
+ for (i=0; i < priv_set->count; i++) {
+
+ new_set[i].luid.low = old_set[i].luid.low;
+ new_set[i].luid.high = old_set[i].luid.high;
+ new_set[i].attr = old_set[i].attr;
+ }
+
+ new_priv_set->count = priv_set->count;
+ new_priv_set->control = priv_set->control;
+ new_priv_set->set = new_set;
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
diff --git a/source/lib/secace.c b/source/lib/secace.c
new file mode 100644
index 00000000000..6769f1288a2
--- /dev/null
+++ b/source/lib/secace.c
@@ -0,0 +1,285 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * SEC_ACE handling functions
+ * Copyright (C) Andrew Tridgell 1992-1998,
+ * Copyright (C) Jeremy R. Allison 1995-2003.
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
+ * Copyright (C) Paul Ashton 1997-1998.
+ *
+ * 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"
+
+/*******************************************************************
+ Check if ACE has OBJECT type.
+********************************************************************/
+
+BOOL sec_ace_object(uint8 type)
+{
+ if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
+ type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
+ return True;
+ }
+ return False;
+}
+
+/*******************************************************************
+ copy a SEC_ACE structure.
+********************************************************************/
+void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
+{
+ ace_dest->type = ace_src->type;
+ ace_dest->flags = ace_src->flags;
+ ace_dest->size = ace_src->size;
+ ace_dest->info.mask = ace_src->info.mask;
+ ace_dest->obj_flags = ace_src->obj_flags;
+ memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE);
+ memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE);
+ sid_copy(&ace_dest->trustee, &ace_src->trustee);
+}
+
+/*******************************************************************
+ Sets up a SEC_ACE structure.
+********************************************************************/
+
+void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
+{
+ t->type = type;
+ t->flags = flag;
+ t->size = sid_size(sid) + 8;
+ t->info = mask;
+
+ ZERO_STRUCTP(&t->trustee);
+ sid_copy(&t->trustee, sid);
+}
+
+/*******************************************************************
+ adds new SID with its permissions to ACE list
+********************************************************************/
+
+NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask)
+{
+ unsigned int i = 0;
+
+ if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER;
+
+ *num += 1;
+
+ if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0)
+ return NT_STATUS_NO_MEMORY;
+
+ for (i = 0; i < *num - 1; i ++)
+ sec_ace_copy(&(*new)[i], &old[i]);
+
+ (*new)[i].type = 0;
+ (*new)[i].flags = 0;
+ (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid);
+ (*new)[i].info.mask = mask;
+ sid_copy(&(*new)[i].trustee, sid);
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ modify SID's permissions at ACL
+********************************************************************/
+
+NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
+{
+ unsigned int i = 0;
+
+ if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER;
+
+ for (i = 0; i < num; i ++) {
+ if (sid_compare(&ace[i].trustee, sid) == 0) {
+ ace[i].info.mask = mask;
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_NOT_FOUND;
+}
+
+/*******************************************************************
+ delete SID from ACL
+********************************************************************/
+
+NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid)
+{
+ unsigned int i = 0;
+ unsigned int n_del = 0;
+
+ if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER;
+
+ if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0)
+ return NT_STATUS_NO_MEMORY;
+
+ for (i = 0; i < *num; i ++) {
+ if (sid_compare(&old[i].trustee, sid) != 0)
+ sec_ace_copy(&(*new)[i], &old[i]);
+ else
+ n_del ++;
+ }
+ if (n_del == 0)
+ return NT_STATUS_NOT_FOUND;
+ else {
+ *num -= n_del;
+ return NT_STATUS_OK;
+ }
+}
+
+/*******************************************************************
+ Compares two SEC_ACE structures
+********************************************************************/
+
+BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
+{
+ /* Trivial case */
+
+ if (!s1 && !s2) return True;
+
+ /* Check top level stuff */
+
+ if (s1->type != s2->type || s1->flags != s2->flags ||
+ s1->info.mask != s2->info.mask) {
+ return False;
+ }
+
+ /* Check SID */
+
+ if (!sid_equal(&s1->trustee, &s2->trustee)) {
+ return False;
+ }
+
+ return True;
+}
+
+int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
+ int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
+
+ if (a1_inh == a2_inh)
+ return 0;
+
+ if (!a1_inh && a2_inh)
+ return -1;
+ return 1;
+}
+
+/*******************************************************************
+ Comparison function to apply the order explained below in a group.
+*******************************************************************/
+
+int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return -1;
+
+ if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return 1;
+
+ /* Both access denied or access allowed. */
+
+ /* 1. ACEs that apply to the object itself */
+
+ if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return -1;
+ else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return 1;
+
+ /* 2. ACEs that apply to a subobject of the object, such as
+ * a property set or property. */
+
+ if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return -1;
+ else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return 1;
+
+ return 0;
+}
+
+/*******************************************************************
+ Functions to convert a SEC_DESC ACE DACL list into canonical order.
+ JRA.
+
+--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
+
+The following describes the preferred order:
+
+ To ensure that noninherited ACEs have precedence over inherited ACEs,
+ place all noninherited ACEs in a group before any inherited ACEs.
+ This ordering ensures, for example, that a noninherited access-denied ACE
+ is enforced regardless of any inherited ACE that allows access.
+
+ Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
+ 1. Access-denied ACEs that apply to the object itself
+ 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
+ 3. Access-allowed ACEs that apply to the object itself
+ 4. Access-allowed ACEs that apply to a subobject of the object"
+
+********************************************************************/
+
+void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
+{
+ unsigned int i;
+
+ if (!srclist || num_aces == 0)
+ return;
+
+ /* Sort so that non-inherited ACE's come first. */
+ qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
+
+ /* Find the boundary between non-inherited ACEs. */
+ for (i = 0; i < num_aces; i++ ) {
+ SEC_ACE *curr_ace = &srclist[i];
+
+ if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
+ break;
+ }
+
+ /* i now points at entry number of the first inherited ACE. */
+
+ /* Sort the non-inherited ACEs. */
+ if (i)
+ qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+
+ /* Now sort the inherited ACEs. */
+ if (num_aces - i)
+ qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+}
+
+/*******************************************************************
+ Check if this ACE has a SID in common with the token.
+********************************************************************/
+
+BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
+{
+ size_t i;
+
+ for (i = 0; i < token->num_sids; i++) {
+ if (sid_equal(&ace->trustee, &token->user_sids[i]))
+ return True;
+ }
+
+ return False;
+}
diff --git a/source/lib/secacl.c b/source/lib/secacl.c
new file mode 100644
index 00000000000..756685a8216
--- /dev/null
+++ b/source/lib/secacl.c
@@ -0,0 +1,118 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * SEC_ACL handling routines
+ * Copyright (C) Andrew Tridgell 1992-1998,
+ * Copyright (C) Jeremy R. Allison 1995-2003.
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
+ * Copyright (C) Paul Ashton 1997-1998.
+ *
+ * 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"
+
+/*******************************************************************
+ Create a SEC_ACL structure.
+********************************************************************/
+
+SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
+{
+ SEC_ACL *dst;
+ int i;
+
+ if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
+ return NULL;
+
+ dst->revision = revision;
+ dst->num_aces = num_aces;
+ dst->size = SEC_ACL_HEADER_SIZE;
+
+ /* Now we need to return a non-NULL address for the ace list even
+ if the number of aces required is zero. This is because there
+ is a distinct difference between a NULL ace and an ace with zero
+ entries in it. This is achieved by checking that num_aces is a
+ positive number. */
+
+ if ((num_aces) &&
+ ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces))
+ == NULL)) {
+ return NULL;
+ }
+
+ for (i = 0; i < num_aces; i++) {
+ dst->ace[i] = ace_list[i]; /* Structure copy. */
+ dst->size += ace_list[i].size;
+ }
+
+ return dst;
+}
+
+/*******************************************************************
+ Duplicate a SEC_ACL structure.
+********************************************************************/
+
+SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
+{
+ if(src == NULL)
+ return NULL;
+
+ return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
+}
+
+/*******************************************************************
+ Compares two SEC_ACL structures
+********************************************************************/
+
+BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
+{
+ unsigned int i, j;
+
+ /* Trivial cases */
+
+ if (!s1 && !s2) return True;
+ if (!s1 || !s2) return False;
+
+ /* Check top level stuff */
+
+ if (s1->revision != s2->revision) {
+ DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
+ s1->revision, s2->revision));
+ return False;
+ }
+
+ if (s1->num_aces != s2->num_aces) {
+ DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
+ s1->revision, s2->revision));
+ return False;
+ }
+
+ /* The ACEs could be in any order so check each ACE in s1 against
+ each ACE in s2. */
+
+ for (i = 0; i < s1->num_aces; i++) {
+ BOOL found = False;
+
+ for (j = 0; j < s2->num_aces; j++) {
+ if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
+ found = True;
+ break;
+ }
+ }
+
+ if (!found) return False;
+ }
+
+ return True;
+}
diff --git a/source/lib/secdesc.c b/source/lib/secdesc.c
new file mode 100644
index 00000000000..411185dbfa6
--- /dev/null
+++ b/source/lib/secdesc.c
@@ -0,0 +1,522 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * SEC_DESC handling functions
+ * Copyright (C) Andrew Tridgell 1992-1998,
+ * Copyright (C) Jeremy R. Allison 1995-2003.
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
+ * Copyright (C) Paul Ashton 1997-1998.
+ *
+ * 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"
+
+/*******************************************************************
+ Works out the linearization size of a SEC_DESC.
+********************************************************************/
+
+size_t sec_desc_size(SEC_DESC *psd)
+{
+ size_t offset;
+
+ if (!psd) return 0;
+
+ offset = SEC_DESC_HEADER_SIZE;
+
+ /* don't align */
+
+ if (psd->owner_sid != NULL)
+ offset += sid_size(psd->owner_sid);
+
+ if (psd->grp_sid != NULL)
+ offset += sid_size(psd->grp_sid);
+
+ if (psd->sacl != NULL)
+ offset += psd->sacl->size;
+
+ if (psd->dacl != NULL)
+ offset += psd->dacl->size;
+
+ return offset;
+}
+
+/*******************************************************************
+ Compares two SEC_DESC structures
+********************************************************************/
+
+BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
+{
+ /* Trivial case */
+
+ if (!s1 && !s2) {
+ goto done;
+ }
+
+ /* Check top level stuff */
+
+ if (s1->revision != s2->revision) {
+ DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
+ s1->revision, s2->revision));
+ return False;
+ }
+
+ if (s1->type!= s2->type) {
+ DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
+ s1->type, s2->type));
+ return False;
+ }
+
+ /* Check owner and group */
+
+ if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
+ fstring str1, str2;
+
+ sid_to_string(str1, s1->owner_sid);
+ sid_to_string(str2, s2->owner_sid);
+
+ DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
+ str1, str2));
+ return False;
+ }
+
+ if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
+ fstring str1, str2;
+
+ sid_to_string(str1, s1->grp_sid);
+ sid_to_string(str2, s2->grp_sid);
+
+ DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
+ str1, str2));
+ return False;
+ }
+
+ /* Check ACLs present in one but not the other */
+
+ if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
+ (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
+ DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
+ return False;
+ }
+
+ /* Sigh - we have to do it the hard way by iterating over all
+ the ACEs in the ACLs */
+
+ if (!sec_acl_equal(s1->dacl, s2->dacl) ||
+ !sec_acl_equal(s1->sacl, s2->sacl)) {
+ DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
+ return False;
+ }
+
+ done:
+ DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
+ return True;
+}
+
+/*******************************************************************
+ Merge part of security descriptor old_sec in to the empty sections of
+ security descriptor new_sec.
+********************************************************************/
+
+SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
+{
+ DOM_SID *owner_sid, *group_sid;
+ SEC_DESC_BUF *return_sdb;
+ SEC_ACL *dacl, *sacl;
+ SEC_DESC *psd = NULL;
+ uint16 secdesc_type;
+ size_t secdesc_size;
+
+ /* Copy over owner and group sids. There seems to be no flag for
+ this so just check the pointer values. */
+
+ owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
+ old_sdb->sec->owner_sid;
+
+ group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
+ old_sdb->sec->grp_sid;
+
+ secdesc_type = new_sdb->sec->type;
+
+ /* Ignore changes to the system ACL. This has the effect of making
+ changes through the security tab audit button not sticking.
+ Perhaps in future Samba could implement these settings somehow. */
+
+ sacl = NULL;
+ secdesc_type &= ~SEC_DESC_SACL_PRESENT;
+
+ /* Copy across discretionary ACL */
+
+ if (secdesc_type & SEC_DESC_DACL_PRESENT) {
+ dacl = new_sdb->sec->dacl;
+ } else {
+ dacl = old_sdb->sec->dacl;
+ }
+
+ /* Create new security descriptor from bits */
+
+ psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type,
+ owner_sid, group_sid, sacl, dacl, &secdesc_size);
+
+ return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
+
+ return(return_sdb);
+}
+
+/*******************************************************************
+ Creates a SEC_DESC structure
+********************************************************************/
+
+SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
+ DOM_SID *owner_sid, DOM_SID *grp_sid,
+ SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
+{
+ SEC_DESC *dst;
+ uint32 offset = 0;
+
+ *sd_size = 0;
+
+ if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
+ return NULL;
+
+ dst->revision = revision;
+ dst->type = type;
+
+ if (sacl)
+ dst->type |= SEC_DESC_SACL_PRESENT;
+ if (dacl)
+ dst->type |= SEC_DESC_DACL_PRESENT;
+
+ dst->off_owner_sid = 0;
+ dst->off_grp_sid = 0;
+ dst->off_sacl = 0;
+ dst->off_dacl = 0;
+
+ if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
+ goto error_exit;
+
+ if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
+ goto error_exit;
+
+ if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
+ goto error_exit;
+
+ if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
+ goto error_exit;
+
+ offset = SEC_DESC_HEADER_SIZE;
+
+ /*
+ * Work out the linearization sizes.
+ */
+
+ if (dst->sacl != NULL) {
+ dst->off_sacl = offset;
+ offset += dst->sacl->size;
+ }
+ if (dst->dacl != NULL) {
+ dst->off_dacl = offset;
+ offset += dst->dacl->size;
+ }
+
+ if (dst->owner_sid != NULL) {
+ dst->off_owner_sid = offset;
+ offset += sid_size(dst->owner_sid);
+ }
+
+ if (dst->grp_sid != NULL) {
+ dst->off_grp_sid = offset;
+ offset += sid_size(dst->grp_sid);
+ }
+
+ *sd_size = (size_t)offset;
+ return dst;
+
+error_exit:
+
+ *sd_size = 0;
+ return NULL;
+}
+
+/*******************************************************************
+ Duplicate a SEC_DESC structure.
+********************************************************************/
+
+SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
+{
+ size_t dummy;
+
+ if(src == NULL)
+ return NULL;
+
+ return make_sec_desc( ctx, src->revision, src->type,
+ src->owner_sid, src->grp_sid, src->sacl,
+ src->dacl, &dummy);
+}
+
+/*******************************************************************
+ Creates a SEC_DESC structure with typical defaults.
+********************************************************************/
+
+SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
+ SEC_ACL *dacl, size_t *sd_size)
+{
+ return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
+ owner_sid, grp_sid, NULL, dacl, sd_size);
+}
+
+/*******************************************************************
+ Creates a SEC_DESC_BUF structure.
+********************************************************************/
+
+SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
+{
+ SEC_DESC_BUF *dst;
+
+ if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
+ return NULL;
+
+ /* max buffer size (allocated size) */
+ dst->max_len = (uint32)len;
+ dst->len = (uint32)len;
+
+ if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
+ return NULL;
+ }
+
+ dst->ptr = 0x1;
+
+ return dst;
+}
+
+/*******************************************************************
+ Duplicates a SEC_DESC_BUF structure.
+********************************************************************/
+
+SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
+{
+ if(src == NULL)
+ return NULL;
+
+ return make_sec_desc_buf( ctx, src->len, src->sec);
+}
+
+/*******************************************************************
+ Add a new SID with its permissions to SEC_DESC.
+********************************************************************/
+
+NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
+{
+ SEC_DESC *sd = 0;
+ SEC_ACL *dacl = 0;
+ SEC_ACE *ace = 0;
+ NTSTATUS status;
+
+ *sd_size = 0;
+
+ if (!ctx || !psd || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
+
+ if (!NT_STATUS_IS_OK(status))
+ return status;
+
+ if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
+ psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ *psd = sd;
+ sd = 0;
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Modify a SID's permissions in a SEC_DESC.
+********************************************************************/
+
+NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
+{
+ NTSTATUS status;
+
+ if (!sd || !sid)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
+
+ if (!NT_STATUS_IS_OK(status))
+ return status;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Delete a SID from a SEC_DESC.
+********************************************************************/
+
+NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
+{
+ SEC_DESC *sd = 0;
+ SEC_ACL *dacl = 0;
+ SEC_ACE *ace = 0;
+ NTSTATUS status;
+
+ *sd_size = 0;
+
+ if (!ctx || !psd[0] || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
+
+ if (!NT_STATUS_IS_OK(status))
+ return status;
+
+ if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
+ psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ *psd = sd;
+ sd = 0;
+ return NT_STATUS_OK;
+}
+
+/* Create a child security descriptor using another security descriptor as
+ the parent container. This child object can either be a container or
+ non-container object. */
+
+SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
+ BOOL child_container)
+{
+ SEC_DESC_BUF *sdb;
+ SEC_DESC *sd;
+ SEC_ACL *new_dacl, *the_acl;
+ SEC_ACE *new_ace_list = NULL;
+ unsigned int new_ace_list_ndx = 0, i;
+ size_t size;
+
+ /* Currently we only process the dacl when creating the child. The
+ sacl should also be processed but this is left out as sacls are
+ not implemented in Samba at the moment.*/
+
+ the_acl = parent_ctr->dacl;
+
+ if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces)))
+ return NULL;
+
+ for (i = 0; the_acl && i < the_acl->num_aces; i++) {
+ SEC_ACE *ace = &the_acl->ace[i];
+ SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
+ uint8 new_flags = 0;
+ BOOL inherit = False;
+ fstring sid_str;
+
+ /* The OBJECT_INHERIT_ACE flag causes the ACE to be
+ inherited by non-container children objects. Container
+ children objects will inherit it as an INHERIT_ONLY
+ ACE. */
+
+ if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
+
+ if (!child_container) {
+ new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
+ } else {
+ new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+ }
+
+ inherit = True;
+ }
+
+ /* The CONAINER_INHERIT_ACE flag means all child container
+ objects will inherit and use the ACE. */
+
+ if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
+ if (!child_container) {
+ inherit = False;
+ } else {
+ new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
+ }
+ }
+
+ /* The INHERIT_ONLY_ACE is not used by the se_access_check()
+ function for the parent container, but is inherited by
+ all child objects as a normal ACE. */
+
+ if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
+ /* Move along, nothing to see here */
+ }
+
+ /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
+ is inherited by child objects but not grandchildren
+ objects. We clear the object inherit and container
+ inherit flags in the inherited ACE. */
+
+ if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+ new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
+ SEC_ACE_FLAG_CONTAINER_INHERIT);
+ }
+
+ /* Add ACE to ACE list */
+
+ if (!inherit)
+ continue;
+
+ init_sec_access(&new_ace->info, ace->info.mask);
+ init_sec_ace(new_ace, &ace->trustee, ace->type,
+ new_ace->info, new_flags);
+
+ sid_to_string(sid_str, &ace->trustee);
+
+ DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
+ " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
+ ace->type, ace->flags, ace->info.mask,
+ sid_str, new_ace->type, new_ace->flags,
+ new_ace->info.mask));
+
+ new_ace_list_ndx++;
+ }
+
+ /* Create child security descriptor to return */
+
+ new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
+
+ /* Use the existing user and group sids. I don't think this is
+ correct. Perhaps the user and group should be passed in as
+ parameters by the caller? */
+
+ sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
+ parent_ctr->owner_sid,
+ parent_ctr->grp_sid,
+ parent_ctr->sacl,
+ new_dacl, &size);
+
+ sdb = make_sec_desc_buf(ctx, size, sd);
+
+ return sdb;
+}
+
+/*******************************************************************
+ Sets up a SEC_ACCESS structure.
+********************************************************************/
+
+void init_sec_access(SEC_ACCESS *t, uint32 mask)
+{
+ t->mask = mask;
+}
+
diff --git a/source/po/genmsg b/source/po/genmsg
new file mode 100755
index 00000000000..08d5bd222f8
--- /dev/null
+++ b/source/po/genmsg
@@ -0,0 +1,40 @@
+#!/bin/sh
+# Copyright (C) 2003 TAKAHASHI Motonobu <monyo@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+FILES='../web/swat.c ../web/statuspage.c ../param/loadparm.c'
+LANGS='en ja tr pl fr de it'
+
+XGETTEXT=xgettext
+MSGMERGE=msgmerge
+
+WIDTH=256
+
+$XGETTEXT --default-domain="i18n_swat" \
+ --add-comments \
+ --keyword=_ --keyword=N_ \
+ --width=${WIDTH} \
+ $FILES
+
+for lang in $LANGS; do
+ echo -n $lang
+ mv ${lang}.msg ${lang}.msg.old
+ $MSGMERGE --width=${WIDTH} ${lang}.msg.old i18n_swat.po -o ${lang}.msg
+done
+
+rm i18n_swat.po
+
diff --git a/source/po/nl.msg b/source/po/nl.msg
new file mode 100644
index 00000000000..8d7b050ce90
--- /dev/null
+++ b/source/po/nl.msg
@@ -0,0 +1,593 @@
+# Dutch messages for international release of SWAT.
+# Copyright (C) 2003 Jelmer Vernooij <jelmer@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: i18n_swat \n"
+"POT-Creation-Date: 2003-10-06 05:30+0900\n"
+"PO-Revision-Date: 2000-02-08 12:48+09:00\n"
+"Last-Translator: Jelmer Vernooij <jelmer@samba.org>\n"
+"Language-Team: (Samba Team) <samba-technical@samba.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=US-ASCII\n"
+"Content-Transfer-Encoding: \n"
+
+#: ../web/swat.c:117
+#, c-format
+msgid "ERROR: Can't open %s"
+msgstr "FOUT: Kan %s niet openen"
+
+#: ../web/swat.c:200
+msgid "Help"
+msgstr "Help"
+
+#: ../web/swat.c:206 ../web/swat.c:220 ../web/swat.c:235 ../web/swat.c:243 ../web/swat.c:252 ../web/swat.c:261 ../web/swat.c:267 ../web/swat.c:273 ../web/swat.c:286
+msgid "Set Default"
+msgstr "Stel Standaard In"
+
+#: ../web/swat.c:408
+#, c-format
+msgid "failed to open %s for writing"
+msgstr "kon %s niet openen voor schrijven"
+
+#: ../web/swat.c:431
+#, c-format
+msgid "Can't reload %s"
+msgstr "Kan %s niet herladen"
+
+#: ../web/swat.c:501
+#, c-format
+msgid "Logged in as <b>%s</b>"
+msgstr "Ingelogd als <b>%s</b>"
+
+#: ../web/swat.c:505
+msgid "Home"
+msgstr "Home"
+
+#: ../web/swat.c:507
+msgid "Globals"
+msgstr "Algemene Instellingen"
+
+#: ../web/swat.c:508
+msgid "Shares"
+msgstr "Gedeelde Bronnen"
+
+#: ../web/swat.c:509
+msgid "Printers"
+msgstr "Printers"
+
+#: ../web/swat.c:510
+msgid "Wizard"
+msgstr "Wizard"
+
+#: ../web/swat.c:513
+msgid "Status"
+msgstr "Status"
+
+#: ../web/swat.c:514
+msgid "View Config"
+msgstr "Bekijk Configuratie"
+
+#: ../web/swat.c:516
+msgid "Password Management"
+msgstr "Wachtwoord Beheer"
+
+#: ../web/swat.c:526
+msgid "Current View Is"
+msgstr "Huidige weergave is"
+
+#: ../web/swat.c:527 ../web/swat.c:530
+msgid "Basic"
+msgstr "Basis"
+
+#: ../web/swat.c:528 ../web/swat.c:531
+msgid "Advanced"
+msgstr "Geadvanceerd"
+
+#: ../web/swat.c:529
+msgid "Change View To"
+msgstr "Verander Weergave In"
+
+#: ../web/swat.c:554
+msgid "Current Config"
+msgstr "Huidige Configuratie"
+
+#: ../web/swat.c:558
+msgid "Normal View"
+msgstr "Normale Weergave"
+
+#: ../web/swat.c:560
+msgid "Full View"
+msgstr "Volledige Weergave"
+
+#. Here we first set and commit all the parameters that were selected
+#. in the previous screen.
+#: ../web/swat.c:579
+msgid "Wizard Parameter Edit Page"
+msgstr "Wizard Instellingen Veranderen Pagina"
+
+#: ../web/swat.c:608
+msgid "Note: smb.conf file has been read and rewritten"
+msgstr "N.B.: het smb.conf bestand is gelezen en herschreven"
+
+#. Here we go ...
+#: ../web/swat.c:716
+msgid "Samba Configuration Wizard"
+msgstr "Samba Configuratie Wizard"
+
+#: ../web/swat.c:720
+msgid "The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."
+msgstr "De \"Herschrijf smb.conf bestand\" knop zal alle standaardwaardes en alle commentaar verwijderen."
+
+#: ../web/swat.c:721
+msgid "The same will happen if you press the commit button."
+msgstr "Hetzelfde zal gebeuren als u de \"toepassen\" knop gebruikt."
+
+#: ../web/swat.c:724
+msgid "Rewrite smb.conf file"
+msgstr "Herschrijf smb.conf bestand"
+
+#: ../web/swat.c:725
+msgid "Commit"
+msgstr "Toepassen"
+
+#: ../web/swat.c:726
+msgid "Edit Parameter Values"
+msgstr "Bewerk Configuratie Waardes"
+
+#: ../web/swat.c:732
+msgid "Server Type"
+msgstr "Server Type"
+
+#: ../web/swat.c:733
+msgid "Stand Alone"
+msgstr "Stand Alone"
+
+#: ../web/swat.c:734
+msgid "Domain Member"
+msgstr "Domein Lid"
+
+#: ../web/swat.c:735
+msgid "Domain Controller"
+msgstr "Domein Controller"
+
+#: ../web/swat.c:738
+msgid "Unusual Type in smb.conf - Please Select New Mode"
+msgstr "Ongebruikelijk Type in smb.conf - Selecteer een nieuwe modus"
+
+#: ../web/swat.c:740
+msgid "Configure WINS As"
+msgstr "Configureer WINS Als"
+
+#: ../web/swat.c:741
+msgid "Not Used"
+msgstr "Niet gebruikt"
+
+#: ../web/swat.c:742
+msgid "Server for client use"
+msgstr "Server voor client gebruik"
+
+#: ../web/swat.c:743
+msgid "Client of another WINS server"
+msgstr "Client van een andere WINS server"
+
+#: ../web/swat.c:745
+msgid "Remote WINS Server"
+msgstr "Naam of IP-adres WINS Server"
+
+#: ../web/swat.c:756
+msgid "Error: WINS Server Mode and WINS Support both set in smb.conf"
+msgstr "Fout: WINS Server Modus en WINS Ondersteuning beiden ingesteld in smb.conf"
+
+#: ../web/swat.c:757
+msgid "Please Select desired WINS mode above."
+msgstr "Selecteer hierboven de gewenste WINS modus."
+
+#: ../web/swat.c:759
+msgid "Expose Home Directories"
+msgstr "Stel Home Directories Open"
+
+#: ../web/swat.c:774
+msgid "The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."
+msgstr "The configuratie hierboven zal meerdere variabelen veranderen en zal over het algemeen zorgen voor snelle installatie van Samba."
+
+#: ../web/swat.c:787
+msgid "Global Parameters"
+msgstr "Algemene Instellingen"
+
+#: ../web/swat.c:815 ../web/swat.c:916 ../web/swat.c:1265
+msgid "Commit Changes"
+msgstr "Pas Veranderingen Toe"
+
+#: ../web/swat.c:819 ../web/swat.c:919 ../web/swat.c:1267
+msgid "Reset Values"
+msgstr "Beginwaarden"
+
+#: ../web/swat.c:844
+msgid "Share Parameters"
+msgstr "Instellingen Gedeelde Bronnen"
+
+#: ../web/swat.c:887
+msgid "Choose Share"
+msgstr "Kies Bron"
+
+#: ../web/swat.c:901
+msgid "Delete Share"
+msgstr "Verwijder Bron"
+
+#: ../web/swat.c:908
+msgid "Create Share"
+msgstr "Maak Bron"
+
+#: ../web/swat.c:944
+msgid "password change in demo mode rejected"
+msgstr "wachtwoord veranderen in demo modus geweigerd"
+
+#: ../web/swat.c:957
+msgid "Can't setup password database vectors."
+msgstr "Kan wachtwoord database vectors niet opzetten."
+
+#: ../web/swat.c:983
+msgid " Must specify \"User Name\" "
+msgstr " \"Gebruikersnaam\" moet opgegeven worden "
+
+#: ../web/swat.c:999
+msgid " Must specify \"Old Password\" "
+msgstr " \"Oude wachtwoord\" moet opgegeven worden "
+
+#: ../web/swat.c:1005
+msgid " Must specify \"Remote Machine\" "
+msgstr " \"Server Naam of IP\" moet opgegeven worden "
+
+#: ../web/swat.c:1012
+msgid " Must specify \"New, and Re-typed Passwords\" "
+msgstr " \"Nieuw, en bevestiging Wachtwoorden\" moeten opgegeven worden "
+
+#: ../web/swat.c:1018
+msgid " Re-typed password didn't match new password "
+msgstr " Bevestigingswachtwoord was anders dan nieuwe wachtwoord "
+
+#: ../web/swat.c:1048
+#, c-format
+msgid " The passwd for '%s' has been changed."
+msgstr " Het wachtwoord voor '%s' is veranderd."
+
+#: ../web/swat.c:1051
+#, c-format
+msgid " The passwd for '%s' has NOT been changed."
+msgstr " Het wachtwoord voor '%s' is niet veranderd."
+
+#: ../web/swat.c:1076
+msgid "Server Password Management"
+msgstr "Server Wachtwoord Beheer"
+
+#.
+#. * Create all the dialog boxes for data collection
+#.
+#: ../web/swat.c:1085 ../web/swat.c:1132
+msgid "User Name"
+msgstr "Gebuikersnaam"
+
+#: ../web/swat.c:1088 ../web/swat.c:1134
+msgid "Old Password"
+msgstr "Oud Wachtwoord"
+
+#: ../web/swat.c:1091 ../web/swat.c:1136
+msgid "New Password"
+msgstr "Nieuw Wachtwoord"
+
+#: ../web/swat.c:1093 ../web/swat.c:1138
+msgid "Re-type New Password"
+msgstr "Bevestiging Nieuw Wachtwoord"
+
+#: ../web/swat.c:1101 ../web/swat.c:1149
+msgid "Change Password"
+msgstr "Verander Wachtwoord"
+
+#: ../web/swat.c:1104
+msgid "Add New User"
+msgstr "Voeg Gebruiker Toe"
+
+#: ../web/swat.c:1106
+msgid "Delete User"
+msgstr "Verwijder Gebruiker"
+
+#: ../web/swat.c:1108
+msgid "Disable User"
+msgstr "Maak gebruiker inactief"
+
+#: ../web/swat.c:1110
+msgid "Enable User"
+msgstr "Maak gebruiker actief"
+
+#: ../web/swat.c:1123
+msgid "Client/Server Password Management"
+msgstr "Client/Server Wachtwoord Beheer"
+
+#: ../web/swat.c:1140
+msgid "Remote Machine"
+msgstr "Naam of IP Server"
+
+#: ../web/swat.c:1179
+msgid "Printer Parameters"
+msgstr "Printer Instellingen"
+
+#: ../web/swat.c:1181
+msgid "Important Note:"
+msgstr "Belangrijk:"
+
+#: ../web/swat.c:1182
+msgid "Printer names marked with [*] in the Choose Printer drop-down box "
+msgstr "Printer namen gemarkeerd met [*] in het Kies Printer veld "
+
+#: ../web/swat.c:1183
+msgid "are autoloaded printers from "
+msgstr "zijn automatisch geladen uit "
+
+#: ../web/swat.c:1184
+msgid "Printcap Name"
+msgstr "Printcap Naam"
+
+#: ../web/swat.c:1185
+msgid "Attempting to delete these printers from SWAT will have no effect."
+msgstr "Proberen deze printers te verwijderen vanuit SWAT zal geen effect hebben."
+
+#: ../web/swat.c:1231
+msgid "Choose Printer"
+msgstr "Kies Printer"
+
+#: ../web/swat.c:1250
+msgid "Delete Printer"
+msgstr "Verwijder Printer"
+
+#: ../web/swat.c:1257
+msgid "Create Printer"
+msgstr "Maak Printer"
+
+#: ../web/statuspage.c:123
+msgid "RDONLY "
+msgstr "RDONLY"
+
+#: ../web/statuspage.c:124
+msgid "WRONLY "
+msgstr "WRONLY"
+
+#: ../web/statuspage.c:125
+msgid "RDWR "
+msgstr "RDWR"
+
+#: ../web/statuspage.c:309
+msgid "Server Status"
+msgstr "Server Status"
+
+#: ../web/statuspage.c:314
+msgid "Auto Refresh"
+msgstr "Automatisch Verversen"
+
+#: ../web/statuspage.c:315 ../web/statuspage.c:320
+msgid "Refresh Interval: "
+msgstr "Ververs Interval:"
+
+#: ../web/statuspage.c:319
+msgid "Stop Refreshing"
+msgstr "Stop met Verversen"
+
+#: ../web/statuspage.c:334
+msgid "version:"
+msgstr "versie:"
+
+#: ../web/statuspage.c:337
+msgid "smbd:"
+msgstr "smbd:"
+
+#: ../web/statuspage.c:337 ../web/statuspage.c:350 ../web/statuspage.c:364
+msgid "running"
+msgstr "draaiend"
+
+#: ../web/statuspage.c:337 ../web/statuspage.c:350 ../web/statuspage.c:364
+msgid "not running"
+msgstr "niet draaiend"
+
+#: ../web/statuspage.c:341
+msgid "Stop smbd"
+msgstr "Stop smbd"
+
+#: ../web/statuspage.c:343
+msgid "Start smbd"
+msgstr "Start smbd"
+
+#: ../web/statuspage.c:345
+msgid "Restart smbd"
+msgstr "Herstart smbd"
+
+#: ../web/statuspage.c:350
+msgid "nmbd:"
+msgstr "nmbd:"
+
+#: ../web/statuspage.c:354
+msgid "Stop nmbd"
+msgstr "Stop nmbd"
+
+#: ../web/statuspage.c:356
+msgid "Start nmbd"
+msgstr "Start nmbd"
+
+#: ../web/statuspage.c:358
+msgid "Restart nmbd"
+msgstr "Herstart nmbd"
+
+#: ../web/statuspage.c:364
+msgid "winbindd:"
+msgstr "winbindd:"
+
+#: ../web/statuspage.c:368
+msgid "Stop winbindd"
+msgstr "Stop winbindd"
+
+#: ../web/statuspage.c:370
+msgid "Start winbindd"
+msgstr "Start winbindd"
+
+#: ../web/statuspage.c:372
+msgid "Restart winbindd"
+msgstr "Herstart winbindd"
+
+#. stop, restart all
+#: ../web/statuspage.c:381
+msgid "Stop All"
+msgstr "Stop Alles"
+
+#: ../web/statuspage.c:382
+msgid "Restart All"
+msgstr "Herstart Alles"
+
+#. start all
+#: ../web/statuspage.c:386
+msgid "Start All"
+msgstr "Start Alles"
+
+#: ../web/statuspage.c:393
+msgid "Active Connections"
+msgstr "Actieve Verbindingen"
+
+#: ../web/statuspage.c:395 ../web/statuspage.c:408 ../web/statuspage.c:416
+msgid "PID"
+msgstr "PID"
+
+#: ../web/statuspage.c:395 ../web/statuspage.c:408
+msgid "Client"
+msgstr "Client"
+
+#: ../web/statuspage.c:395
+msgid "IP address"
+msgstr "IP adres"
+
+#: ../web/statuspage.c:395 ../web/statuspage.c:408 ../web/statuspage.c:416
+msgid "Date"
+msgstr "Datum"
+
+#: ../web/statuspage.c:397
+msgid "Kill"
+msgstr "Kill"
+
+#: ../web/statuspage.c:405
+msgid "Active Shares"
+msgstr "Actieve Bronnen"
+
+#: ../web/statuspage.c:408
+msgid "Share"
+msgstr "Bron"
+
+#: ../web/statuspage.c:408
+msgid "User"
+msgstr "Gebruiker"
+
+#: ../web/statuspage.c:408
+msgid "Group"
+msgstr "Groep"
+
+#: ../web/statuspage.c:414
+msgid "Open Files"
+msgstr "Geopende Bestanden"
+
+#: ../web/statuspage.c:416
+msgid "Sharing"
+msgstr "Gedeeld"
+
+#: ../web/statuspage.c:416
+msgid "R/W"
+msgstr "Lees/Schrijf"
+
+#: ../web/statuspage.c:416
+msgid "Oplock"
+msgstr "Oplock"
+
+#: ../web/statuspage.c:416
+msgid "File"
+msgstr "Bestand"
+
+#: ../web/statuspage.c:425
+msgid "Show Client in col 1"
+msgstr "Toon Client in kolom 1"
+
+#: ../web/statuspage.c:426
+msgid "Show PID in col 1"
+msgstr "Toon PID in kolom 1"
+
+#: ../param/loadparm.c:755
+msgid "Base Options"
+msgstr "Basis Opties"
+
+#: ../param/loadparm.c:775
+msgid "Security Options"
+msgstr "Veiligheidsopties"
+
+#: ../param/loadparm.c:859
+msgid "Logging Options"
+msgstr "Log Opties"
+
+#: ../param/loadparm.c:874
+msgid "Protocol Options"
+msgstr "Protocol Opties"
+
+#: ../param/loadparm.c:911
+msgid "Tuning Options"
+msgstr "Fijntune Opties"
+
+#: ../param/loadparm.c:940
+msgid "Printing Options"
+msgstr "Printer Opties"
+
+#: ../param/loadparm.c:970
+msgid "Filename Handling"
+msgstr "Bestandsnaam Afhandeling"
+
+#: ../param/loadparm.c:996
+msgid "Domain Options"
+msgstr "Domein Opties"
+
+#: ../param/loadparm.c:1000
+msgid "Logon Options"
+msgstr "Logon Opties"
+
+#: ../param/loadparm.c:1019
+msgid "Browse Options"
+msgstr "Verken Opties"
+
+#: ../param/loadparm.c:1033
+msgid "WINS Options"
+msgstr "WINS Opties"
+
+#: ../param/loadparm.c:1043
+msgid "Locking Options"
+msgstr "Locking Opties"
+
+#: ../param/loadparm.c:1061
+msgid "Ldap Options"
+msgstr "LDAP Opties"
+
+#: ../param/loadparm.c:1078
+msgid "Miscellaneous Options"
+msgstr "Verscheidene Opties"
+
+#: ../param/loadparm.c:1138
+msgid "VFS module options"
+msgstr "VFS module opties"
+
+#: ../param/loadparm.c:1148
+msgid "Winbind options"
+msgstr "Winbind opties"
diff --git a/source/tests/sysquotas.c b/source/tests/sysquotas.c
new file mode 100644
index 00000000000..e83f28e2d0b
--- /dev/null
+++ b/source/tests/sysquotas.c
@@ -0,0 +1,94 @@
+/* this test should find out what quota api is avalable on the os */
+
+#if defined(HAVE_QUOTACTL_4A)
+/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#if defined(HAVE_LINUX_QUOTA_H)
+# include <linux/quota.h>
+# if defined(HAVE_STRUCT_IF_DQBLK)
+# define SYS_DQBLK if_dqblk
+# elif defined(HAVE_STRUCT_MEM_DQBLK)
+# define SYS_DQBLK mem_dqblk
+# endif
+#elif defined(HAVE_SYS_QUOTA_H)
+# include <sys/quota.h>
+#endif
+
+#ifndef SYS_DQBLK
+#define SYS_DQBLK dqblk
+#endif
+
+ int autoconf_quota(void)
+{
+ int ret = -1;
+ struct SYS_DQBLK D;
+
+ ret = quotactl(Q_GETQUOTA,"/dev/hda1",0,(void *)&D);
+
+ return ret;
+}
+
+#elif defined(HAVE_QUOTACTL_4B)
+/* int quotactl(const char *path, int cmd, int id, char *addr); */
+
+#ifdef HAVE_SYS_QUOTA_H
+#include <sys/quota.h>
+#else /* *BSD */
+#include <sys/types.h>
+#include <ufs/ufs/quota.h>
+#include <machine/param.h>
+#endif
+
+ int autoconf_quota(void)
+{
+ int ret = -1;
+ struct dqblk D;
+
+ ret = quotactl("/",Q_GETQUOTA,0,(char *) &D);
+
+ return ret;
+}
+
+#elif defined(HAVE_QUOTACTL_3)
+/* int quotactl (char *spec, int request, char *arg); */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_QUOTA_H
+#include <sys/quota.h>
+#endif
+
+ int autoconf_quota(void)
+{
+ int ret = -1;
+ struct q_request request;
+
+ ret = quotactl("/", Q_GETQUOTA, &request);
+
+ return ret;
+}
+
+#elif defined(HAVE_QUOTACTL_2)
+
+#error HAVE_QUOTACTL_2 not implemented
+
+#else
+
+#error Unknow QUOTACTL prototype
+
+#endif
+
+ int main(void)
+{
+ autoconf_quota();
+ return 0;
+}