summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/trustdom_cache.c215
-rw-r--r--source3/printing/printing_db.c204
2 files changed, 419 insertions, 0 deletions
diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c
new file mode 100644
index 0000000000..cddbb2daa6
--- /dev/null
+++ b/source3/libsmb/trustdom_cache.c
@@ -0,0 +1,215 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Trusted domain names cache on top of gencache.
+
+ Copyright (C) Rafal Szczesniak 2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL /* there's no proper class yet */
+
+#define TDOMKEY_FMT "TDOM/%s"
+
+
+/**
+ * @file trustdom_cache.c
+ *
+ * Implementation of trusted domain names cache useful when
+ * samba acts as domain member server. In such case, caching
+ * domain names currently trusted gives a performance gain
+ * because there's no need to query PDC each time we need
+ * list of trusted domains
+ **/
+
+
+/**
+ * Initialise trustdom name caching system. Call gencache
+ * initialisation routine to perform necessary activities.
+ *
+ * @return true upon successful cache initialisation or
+ * false if cache init failed
+ **/
+
+BOOL trustdom_cache_enable(void)
+{
+ /* Init trustdom cache by calling gencache initialisation */
+ if (!gencache_init()) {
+ DEBUG(2, ("trustdomcache_enable: Couldn't initialise trustdom cache on top of gencache.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/**
+ * Shutdown trustdom name caching system. Calls gencache
+ * shutdown function.
+ *
+ * @return true upon successful cache close or
+ * false if it failed
+ **/
+
+BOOL trustdom_cache_shutdown(void)
+{
+ /* Close trustdom cache by calling gencache shutdown */
+ if (!gencache_shutdown()) {
+ DEBUG(2, ("trustdomcache_shutdown: Couldn't shutdown trustdom cache on top of gencache.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/**
+ * Form up trustdom name key. It is based only
+ * on domain name now.
+ *
+ * @param name trusted domain name
+ * @return cache key for use in gencache mechanism
+ **/
+
+static char* trustdom_cache_key(const char* name)
+{
+ char* keystr;
+ asprintf(&keystr, TDOMKEY_FMT, strupper_static(name));
+
+ return keystr;
+}
+
+
+/**
+ * Store trusted domain in gencache as the domain name (key)
+ * and ip address of domain controller (value)
+ *
+ * @param name trusted domain name
+ * @param alt_name alternative trusted domain name (used in ADS domains)
+ * @param sid trusted domain's SID
+ * @param timeout cache entry expiration time
+ * @return true upon successful value storing or
+ * false if store attempt failed
+ **/
+
+BOOL trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid,
+ time_t timeout)
+{
+ char *key, *alt_key;
+ fstring sid_string;
+
+ /*
+ * we use gecache call to avoid annoying debug messages
+ * about initialised trustdom
+ */
+ if (!gencache_init()) return False;
+
+ DEBUG(5, ("trustdom_store: storing SID %s of domain %s\n",
+ sid_string_static(sid), name));
+
+ key = trustdom_cache_key(name);
+ alt_key = alt_name ? trustdom_cache_key(alt_name) : NULL;
+
+ /* Generate string representation domain SID */
+ sid_to_string(sid_string, sid);
+
+ /*
+ * try to put the names in the cache
+ */
+ if (alt_key) {
+ return (gencache_set(alt_key, sid_string, timeout)
+ && gencache_set(key, sid_string, timeout));
+ }
+
+ return gencache_set(key, sid_string, timeout);
+}
+
+
+/**
+ * Fetch trusted domain's dc from the gencache.
+ * This routine can also be used to check whether given
+ * domain is currently trusted one.
+ *
+ * @param name trusted domain name
+ * @param sid trusted domain's SID to be returned
+ * @return true if entry is found or
+ * false if has expired/doesn't exist
+ **/
+
+BOOL trustdom_cache_fetch(const char* name, DOM_SID* sid)
+{
+ char *key, *value;
+ time_t timeout;
+
+ /* init the cache */
+ if (!gencache_init()) return False;
+
+ /* exit now if null pointers were passed as they're required further */
+ if (!sid) return False;
+
+ /* prepare a key and get the value */
+ key = trustdom_cache_key(name);
+
+ if (!gencache_get(key, &value, &timeout)) {
+ DEBUG(5, ("no entry for trusted domain %s found.\n", name));
+ return False;
+ } else {
+ DEBUG(5, ("trusted domain %s found (%s)\n", name, value));
+ }
+
+ /* convert ip string representation into in_addr structure */
+ if(! string_to_sid(sid, value)) {
+ sid = NULL;
+ return False;
+ }
+
+ return True;
+}
+
+
+/**
+ * Delete single trustdom entry. Look at the
+ * gencache_iterate definition.
+ *
+ **/
+
+static void flush_trustdom_name(const char* key, const char *value, time_t timeout, void* dptr)
+{
+ gencache_del(key);
+ DEBUG(5, ("Deleting entry %s\n", key));
+}
+
+
+/**
+ * Flush all the trusted domains entries from the cache.
+ **/
+
+void trustdom_cache_flush(void)
+{
+ if (!gencache_init())
+ return;
+
+ /*
+ * iterate through each TDOM cache's entry and flush it
+ * by flush_trustdom_name function
+ */
+ gencache_iterate(flush_trustdom_name, NULL, trustdom_cache_key("*"));
+ DEBUG(5, ("Trusted domains cache flushed\n"));
+}
+
diff --git a/source3/printing/printing_db.c b/source3/printing/printing_db.c
new file mode 100644
index 0000000000..ec33daea1a
--- /dev/null
+++ b/source3/printing/printing_db.c
@@ -0,0 +1,204 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ printing backend routines
+ Copyright (C) Andrew Tridgell 1992-2000
+ Copyright (C) Jeremy Allison 2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "printing.h"
+
+static struct tdb_print_db *print_db_head;
+
+/****************************************************************************
+ Function to find or create the printer specific job tdb given a printername.
+ Limits the number of tdb's open to MAX_PRINT_DBS_OPEN.
+****************************************************************************/
+
+struct tdb_print_db *get_print_db_byname(const char *printername)
+{
+ struct tdb_print_db *p = NULL, *last_entry = NULL;
+ int num_open = 0;
+ pstring printdb_path;
+ BOOL done_become_root = False;
+
+ for (p = print_db_head, last_entry = print_db_head; p; p = p->next) {
+ /* Ensure the list terminates... JRA. */
+ SMB_ASSERT(p->next != print_db_head);
+
+ if (p->tdb && strequal(p->printer_name, printername)) {
+ DLIST_PROMOTE(print_db_head, p);
+ p->ref_count++;
+ return p;
+ }
+ num_open++;
+ last_entry = p;
+ }
+
+ /* Not found. */
+ if (num_open >= MAX_PRINT_DBS_OPEN) {
+ /* Try and recycle the last entry. */
+ DLIST_PROMOTE(print_db_head, last_entry);
+
+ for (p = print_db_head; p; p = p->next) {
+ if (p->ref_count)
+ continue;
+ if (p->tdb) {
+ if (tdb_close(print_db_head->tdb)) {
+ DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
+ print_db_head->printer_name ));
+ return NULL;
+ }
+ }
+ p->tdb = NULL;
+ p->ref_count = 0;
+ memset(p->printer_name, '\0', sizeof(p->printer_name));
+ break;
+ }
+ if (p) {
+ DLIST_PROMOTE(print_db_head, p);
+ p = print_db_head;
+ }
+ }
+
+ if (!p) {
+ /* Create one. */
+ p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db));
+ if (!p) {
+ DEBUG(0,("get_print_db: malloc fail !\n"));
+ return NULL;
+ }
+ ZERO_STRUCTP(p);
+ DLIST_ADD(print_db_head, p);
+ }
+
+ pstrcpy(printdb_path, lock_path("printing/"));
+ pstrcat(printdb_path, printername);
+ pstrcat(printdb_path, ".tdb");
+
+ if (geteuid() != 0) {
+ become_root();
+ done_become_root = True;
+ }
+
+ p->tdb = tdb_open_log(printdb_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+
+ if (done_become_root)
+ unbecome_root();
+
+ if (!p->tdb) {
+ DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n",
+ printdb_path ));
+ DLIST_REMOVE(print_db_head, p);
+ SAFE_FREE(p);
+ return NULL;
+ }
+ fstrcpy(p->printer_name, printername);
+ p->ref_count++;
+ return p;
+}
+
+/***************************************************************************
+ Remove a reference count.
+****************************************************************************/
+
+void release_print_db( struct tdb_print_db *pdb)
+{
+ pdb->ref_count--;
+ SMB_ASSERT(pdb->ref_count >= 0);
+}
+
+/***************************************************************************
+ Close all open print db entries.
+****************************************************************************/
+
+void close_all_print_db(void)
+{
+ struct tdb_print_db *p = NULL, *next_p = NULL;
+
+ for (p = print_db_head; p; p = next_p) {
+ next_p = p->next;
+
+ if (p->tdb)
+ tdb_close(p->tdb);
+ DLIST_REMOVE(print_db_head, p);
+ ZERO_STRUCTP(p);
+ SAFE_FREE(p);
+ }
+}
+
+
+/****************************************************************************
+ Fetch and clean the pid_t record list for all pids interested in notify
+ messages. data needs freeing on exit.
+****************************************************************************/
+
+TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, BOOL cleanlist)
+{
+ TDB_DATA data;
+ size_t i;
+
+ ZERO_STRUCT(data);
+
+ data = tdb_fetch_by_string( tdb, NOTIFY_PID_LIST_KEY );
+
+ if (!data.dptr) {
+ ZERO_STRUCT(data);
+ return data;
+ }
+
+ if (data.dsize % 8) {
+ DEBUG(0,("get_printer_notify_pid_list: Size of record for printer %s not a multiple of 8 !\n", printer_name ));
+ tdb_delete_by_string(tdb, NOTIFY_PID_LIST_KEY );
+ SAFE_FREE(data.dptr);
+ ZERO_STRUCT(data);
+ return data;
+ }
+
+ if (!cleanlist)
+ return data;
+
+ /*
+ * Weed out all dead entries.
+ */
+
+ for( i = 0; i < data.dsize; i += 8) {
+ pid_t pid = (pid_t)IVAL(data.dptr, i);
+
+ if (pid == sys_getpid())
+ continue;
+
+ /* Entry is dead if process doesn't exist or refcount is zero. */
+
+ while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) {
+
+ /* Refcount == zero is a logic error and should never happen. */
+ if (IVAL(data.dptr, i + 4) == 0) {
+ DEBUG(0,("get_printer_notify_pid_list: Refcount == 0 for pid = %u printer %s !\n",
+ (unsigned int)pid, printer_name ));
+ }
+
+ if (data.dsize - i > 8)
+ memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
+ data.dsize -= 8;
+ }
+ }
+
+ return data;
+}
+
+