diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/account_pol.c | 148 | ||||
-rw-r--r-- | source3/lib/ads_flags.c | 150 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 8 | ||||
-rw-r--r-- | source3/lib/ctdbd_conn.c | 2 | ||||
-rw-r--r-- | source3/lib/dbwrap_tdb.c | 2 | ||||
-rw-r--r-- | source3/lib/dbwrap_util.c | 173 | ||||
-rw-r--r-- | source3/lib/errmap_unix.c | 1 | ||||
-rw-r--r-- | source3/lib/events.c | 2 | ||||
-rw-r--r-- | source3/lib/gencache.c | 529 | ||||
-rw-r--r-- | source3/lib/ldap_escape.c | 25 | ||||
-rw-r--r-- | source3/lib/netapi/netapi.c | 1 | ||||
-rw-r--r-- | source3/lib/netapi/user.c | 2 | ||||
-rw-r--r-- | source3/lib/smbldap_util.c | 12 | ||||
-rw-r--r-- | source3/lib/system.c | 4 | ||||
-rw-r--r-- | source3/lib/tldap.c | 6 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 3 | ||||
-rw-r--r-- | source3/lib/util_str.c | 36 | ||||
-rw-r--r-- | source3/lib/util_tdb.c | 19 |
18 files changed, 604 insertions, 519 deletions
diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index 1e435ca53e..f4101e96bc 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -1,20 +1,20 @@ -/* +/* * Unix SMB/CIFS implementation. * account policy storage * Copyright (C) Jean François Micouleau 1998-2001. * Copyright (C) Andrew Bartlett 2002 * Copyright (C) Guenther Deschner 2004-2005 - * + * * 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 3 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, see <http://www.gnu.org/licenses/>. */ @@ -31,7 +31,7 @@ static struct db_context *db; struct ap_table { - int field; + enum pdb_policy_type type; const char *string; uint32 default_val; const char *description; @@ -39,51 +39,51 @@ struct ap_table { }; static const struct ap_table account_policy_names[] = { - {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, - "Minimal password length (default: 5)", + {PDB_POLICY_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, + "Minimal password length (default: 5)", "sambaMinPwdLength" }, - {AP_PASSWORD_HISTORY, "password history", 0, - "Length of Password History Entries (default: 0 => off)", + {PDB_POLICY_PASSWORD_HISTORY, "password history", 0, + "Length of Password History Entries (default: 0 => off)", "sambaPwdHistoryLength" }, - - {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, + + {PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, "Force Users to logon for password change (default: 0 => off, 2 => on)", "sambaLogonToChgPwd" }, - - {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1, - "Maximum password age, in seconds (default: -1 => never expire passwords)", + + {PDB_POLICY_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1, + "Maximum password age, in seconds (default: -1 => never expire passwords)", "sambaMaxPwdAge" }, - - {AP_MIN_PASSWORD_AGE,"minimum password age", 0, - "Minimal password age, in seconds (default: 0 => allow immediate password change)", + + {PDB_POLICY_MIN_PASSWORD_AGE,"minimum password age", 0, + "Minimal password age, in seconds (default: 0 => allow immediate password change)", "sambaMinPwdAge" }, - - {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30, + + {PDB_POLICY_LOCK_ACCOUNT_DURATION, "lockout duration", 30, "Lockout duration in minutes (default: 30, -1 => forever)", "sambaLockoutDuration" }, - - {AP_RESET_COUNT_TIME, "reset count minutes", 30, - "Reset time after lockout in minutes (default: 30)", + + {PDB_POLICY_RESET_COUNT_TIME, "reset count minutes", 30, + "Reset time after lockout in minutes (default: 30)", "sambaLockoutObservationWindow" }, - - {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, - "Lockout users after bad logon attempts (default: 0 => off)", + + {PDB_POLICY_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, + "Lockout users after bad logon attempts (default: 0 => off)", "sambaLockoutThreshold" }, - - {AP_TIME_TO_LOGOUT, "disconnect time", (uint32) -1, - "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", - "sambaForceLogoff" }, - - {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0, + + {PDB_POLICY_TIME_TO_LOGOUT, "disconnect time", (uint32) -1, + "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", + "sambaForceLogoff" }, + + {PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0, "Allow Machine Password changes (default: 0 => off)", "sambaRefuseMachinePwdChange" }, - + {0, NULL, 0, "", NULL} }; void account_policy_names_list(const char ***names, int *num_names) -{ +{ const char **nl; int i, count; @@ -106,11 +106,11 @@ void account_policy_names_list(const char ***names, int *num_names) Get the account policy name as a string from its #define'ed number ****************************************************************************/ -const char *decode_account_policy_name(int field) +const char *decode_account_policy_name(enum pdb_policy_type type) { int i; for (i=0; account_policy_names[i].string; i++) { - if (field == account_policy_names[i].field) { + if (type == account_policy_names[i].type) { return account_policy_names[i].string; } } @@ -121,11 +121,11 @@ const char *decode_account_policy_name(int field) Get the account policy LDAP attribute as a string from its #define'ed number ****************************************************************************/ -const char *get_account_policy_attr(int field) +const char *get_account_policy_attr(enum pdb_policy_type type) { int i; - for (i=0; account_policy_names[i].field; i++) { - if (field == account_policy_names[i].field) { + for (i=0; account_policy_names[i].type; i++) { + if (type == account_policy_names[i].type) { return account_policy_names[i].ldap_attr; } } @@ -136,11 +136,11 @@ const char *get_account_policy_attr(int field) Get the account policy description as a string from its #define'ed number ****************************************************************************/ -const char *account_policy_get_desc(int field) +const char *account_policy_get_desc(enum pdb_policy_type type) { int i; for (i=0; account_policy_names[i].string; i++) { - if (field == account_policy_names[i].field) { + if (type == account_policy_names[i].type) { return account_policy_names[i].description; } } @@ -151,12 +151,12 @@ const char *account_policy_get_desc(int field) Get the account policy name as a string from its #define'ed number ****************************************************************************/ -int account_policy_name_to_fieldnum(const char *name) +enum pdb_policy_type account_policy_name_to_typenum(const char *name) { int i; for (i=0; account_policy_names[i].string; i++) { if (strcmp(name, account_policy_names[i].string) == 0) { - return account_policy_names[i].field; + return account_policy_names[i].type; } } return 0; @@ -166,35 +166,35 @@ int account_policy_name_to_fieldnum(const char *name) Get default value for account policy *****************************************************************************/ -bool account_policy_get_default(int account_policy, uint32 *val) +bool account_policy_get_default(enum pdb_policy_type type, uint32_t *val) { int i; - for (i=0; account_policy_names[i].field; i++) { - if (account_policy_names[i].field == account_policy) { + for (i=0; account_policy_names[i].type; i++) { + if (account_policy_names[i].type == type) { *val = account_policy_names[i].default_val; return True; } } - DEBUG(0,("no default for account_policy index %d found. This should never happen\n", - account_policy)); + DEBUG(0,("no default for account_policy index %d found. This should never happen\n", + type)); return False; } /***************************************************************************** - Set default for a field if it is empty + Set default for a type if it is empty *****************************************************************************/ -static bool account_policy_set_default_on_empty(int account_policy) +static bool account_policy_set_default_on_empty(enum pdb_policy_type type) { uint32 value; - if (!account_policy_get(account_policy, &value) && - !account_policy_get_default(account_policy, &value)) { + if (!account_policy_get(type, &value) && + !account_policy_get_default(type, &value)) { return False; } - return account_policy_set(account_policy, value); + return account_policy_set(type, value); } /***************************************************************************** @@ -255,9 +255,9 @@ bool init_account_policy(void) goto cancel; } - for (i=0; account_policy_names[i].field; i++) { + for (i=0; account_policy_names[i].type; i++) { - if (!account_policy_set_default_on_empty(account_policy_names[i].field)) { + if (!account_policy_set_default_on_empty(account_policy_names[i].type)) { DEBUG(0,("failed to set default value in account policy tdb\n")); goto cancel; } @@ -299,10 +299,10 @@ bool init_account_policy(void) } /***************************************************************************** -Get an account policy (from tdb) +Get an account policy (from tdb) *****************************************************************************/ -bool account_policy_get(int field, uint32 *value) +bool account_policy_get(enum pdb_policy_type type, uint32_t *value) { const char *name; uint32 regval; @@ -315,17 +315,17 @@ bool account_policy_get(int field, uint32 *value) *value = 0; } - name = decode_account_policy_name(field); + name = decode_account_policy_name(type); if (name == NULL) { - DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); + DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", type)); return False; } - + if (!dbwrap_fetch_uint32(db, name, ®val)) { - DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, name)); + DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for type %d (%s), returning 0\n", type, name)); return False; } - + if (value) { *value = regval; } @@ -336,10 +336,10 @@ bool account_policy_get(int field, uint32 *value) /**************************************************************************** -Set an account policy (in tdb) +Set an account policy (in tdb) ****************************************************************************/ -bool account_policy_set(int field, uint32 value) +bool account_policy_set(enum pdb_policy_type type, uint32_t value) { const char *name; NTSTATUS status; @@ -348,36 +348,36 @@ bool account_policy_set(int field, uint32 value) return False; } - name = decode_account_policy_name(field); + name = decode_account_policy_name(type); if (name == NULL) { - DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field)); + DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", type)); return False; } status = dbwrap_trans_store_uint32(db, name, value); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("store_uint32 failed for field %d (%s) on value " - "%u: %s\n", field, name, value, nt_errstr(status))); + DEBUG(1, ("store_uint32 failed for type %d (%s) on value " + "%u: %s\n", type, name, value, nt_errstr(status))); return False; } DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value)); - + return True; } /**************************************************************************** -Set an account policy in the cache +Set an account policy in the cache ****************************************************************************/ -bool cache_account_policy_set(int field, uint32 value) +bool cache_account_policy_set(enum pdb_policy_type type, uint32_t value) { const char *policy_name = NULL; char *cache_key = NULL; char *cache_value = NULL; bool ret = False; - policy_name = decode_account_policy_name(field); + policy_name = decode_account_policy_name(type); if (policy_name == NULL) { DEBUG(0,("cache_account_policy_set: no policy found\n")); return False; @@ -404,17 +404,17 @@ bool cache_account_policy_set(int field, uint32 value) } /***************************************************************************** -Get an account policy from the cache +Get an account policy from the cache *****************************************************************************/ -bool cache_account_policy_get(int field, uint32 *value) +bool cache_account_policy_get(enum pdb_policy_type type, uint32_t *value) { const char *policy_name = NULL; char *cache_key = NULL; char *cache_value = NULL; bool ret = False; - policy_name = decode_account_policy_name(field); + policy_name = decode_account_policy_name(type); if (policy_name == NULL) { DEBUG(0,("cache_account_policy_set: no policy found\n")); return False; diff --git a/source3/lib/ads_flags.c b/source3/lib/ads_flags.c deleted file mode 100644 index a8fa062f2a..0000000000 --- a/source3/lib/ads_flags.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Unix SMB/CIFS implementation. - ads (active directory) utility library - - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Andrew Tridgell 2001 - - 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 3 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, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* -translated the ACB_CTRL Flags to UserFlags (userAccountControl) -*/ -uint32 ads_acb2uf(uint32 acb) -{ - uint32 uf = 0x00000000; - - if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE; - if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED; - if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD; - if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT; - if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT; - if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT; - if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT; - if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT; - if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT; - if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD; - if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT; - if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY; - if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED; - if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION; - if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH; - if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED; - if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED; - if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED; - - return uf; -} - -/* -translated the UserFlags (userAccountControl) to ACB_CTRL Flags -*/ -uint32 ads_uf2acb(uint32 uf) -{ - uint32 acb = 0x00000000; - - if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED; - if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ; - if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ; - if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS; - if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP; - if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK; - if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY; - if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED; - if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION; - if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH; - if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD; - if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED; - if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED; - - switch (uf & UF_ACCOUNT_TYPE_MASK) - { - case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break; - case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break; - case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break; - case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break; - case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break; - /*Fix Me: what should we do here? */ - default: acb |= ACB_NORMAL;break; - } - - return acb; -} - -/* -get the accountType from the UserFlags -*/ -uint32 ads_uf2atype(uint32 uf) -{ - uint32 atype = 0x00000000; - - if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST; - - return atype; -} - -/* -get the accountType from the groupType -*/ -uint32 ads_gtype2atype(uint32 gtype) -{ - uint32 atype = 0x00000000; - - switch(gtype) { - case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_GLOBAL_GROUP: - atype = ATYPE_SECURITY_GLOBAL_GROUP; - break; - - case GTYPE_DISTRIBUTION_GLOBAL_GROUP: - atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP; - break; - case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP: - atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP; - break; - case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP: - atype = ATYPE_DISTRIBUTION_LOCAL_GROUP; - break; - } - - return atype; -} - -/* turn a sAMAccountType into a SID_NAME_USE */ -enum lsa_SidType ads_atype_map(uint32 atype) -{ - switch (atype & 0xF0000000) { - case ATYPE_GLOBAL_GROUP: - return SID_NAME_DOM_GRP; - case ATYPE_SECURITY_LOCAL_GROUP: - return SID_NAME_ALIAS; - case ATYPE_ACCOUNT: - return SID_NAME_USER; - default: - DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); - } - return SID_NAME_UNKNOWN; -} diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index a1663c1f38..272f107138 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -753,7 +753,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - if (!push_ucs2_talloc(NULL, &buffer, src, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) { return (size_t)-1; } @@ -837,7 +837,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer = NULL; - if (!convert_string_talloc(NULL, CH_UNIX, CH_UTF16LE, src, srclen, + if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen, (void **)(void *)&buffer, &size, True)) { @@ -951,7 +951,7 @@ size_t push_ascii_nstring(void *dest, const char *src) smb_ucs2_t *buffer; conv_silent = True; - if (!push_ucs2_talloc(NULL, &buffer, src, &buffer_len)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &buffer_len)) { smb_panic("failed to create UCS2 buffer"); } @@ -1268,7 +1268,7 @@ static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) } if (flags & STR_UPPER) { - tmpbuf = strupper_talloc(NULL, src); + tmpbuf = strupper_talloc(talloc_tos(), src); if (!tmpbuf) { return (size_t)-1; } diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index dde377581b..449e049ffa 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -358,7 +358,7 @@ static NTSTATUS ctdb_read_req(struct ctdbd_connection *conn, uint32 reqid, goto next_pkt; } - if (!(msg_state = TALLOC_P(NULL, struct deferred_msg_state))) { + if (!(msg_state = TALLOC_P(talloc_autofree_context(), struct deferred_msg_state))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(hdr); goto next_pkt; diff --git a/source3/lib/dbwrap_tdb.c b/source3/lib/dbwrap_tdb.c index c71e073b41..297a351764 100644 --- a/source3/lib/dbwrap_tdb.c +++ b/source3/lib/dbwrap_tdb.c @@ -94,7 +94,7 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db, /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */ if(DEBUGLEVEL >= 10) { - char *keystr = hex_encode_talloc(NULL, (unsigned char*)key.dptr, key.dsize); + char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize); DEBUG(10, (DEBUGLEVEL > 10 ? "Locking key %s\n" : "Locking key %.20s\n", keystr)); diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c index 3be3a49e7d..c3ab93c4df 100644 --- a/source3/lib/dbwrap_util.c +++ b/source3/lib/dbwrap_util.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Utility functions for the dbwrap API Copyright (C) Volker Lendecke 2007 + Copyright (C) Michael Adam 2009 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 @@ -178,96 +179,77 @@ int32 dbwrap_change_int32_atomic(struct db_context *db, const char *keystr, return 0; } -NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf, - int flag) +struct dbwrap_store_context { + TDB_DATA *key; + TDB_DATA *dbuf; + int flag; +}; + +static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data) { - int res; struct db_record *rec = NULL; NTSTATUS status; + struct dbwrap_store_context *store_ctx; - res = db->transaction_start(db); - if (res != 0) { - DEBUG(5, ("transaction_start failed\n")); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } + store_ctx = (struct dbwrap_store_context *)private_data; - rec = db->fetch_locked(db, talloc_tos(), key); + rec = db->fetch_locked(db, talloc_tos(), *(store_ctx->key)); if (rec == NULL) { DEBUG(5, ("fetch_locked failed\n")); - status = NT_STATUS_NO_MEMORY; - goto cancel; + return NT_STATUS_NO_MEMORY; } - status = rec->store(rec, dbuf, flag); + status = rec->store(rec, *(store_ctx->dbuf), store_ctx->flag); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("store returned %s\n", nt_errstr(status))); - goto cancel; } TALLOC_FREE(rec); + return status; +} - res = db->transaction_commit(db); - if (res != 0) { - DEBUG(5, ("tdb_transaction_commit failed\n")); - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - TALLOC_FREE(rec); - return status; - } +NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + NTSTATUS status; + struct dbwrap_store_context store_ctx; - return NT_STATUS_OK; + store_ctx.key = &key; + store_ctx.dbuf = &dbuf; + store_ctx.flag = flag; - cancel: - TALLOC_FREE(rec); + status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx); - if (db->transaction_cancel(db) != 0) { - smb_panic("Cancelling transaction failed"); - } return status; } -NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key) +static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data) { - int res; - struct db_record *rec = NULL; NTSTATUS status; + struct db_record *rec; + TDB_DATA *key = (TDB_DATA *)private_data; - res = db->transaction_start(db); - if (res != 0) { - DEBUG(5, ("transaction_start failed\n")); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - rec = db->fetch_locked(db, talloc_tos(), key); + rec = db->fetch_locked(db, talloc_tos(), *key); if (rec == NULL) { DEBUG(5, ("fetch_locked failed\n")); - status = NT_STATUS_NO_MEMORY; - goto cancel; + return NT_STATUS_NO_MEMORY; } status = rec->delete_rec(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status))); - goto cancel; } - TALLOC_FREE(rec); - - res = db->transaction_commit(db); - if (res != 0) { - DEBUG(5, ("tdb_transaction_commit failed\n")); - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - TALLOC_FREE(rec); - return status; - } + talloc_free(rec); + return status; +} - return NT_STATUS_OK; +NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key) +{ + NTSTATUS status; - cancel: - TALLOC_FREE(rec); + status = dbwrap_trans_do(db, dbwrap_delete_action, &key); - if (db->transaction_cancel(db) != 0) { - smb_panic("Cancelling transaction failed"); - } return status; } @@ -307,3 +289,86 @@ NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key) { return dbwrap_trans_delete(db, string_term_tdb_data(key)); } + +/** + * Wrap db action(s) into a transaction. + */ +NTSTATUS dbwrap_trans_do(struct db_context *db, + NTSTATUS (*action)(struct db_context *, void *), + void *private_data) +{ + int res; + NTSTATUS status; + + res = db->transaction_start(db); + if (res != 0) { + DEBUG(5, ("transaction_start failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = action(db, private_data); + if (!NT_STATUS_IS_OK(status)) { + if (db->transaction_cancel(db) != 0) { + smb_panic("Cancelling transaction failed"); + } + return status; + } + + res = db->transaction_commit(db); + if (res == 0) { + return NT_STATUS_OK; + } + + DEBUG(2, ("transaction_commit failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key) +{ + char *key_upper; + NTSTATUS status; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dbwrap_delete_bystring(db, key_upper); + + talloc_free(key_upper); + return status; +} + +NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key, + TDB_DATA data, int flags) +{ + char *key_upper; + NTSTATUS status; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dbwrap_store_bystring(db, key_upper, data, flags); + + talloc_free(key_upper); + return status; +} + +TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, + const char *key) +{ + char *key_upper; + TDB_DATA result; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return make_tdb_data(NULL, 0); + } + + result = dbwrap_fetch_bystring(db, mem_ctx, key_upper); + + talloc_free(key_upper); + return result; +} diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c index 0c39a572ad..00c5475394 100644 --- a/source3/lib/errmap_unix.c +++ b/source3/lib/errmap_unix.c @@ -40,6 +40,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = { { EISDIR, ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, { EMLINK, ERRDOS, ERRgeneral, NT_STATUS_TOO_MANY_LINKS }, { EINTR, ERRHRD, ERRgeneral, NT_STATUS_RETRY }, + { ENOSYS, ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED }, #ifdef ELOOP { ELOOP, ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND }, #endif diff --git a/source3/lib/events.c b/source3/lib/events.c index 08debb4252..7a06ad0829 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -286,7 +286,7 @@ static void s3_event_debug(void *context, enum tevent_debug_level level, samba_level = 2; break; case TEVENT_DEBUG_TRACE: - samba_level = 10; + samba_level = 11; break; }; diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 7f133f20b0..ee1f4b70b3 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -26,12 +26,13 @@ #define DBGC_CLASS DBGC_TDB #define TIMEOUT_LEN 12 -#define CACHE_DATA_FMT "%12u/%s" +#define CACHE_DATA_FMT "%12u/" #define READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" #define BLOB_TYPE "DATA_BLOB" #define BLOB_TYPE_LEN 9 -static TDB_CONTEXT *cache; +static struct tdb_context *cache; +static struct tdb_context *cache_notrans; /** * @file gencache.c @@ -49,9 +50,10 @@ static TDB_CONTEXT *cache; * false on failure **/ -bool gencache_init(void) +static bool gencache_init(void) { char* cache_fname = NULL; + int open_flags = O_RDWR|O_CREAT; /* skip file open if it's already opened */ if (cache) return True; @@ -60,11 +62,12 @@ bool gencache_init(void) DEBUG(5, ("Opening cache file at %s\n", cache_fname)); - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0644); + cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags, 0644); if (!cache && (errno == EACCES)) { - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDONLY, 0644); + open_flags = O_RDONLY; + cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags, + 0644); if (cache) { DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname)); } @@ -74,65 +77,123 @@ bool gencache_init(void) DEBUG(5, ("Attempt to open gencache.tdb has failed.\n")); return False; } - return True; -} + cache_fname = lock_path("gencache_notrans.tdb"); -/** - * Cache shutdown function. Closes opened cache tdb file. - * - * @return true on successful closing the cache or - * false on failure during cache shutdown - **/ + DEBUG(5, ("Opening cache file at %s\n", cache_fname)); -bool gencache_shutdown(void) -{ - int ret; - /* tdb_close routine returns -1 on error */ - if (!cache) return False; - DEBUG(5, ("Closing cache file\n")); - ret = tdb_close(cache); - cache = NULL; - return ret != -1; + cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST, + open_flags, 0644); + if (cache_notrans == NULL) { + DEBUG(5, ("Opening %s failed: %s\n", cache_fname, + strerror(errno))); + tdb_close(cache); + return false; + } + + return True; } +static TDB_DATA last_stabilize_key(void) +{ + TDB_DATA result; + result.dptr = (uint8_t *)"@LAST_STABILIZED"; + result.dsize = 17; + return result; +} /** * Set an entry in the cache file. If there's no such * one, then add it. * * @param keystr string that represents a key of this entry - * @param value text representation value being cached + * @param blob DATA_BLOB value being cached * @param timeout time when the value is expired * * @retval true when entry is successfuly stored * @retval false on failure **/ -bool gencache_set(const char *keystr, const char *value, time_t timeout) +bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, + time_t timeout) { int ret; TDB_DATA databuf; - char* valstr = NULL; + char* val; + time_t last_stabilize; + static int writecount; + + if (tdb_data_cmp(string_term_tdb_data(keystr), + last_stabilize_key()) == 0) { + DEBUG(10, ("Can't store %s as a key\n", keystr)); + return false; + } - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr && value); + if ((keystr == NULL) || (blob == NULL)) { + return false; + } if (!gencache_init()) return False; - if (asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value) == -1) { + val = talloc_asprintf(talloc_tos(), CACHE_DATA_FMT, (int)timeout); + if (val == NULL) { return False; } + val = talloc_realloc(NULL, val, char, talloc_array_length(val)-1); + if (val == NULL) { + return false; + } + val = (char *)talloc_append_blob(NULL, val, *blob); + if (val == NULL) { + return false; + } - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", keystr, value,ctime(&timeout), + DEBUG(10, ("Adding cache entry with key = %s and timeout =" + " %s (%d seconds %s)\n", keystr, ctime(&timeout), (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store_bystring(cache, keystr, databuf, 0); - SAFE_FREE(valstr); + ret = tdb_store_bystring( + cache_notrans, keystr, + make_tdb_data((uint8_t *)val, talloc_array_length(val)), + 0); + TALLOC_FREE(val); + if (ret != 0) { + return false; + } + + /* + * Every 100 writes within a single process, stabilize the cache with + * a transaction. This is done to prevent a single transaction to + * become huge and chew lots of memory. + */ + writecount += 1; + if (writecount > lp_parm_int(-1, "gencache", "stabilize_count", 100)) { + gencache_stabilize(); + writecount = 0; + goto done; + } + + /* + * Every 5 minutes, call gencache_stabilize() to not let grow + * gencache_notrans.tdb too large. + */ + + last_stabilize = 0; + databuf = tdb_fetch(cache_notrans, last_stabilize_key()); + if ((databuf.dptr != NULL) + && (databuf.dptr[databuf.dsize-1] == '\0')) { + last_stabilize = atoi((char *)databuf.dptr); + SAFE_FREE(databuf.dptr); + } + if ((last_stabilize + + lp_parm_int(-1, "gencache", "stabilize_interval", 300)) + < time(NULL)) { + gencache_stabilize(); + } + +done: return ret == 0; } @@ -147,26 +208,63 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout) bool gencache_del(const char *keystr) { - int ret; + bool exists; + bool ret = false; + char *value; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + if (keystr == NULL) { + return false; + } if (!gencache_init()) return False; DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); - ret = tdb_delete_bystring(cache, keystr); - return ret == 0; + if (tdb_lock_bystring(cache_notrans, keystr) == -1) { + DEBUG(5, ("Could not lock key for %s\n", keystr)); + return false; + } + + /* + * We delete an element by setting its timeout to 0. This way we don't + * have to do a transaction on gencache.tdb every time we delete an + * element. + */ + + exists = gencache_get(keystr, &value, NULL); + if (exists) { + SAFE_FREE(value); + ret = gencache_set(keystr, "", 0); + } + tdb_unlock_bystring(cache_notrans, keystr); + return ret; } +static bool gencache_pull_timeout(char *val, time_t *pres, char **pendptr) +{ + time_t res; + char *endptr; + + res = strtol(val, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid gencache data format: %s\n", val)); + return false; + } + if (pres != NULL) { + *pres = res; + } + if (pendptr != NULL) { + *pendptr = endptr; + } + return true; +} /** * Get existing entry from the cache file. * * @param keystr string that represents a key of this entry - * @param valstr buffer that is allocated and filled with the entry value - * buffer's disposing must be done outside + * @param blob DATA_BLOB that is filled with entry's blob * @param timeout pointer to a time_t that is filled with entry's * timeout * @@ -174,31 +272,40 @@ bool gencache_del(const char *keystr) * @retval False for failure **/ -bool gencache_get(const char *keystr, char **valstr, time_t *timeout) +bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, + time_t *timeout) { TDB_DATA databuf; time_t t; char *endptr; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + if (keystr == NULL) { + return false; + } + + if (tdb_data_cmp(string_term_tdb_data(keystr), + last_stabilize_key()) == 0) { + DEBUG(10, ("Can't get %s as a key\n", keystr)); + return false; + } if (!gencache_init()) { return False; } - databuf = tdb_fetch_bystring(cache, keystr); + databuf = tdb_fetch_bystring(cache_notrans, keystr); if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", + databuf = tdb_fetch_bystring(cache, keystr); + } + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found \n", keystr)); return False; } - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr)); + if (!gencache_pull_timeout((char *)databuf.dptr, &t, &endptr)) { SAFE_FREE(databuf.dptr); return False; } @@ -207,20 +314,33 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout) "timeout = %s", t > time(NULL) ? "valid" : "expired", keystr, endptr+1, ctime(&t))); + if (t == 0) { + /* Deleted */ + SAFE_FREE(databuf.dptr); + return False; + } + if (t <= time(NULL)) { - /* We're expired, delete the entry */ - tdb_delete_bystring(cache, keystr); + /* + * We're expired, delete the entry. We can't use gencache_del + * here, because that uses gencache_get_data_blob for checking + * the existence of a record. We know the thing exists and + * directly store an empty value with 0 timeout. + */ + gencache_set(keystr, "", 0); SAFE_FREE(databuf.dptr); return False; } - if (valstr) { - *valstr = SMB_STRDUP(endptr+1); - if (*valstr == NULL) { + if (blob != NULL) { + *blob = data_blob( + endptr+1, + databuf.dsize - PTR_DIFF(endptr+1, databuf.dptr)); + if (blob->data == NULL) { SAFE_FREE(databuf.dptr); - DEBUG(0, ("strdup failed\n")); + DEBUG(0, ("memdup failed\n")); return False; } } @@ -234,155 +354,192 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout) return True; } +struct stabilize_state { + bool written; + bool error; +}; +static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, + void *priv); + /** - * Get existing entry from the cache file. - * - * @param keystr string that represents a key of this entry - * @param blob DATA_BLOB that is filled with entry's blob - * @param expired pointer to a bool that indicates whether the entry is expired + * Stabilize gencache * - * @retval true when entry is successfuly fetched - * @retval False for failure - **/ + * Migrate the clear-if-first gencache data to the stable, + * transaction-based gencache.tdb + */ -bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, bool *expired) +bool gencache_stabilize(void) { - TDB_DATA databuf; - time_t t; - char *blob_type; - unsigned char *buf = NULL; - bool ret = False; - fstring valstr; - int buflen = 0, len = 0, blob_len = 0; - unsigned char *blob_buf = NULL; - - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + struct stabilize_state state; + int res; + char *now; if (!gencache_init()) { - return False; + return false; } - databuf = tdb_fetch_bystring(cache, keystr); - if (!databuf.dptr) { - DEBUG(10,("Cache entry with key = %s couldn't be found\n", - keystr)); - return False; + res = tdb_transaction_start(cache); + if (res == -1) { + DEBUG(10, ("Could not start transaction on gencache.tdb: " + "%s\n", tdb_errorstr(cache))); + return false; + } + res = tdb_transaction_start(cache_notrans); + if (res == -1) { + tdb_transaction_cancel(cache); + DEBUG(10, ("Could not start transaction on " + "gencache_notrans.tdb: %s\n", + tdb_errorstr(cache_notrans))); + return false; } - buf = (unsigned char *)databuf.dptr; - buflen = databuf.dsize; + state.error = false; + state.written = false; - len += tdb_unpack(buf+len, buflen-len, "fB", - &valstr, - &blob_len, &blob_buf); - if (len == -1) { - goto out; + res = tdb_traverse(cache_notrans, stabilize_fn, &state); + if ((res == -1) || state.error) { + if ((tdb_transaction_cancel(cache_notrans) == -1) + || (tdb_transaction_cancel(cache) == -1)) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return false; } - t = strtol(valstr, &blob_type, 10); + if (!state.written) { + if ((tdb_transaction_cancel(cache_notrans) == -1) + || (tdb_transaction_cancel(cache) == -1)) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return true; + } - if (strcmp(blob_type+1, BLOB_TYPE) != 0) { - goto out; + res = tdb_transaction_commit(cache); + if (res == -1) { + DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " + "%s\n", tdb_errorstr(cache))); + if (tdb_transaction_cancel(cache_notrans) == -1) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return false; } - DEBUG(10,("Returning %s cache entry: key = %s, " - "timeout = %s", t > time(NULL) ? "valid" : - "expired", keystr, ctime(&t))); + res = tdb_transaction_commit(cache_notrans); + if (res == -1) { + DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " + "%s\n", tdb_errorstr(cache))); + return false; + } - if (t <= time(NULL)) { - /* We're expired */ - if (expired) { - *expired = True; - } + now = talloc_asprintf(talloc_tos(), "%d", (int)time(NULL)); + if (now != NULL) { + tdb_store(cache_notrans, last_stabilize_key(), + string_term_tdb_data(now), 0); + TALLOC_FREE(now); } - if (blob) { - *blob = data_blob(blob_buf, blob_len); - if (!blob->data) { - goto out; + return true; +} + +static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, + void *priv) +{ + struct stabilize_state *state = (struct stabilize_state *)priv; + int res; + time_t timeout; + + if (tdb_data_cmp(key, last_stabilize_key()) == 0) { + return 0; + } + + if (!gencache_pull_timeout((char *)val.dptr, &timeout, NULL)) { + DEBUG(10, ("Ignoring invalid entry\n")); + return 0; + } + if ((timeout < time(NULL)) || (val.dsize == 0)) { + res = tdb_delete(cache, key); + if ((res == -1) && (tdb_error(cache) == TDB_ERR_NOEXIST)) { + res = 0; + } else { + state->written = true; + } + } else { + res = tdb_store(cache, key, val, 0); + if (res == 0) { + state->written = true; } } - ret = True; - out: - SAFE_FREE(blob_buf); - SAFE_FREE(databuf.dptr); + if (res == -1) { + DEBUG(10, ("Transfer to gencache.tdb failed: %s\n", + tdb_errorstr(cache))); + state->error = true; + return -1; + } - return ret; + if (tdb_delete(cache_notrans, key) == -1) { + DEBUG(10, ("tdb_delete from gencache_notrans.tdb failed: " + "%s\n", tdb_errorstr(cache_notrans))); + state->error = true; + return -1; + } + return 0; } /** - * Set an entry in the cache file. If there's no such - * one, then add it. + * Get existing entry from the cache file. * * @param keystr string that represents a key of this entry - * @param blob DATA_BLOB value being cached - * @param timeout time when the value is expired + * @param valstr buffer that is allocated and filled with the entry value + * buffer's disposing must be done outside + * @param timeout pointer to a time_t that is filled with entry's + * timeout * - * @retval true when entry is successfuly stored - * @retval false on failure + * @retval true when entry is successfuly fetched + * @retval False for failure **/ -bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, time_t timeout) +bool gencache_get(const char *keystr, char **value, time_t *ptimeout) { + DATA_BLOB blob; bool ret = False; - int tdb_ret; - TDB_DATA databuf; - char *valstr = NULL; - unsigned char *buf = NULL; - int len = 0, buflen = 0; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr && blob); - - if (!gencache_init()) { - return False; + ret = gencache_get_data_blob(keystr, &blob, ptimeout); + if (!ret) { + return false; } - - if (asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE) == -1) { - return False; + if ((blob.data == NULL) || (blob.length == 0)) { + SAFE_FREE(blob.data); + return false; } - - again: - len = 0; - - len += tdb_pack(buf+len, buflen-len, "fB", - valstr, - blob->length, blob->data); - - if (len == -1) { - goto out; + if (blob.data[blob.length-1] != '\0') { + /* Not NULL terminated, can't be a string */ + SAFE_FREE(blob.data); + return false; } - - if (buflen < len) { - SAFE_FREE(buf); - buf = SMB_MALLOC_ARRAY(unsigned char, len); - if (!buf) { - goto out; - } - buflen = len; - goto again; - } - - databuf = make_tdb_data(buf, len); - - DEBUG(10,("Adding cache entry with key = %s; " - "blob size = %d and timeout = %s" - "(%d seconds %s)\n", keystr, (int)databuf.dsize, - ctime(&timeout), (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - tdb_ret = tdb_store_bystring(cache, keystr, databuf, 0); - if (tdb_ret == 0) { - ret = True; + *value = SMB_STRDUP((char *)blob.data); + data_blob_free(&blob); + if (*value == NULL) { + return false; } + return true; +} - out: - SAFE_FREE(valstr); - SAFE_FREE(buf); +/** + * Set an entry in the cache file. If there's no such + * one, then add it. + * + * @param keystr string that represents a key of this entry + * @param value text representation value being cached + * @param timeout time when the value is expired + * + * @retval true when entry is successfuly stored + * @retval false on failure + **/ - return ret; +bool gencache_set(const char *keystr, const char *value, time_t timeout) +{ + DATA_BLOB blob = data_blob_const(value, strlen(value)+1); + return gencache_set_data_blob(keystr, &blob, timeout); } /** @@ -401,6 +558,7 @@ struct gencache_iterate_state { void *priv); const char *pattern; void *priv; + bool in_persistent; }; static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, @@ -416,6 +574,14 @@ static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, time_t timeout; char *timeout_endp; + if (tdb_data_cmp(key, last_stabilize_key()) == 0) { + return 0; + } + + if (state->in_persistent && tdb_exists(cache_notrans, key)) { + return 0; + } + if (key.dptr[key.dsize-1] == '\0') { keystr = (char *)key.dptr; } else { @@ -465,8 +631,9 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time { struct gencache_iterate_state state; - /* fail completely if get null pointers passed */ - SMB_ASSERT(fn && keystr_pattern); + if ((fn == NULL) || (keystr_pattern == NULL)) { + return; + } if (!gencache_init()) return; @@ -475,30 +642,10 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time state.fn = fn; state.pattern = keystr_pattern; state.priv = data; - tdb_traverse(cache, gencache_iterate_fn, &state); -} -/******************************************************************** - lock a key -********************************************************************/ + state.in_persistent = false; + tdb_traverse(cache_notrans, gencache_iterate_fn, &state); -int gencache_lock_entry( const char *key ) -{ - if (!gencache_init()) - return -1; - - return tdb_lock_bystring(cache, key); -} - -/******************************************************************** - unlock a key -********************************************************************/ - -void gencache_unlock_entry( const char *key ) -{ - if (!gencache_init()) - return; - - tdb_unlock_bystring(cache, key); - return; + state.in_persistent = true; + tdb_traverse(cache, gencache_iterate_fn, &state); } diff --git a/source3/lib/ldap_escape.c b/source3/lib/ldap_escape.c index d101bc5ecd..a731cb9864 100644 --- a/source3/lib/ldap_escape.c +++ b/source3/lib/ldap_escape.c @@ -32,10 +32,10 @@ * and to be free()ed by the caller. **/ -char *escape_ldap_string_alloc(const char *s) +char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s) { size_t len = strlen(s)+1; - char *output = (char *)SMB_MALLOC(len); + char *output = talloc_array(mem_ctx, char, len); const char *sub; int i = 0; char *p = output; @@ -43,7 +43,7 @@ char *escape_ldap_string_alloc(const char *s) if (output == NULL) { return NULL; } - + while (*s) { switch (*s) @@ -64,14 +64,17 @@ char *escape_ldap_string_alloc(const char *s) sub = NULL; break; } - + if (sub) { + char *tmp; len = len + 3; - output = (char *)SMB_REALLOC(output, len); - if (!output) { + tmp = talloc_realloc(mem_ctx, output, char, len); + if (tmp == NULL) { + TALLOC_FREE(output); return NULL; } - + output = tmp; + p = &output[i]; strncpy (p, sub, 3); p += 3; @@ -84,7 +87,7 @@ char *escape_ldap_string_alloc(const char *s) } s++; } - + *p = '\0'; return output; } @@ -101,7 +104,7 @@ char *escape_rdn_val_string_alloc(const char *s) } p = output; - + while (*s) { switch (*s) @@ -122,10 +125,10 @@ char *escape_rdn_val_string_alloc(const char *s) *p = *s; p++; } - + s++; } - + *p = '\0'; /* resize the string to the actual final size */ diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c index 2f8474b37f..e80879a1d2 100644 --- a/source3/lib/netapi/netapi.c +++ b/source3/lib/netapi/netapi.c @@ -170,7 +170,6 @@ NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx) gfree_charcnv(); gfree_interfaces(); - gencache_shutdown(); secrets_shutdown(); TALLOC_FREE(ctx); diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index 39472b20d7..9fa3ddd9a8 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -770,7 +770,7 @@ static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb) { uint32_t fl = UF_SCRIPT; /* god knows why */ - fl |= ads_acb2uf(acb); + fl |= ds_acb2uf(acb); return fl; } diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c index 66aef6ba66..478a3d24ca 100644 --- a/source3/lib/smbldap_util.c +++ b/source3/lib/smbldap_util.c @@ -126,7 +126,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, char *escape_domain_name; /* escape for filter */ - escape_domain_name = escape_ldap_string_alloc(domain_name); + escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -135,11 +135,11 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name, LDAP_OBJ_DOMINFO) < 0) { - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); attr_list = get_attr_list(NULL, dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); @@ -258,7 +258,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, int count; char *escape_domain_name; - escape_domain_name = escape_ldap_string_alloc(domain_name); + escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -268,11 +268,11 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, LDAP_OBJ_DOMINFO, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name) < 0) { - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter)); diff --git a/source3/lib/system.c b/source3/lib/system.c index ffc236e93b..6a4f5d5413 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -458,8 +458,6 @@ static struct timespec calc_create_time_stat_ex(const struct stat_ex *st) static void get_create_timespec(const struct stat *pst, struct stat_ex *dst) { - struct timespec ret; - if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) { dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */ dst->st_ex_btime.tv_nsec = 0; @@ -483,7 +481,7 @@ static void get_create_timespec(const struct stat *pst, struct stat_ex *dst) /* Deal with systems that don't initialize birthtime correctly. * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>. */ - if (null_timespec(ret)) { + if (null_timespec(dst->st_ex_btime)) { dst->st_ex_btime = calc_create_time_stat(pst); dst->st_ex_calculated_birthtime = true; } diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c index 451bc18d2e..fa56763a33 100644 --- a/source3/lib/tldap.c +++ b/source3/lib/tldap.c @@ -1618,7 +1618,7 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx, static void tldap_add_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_ADD); + tldap_simple_done(subreq, TLDAP_RES_ADD); } int tldap_add_recv(struct tevent_req *req) @@ -1718,7 +1718,7 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx, static void tldap_modify_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_MODIFY); + tldap_simple_done(subreq, TLDAP_RES_MODIFY); } int tldap_modify_recv(struct tevent_req *req) @@ -1795,7 +1795,7 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx, static void tldap_delete_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_DELETE); + tldap_simple_done(subreq, TLDAP_RES_DELETE); } int tldap_delete_recv(struct tevent_req *req) diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 31261afd72..af64f370ba 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -349,6 +349,9 @@ static const smb_socket_option socket_options[] = { #ifdef TCP_FASTACK {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT}, #endif +#ifdef TCP_QUICKACK + {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, +#endif {NULL,0,0,0,0}}; /**************************************************************************** diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index cdd7d0a300..c197fd7515 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -96,14 +96,14 @@ int StrCaseCmp(const char *s, const char *t) return +1; } - if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) { return strcmp(ps, pt); /* Not quite the right answer, but finding the right one under this failure case is expensive, and it's pretty close */ } - if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) { TALLOC_FREE(buffer_s); return strcmp(ps, pt); /* Not quite the right answer, but finding the right one @@ -157,14 +157,14 @@ int StrnCaseCmp(const char *s, const char *t, size_t len) return 0; } - if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) { return strncmp(ps, pt, len-n); /* Not quite the right answer, but finding the right one under this failure case is expensive, and it's pretty close */ } - if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) { TALLOC_FREE(buffer_s); return strncmp(ps, pt, len-n); /* Not quite the right answer, but finding the right one @@ -366,7 +366,7 @@ size_t str_charnum(const char *s) { size_t ret, converted_size; smb_ucs2_t *tmpbuf2 = NULL; - if (!push_ucs2_talloc(NULL, &tmpbuf2, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) { return 0; } ret = strlen_w(tmpbuf2); @@ -384,7 +384,7 @@ size_t str_ascii_charnum(const char *s) { size_t ret, converted_size; char *tmpbuf2 = NULL; - if (!push_ascii_talloc(NULL, &tmpbuf2, s, &converted_size)) { + if (!push_ascii_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) { return 0; } ret = strlen(tmpbuf2); @@ -455,7 +455,7 @@ bool strhasupper(const char *s) bool ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) { return false; } @@ -480,7 +480,7 @@ bool strhaslower(const char *s) bool ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) { return false; } @@ -1177,7 +1177,7 @@ char *strchr_m(const char *src, char c) s = src; #endif - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Wrong answer, but what can we do... */ return strchr(src, c); } @@ -1187,7 +1187,7 @@ char *strchr_m(const char *src, char c) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { SAFE_FREE(ws); /* Wrong answer, but what can we do... */ return strchr(src, c); @@ -1248,7 +1248,7 @@ char *strrchr_m(const char *s, char c) char *ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Wrong answer, but what can we do. */ return strrchr(s, c); } @@ -1258,7 +1258,7 @@ char *strrchr_m(const char *s, char c) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { TALLOC_FREE(ws); /* Wrong answer, but what can we do. */ return strrchr(s, c); @@ -1283,7 +1283,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n) char *ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Too hard to try and get right. */ return NULL; } @@ -1293,7 +1293,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { TALLOC_FREE(ws); /* Too hard to try and get right. */ return NULL; @@ -1352,12 +1352,12 @@ char *strstr_m(const char *src, const char *findstr) s = src; #endif - if (!push_ucs2_talloc(NULL, &src_w, src, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) { DEBUG(0,("strstr_m: src malloc fail\n")); return NULL; } - if (!push_ucs2_talloc(NULL, &find_w, findstr, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) { TALLOC_FREE(src_w); DEBUG(0,("strstr_m: find malloc fail\n")); return NULL; @@ -1372,7 +1372,7 @@ char *strstr_m(const char *src, const char *findstr) } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, src_w, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) { TALLOC_FREE(src_w); TALLOC_FREE(find_w); DEBUG(0,("strstr_m: dest malloc fail\n")); @@ -1932,7 +1932,7 @@ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */ SMB_ASSERT(result != NULL); - while (len-- && out_cnt < (data.length * 2) - 5) { + while (len--) { int c = (unsigned char) *(data.data++); bits += c; char_count++; diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 78fa7cd0a1..5b3d94dabe 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -630,3 +630,22 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) return NT_STATUS_INTERNAL_ERROR; } + +int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2) +{ + int ret; + if (t1.dptr == NULL && t2.dptr != NULL) { + return -1; + } + if (t1.dptr != NULL && t2.dptr == NULL) { + return 1; + } + if (t1.dptr == t2.dptr) { + return t1.dsize - t2.dsize; + } + ret = memcmp(t1.dptr, t2.dptr, MIN(t1.dsize, t2.dsize)); + if (ret == 0) { + return t1.dsize - t2.dsize; + } + return ret; +} |