From d337c3d486a3ff2a194dee20bf75d81c94241a24 Mon Sep 17 00:00:00 2001 From: alexhudson Date: Wed, 23 Jan 2008 08:20:27 +0000 Subject: [PATCH] Merge remove-mdb branch onto trunk, branch is now closed! --- Makefile.am | 92 +- autogen.sh | 2 +- configure.ac | 62 +- include/Bongo.rules | 9 +- include/bongoagent.h | 20 +- include/bongojson.h | 2 +- include/bongoutil.h | 4 +- include/cmlib.h | 87 - include/connio-trace.h | 46 + include/connio.h | 321 +- include/management.h | 1284 ----- include/msgaddr.h | 6 +- include/msgapi.h | 499 +- include/msgftrs.h | 4 - include/nmlib.h | 10 +- init/bongo.init.rpl.in | 63 + init/bongoinit.conf.rpl.in | 11 + man/Bongo.rules | 1 - man/mdbtool.1 | 69 - po/bongo-web/pt_BR.po | 872 ++++ po/bongo/pt_BR.po | 893 ++++ src/agents/addressbook/Bongo.rules | 28 - src/agents/addressbook/addressbook.c | 333 -- src/agents/addressbook/addressbook.h | 132 - src/agents/addressbook/command.c | 526 -- src/agents/alarm/Bongo.rules | 6 +- src/agents/alarm/alarm.c | 15 +- src/agents/alarm/alarm.h | 5 - src/agents/antispam/Bongo.rules | 5 +- src/agents/antispam/antispam.c | 235 +- src/agents/antispam/antispam.h | 18 +- src/agents/antispam/spamd.c | 37 +- src/agents/avirus/Bongo.rules | 5 +- src/agents/avirus/avirus.c | 386 +- src/agents/avirus/avirus.h | 24 +- src/agents/calcmd/Bongo.rules | 6 +- src/agents/calcmd/calcmdd.c | 17 +- src/agents/calcmd/calcmdd.h | 6 - src/agents/collector/Bongo.rules | 8 +- src/agents/collector/collector.c | 15 +- src/agents/collector/collector.h | 6 - src/agents/generic/Bongo.rules | 6 +- src/agents/generic/generic.c | 15 +- src/agents/generic/generic.h | 6 - src/agents/imap/Bongo.rules | 7 +- src/agents/imap/event.c | 5 +- src/agents/imap/fetch.c | 148 +- src/agents/imap/fetch.h | 2 +- src/agents/imap/imapd.c | 310 +- src/agents/imap/imapd.h | 30 +- src/agents/imap/search.c | 17 +- src/agents/imap/session.c | 200 +- src/agents/imap/uid.c | 4 - src/agents/itip/Bongo.rules | 6 +- src/agents/itip/itip.c | 17 +- src/agents/itip/itip.h | 6 - src/agents/mailprox/Bongo.rules | 6 +- src/agents/mailprox/imap.c | 1 - src/agents/mailprox/mailprox.c | 203 +- src/agents/mailprox/mailprox.h | 8 - src/agents/mailprox/pop.c | 1 - src/agents/pluspack/Bongo.rules | 6 +- src/agents/pluspack/pluspack.c | 15 +- src/agents/pluspack/pluspack.h | 9 - src/agents/pop/Bongo.rules | 7 +- src/agents/pop/pop3.c | 214 +- src/agents/queue/Bongo.rules | 6 +- src/agents/queue/conf.c | 477 +- src/agents/queue/conf.h | 37 +- src/agents/queue/domain.c | 579 +-- src/agents/queue/domain.h | 14 +- src/agents/queue/messages.h | 23 +- src/agents/queue/queue.c | 249 +- src/agents/queue/queue.h | 2 +- src/agents/queue/queued.c | 268 +- src/agents/queue/queued.h | 9 +- src/agents/rules/Bongo.rules | 6 +- src/agents/rules/rules.c | 47 +- src/agents/rules/rules.h | 10 - src/agents/smtp/Bongo.rules | 7 +- src/agents/smtp/smtpd.c | 1400 +----- src/agents/store/Bongo.rules | 7 +- src/agents/store/alarmdb.c | 6 +- src/agents/store/auth.c | 1 - src/agents/store/calendar.c | 4 +- src/agents/store/command.c | 469 +- src/agents/store/config.c | 157 +- src/agents/store/cookie.c | 178 +- src/agents/store/db.c | 237 +- src/agents/store/db.h | 9 +- src/agents/store/filters/contact-filter.cpp | 5 +- src/agents/store/filters/event-filter.cpp | 5 +- src/agents/store/filters/filter.cpp | 8 +- src/agents/store/filters/filter.h | 8 +- src/agents/store/filters/mail-filter.cpp | 14 +- src/agents/store/index.cpp | 4 +- src/agents/store/index.h | 2 +- src/agents/store/lock.c | 22 +- src/agents/store/mail-parser.c | 9 +- src/agents/store/mail.c | 12 +- src/agents/store/maildir.c | 176 + src/agents/store/messages.h | 2 + src/agents/store/mime.c | 12 +- src/agents/store/search.c | 41 +- src/agents/store/store.c | 562 +-- src/agents/store/stored.c | 77 +- src/agents/store/stored.h | 26 +- src/agents/store/tests/Bongo.rules | 14 +- src/agents/store/tests/mkauthhash.c | 59 +- src/apps/admin/Bongo.rules | 4 +- .../admin/bongo/admintool/SetupCommands.py | 11 +- src/apps/admin/bongoadmin.c | 1 - src/apps/backup/Bongo.rules | 7 +- src/apps/backup/backup.c | 69 +- src/apps/backup/backup.h | 25 +- src/apps/config/Bongo.rules | 29 +- src/apps/config/config.c | 443 +- src/apps/config/config.h | 22 +- src/apps/config/config/aliases/default_config | 7 + src/apps/config/config/antivirus | 12 +- src/apps/config/config/global | 5 + src/apps/config/config/imap | 6 + src/apps/config/config/mailproxy | 7 + src/apps/config/config/manager | 21 +- src/apps/config/config/pop3 | 5 + src/apps/config/config/queue | 29 + src/apps/config/config/smtp | 24 + src/apps/config/hawkeye/history | 7 + src/apps/config/store.c | 166 + src/apps/manager/Bongo.rules | 5 +- src/apps/manager/manager.c | 60 +- src/apps/sendmail/Bongo.rules | 5 +- src/apps/sendmail/sendmail.c | 14 +- src/apps/setup/Bongo.rules | 6 +- src/apps/setup/bongo-setup.py | 6 +- src/apps/storetool/Bongo.rules | 6 +- src/apps/storetool/bongo-storetool.py | 4 + .../bongo/storetool/BackupCommands.py | 290 ++ .../storetool/bongo/storetool/MailCommands.py | 57 +- .../storetool/bongo/storetool/TestCommands.py | 82 + src/apps/storetool/demo/Bongo.rules | 14 +- src/apps/testtool/Bongo.rules | 6 +- src/apps/testtool/testtool.c | 2 - src/libs/bongoutil/Bongo.rules | 4 +- src/libs/bongoutil/array.c | 42 +- src/libs/bongoutil/bongoutil.c | 6 +- src/libs/bongoutil/tests/Bongo.rules | 2 +- src/libs/bongoutil/utf7mod.c | 4 +- src/libs/cal/Bongo.rules | 12 +- src/libs/cal/tests/Bongo.rules | 6 +- src/libs/calcmd/Bongo.rules | 10 +- src/libs/calcmd/tests/Bongo.rules | 4 +- src/libs/connio/Bongo.rules | 5 +- src/libs/connio/connio.c | 133 +- src/libs/connio/sockets.c | 187 + src/libs/connio/tests/Bongo.rules | 6 +- src/libs/json/json.c | 2 +- src/libs/logger/Bongo.rules | 8 +- src/libs/logger/logs.conf | 10 +- src/libs/management/Bongo.rules | 6 +- src/libs/management/managee.c | 6 +- src/libs/mdb-odbc/Makefile.am | 20 - src/libs/mdb-odbc/mdbodbc.c | 4466 ----------------- src/libs/mdb-odbc/mdbodbcp.h | 956 ---- src/libs/memmgr/Bongo.rules | 4 +- src/libs/msgapi/Bongo.rules | 53 +- src/libs/msgapi/auth-backends/README.odbc | 30 + src/libs/msgapi/auth-backends/ldap.c | 57 + src/libs/msgapi/auth-backends/odbc.c | 542 ++ src/libs/msgapi/auth-backends/sqlite.c | 296 ++ src/libs/msgapi/auth-backends/sqlite.h | 12 + src/libs/msgapi/cookie.c | 188 + src/libs/msgapi/msgaddr.c | 168 +- src/libs/msgapi/msgapi.c | 1986 +------- src/libs/msgapi/msgapip.h | 7 - src/libs/msgapi/msgauth.c | 266 + src/libs/msgapi/msgcollector.c | 38 +- src/libs/msgapi/msgdate.c | 1 - src/libs/msgapi/plugin-api.h | 45 + src/libs/msgapi/sqldb.c | 300 ++ src/libs/nmap/Bongo.rules | 6 +- src/libs/nmap/bongoagent.c | 67 +- src/libs/nmap/nmap.c | 103 +- src/libs/python/Bongo.rules | 29 +- src/libs/python/bongo/admin/ManagedSlapd.py | 58 +- src/libs/python/bongo/store/CommandStream.py | 22 + src/libs/python/bongo/store/StoreClient.py | 77 +- .../python/bongo/store/StoreConnection.py | 4 +- src/libs/python/libbongo/Bongo.rules | 27 +- src/libs/python/libbongo/bootstrap.c | 3 - src/libs/python/libbongo/cal.c | 3 +- src/libs/python/libbongo/libs.c | 21 +- src/libs/python/libbongo/msgapi-defs.c | 286 -- src/libs/python/libbongo/msgapi.c | 303 -- src/libs/python/libbongo/tests.c | 47 + src/libs/streamio/Bongo.rules | 6 +- src/libs/xpl/Bongo.rules | 6 +- src/libs/xpl/cryptolock.c | 15 +- src/libs/xpl/dns.c | 1 - src/libs/xpl/hash.c | 1 + src/libs/xpl/mem.c | 3 +- src/libs/xpl/tests/Bongo.rules | 2 +- src/www/Bongo.rules | 119 +- src/www/bongo-standalone.py | 109 +- src/www/bongo/commonweb/ElementTree.py | 17 + src/www/bongo/commonweb/Standalone.py | 18 +- src/www/bongo/dragonfly/Auth.py | 35 +- src/www/bongo/dragonfly/MailView.py | 23 +- src/www/bongo/dragonfly/PreferencesView.py | 13 +- src/www/bongo/dragonfly/ResourcePath.py | 8 +- src/www/bongo/dragonfly/SummaryView.py | 32 + src/www/bongo/hawkeye/AgentView.py | 278 +- src/www/bongo/hawkeye/AliasView.py | 179 + src/www/bongo/hawkeye/AntispamView.py | 113 - src/www/bongo/hawkeye/BackupView.py | 2 +- src/www/bongo/hawkeye/HawkeyeHandler.py | 101 +- src/www/bongo/hawkeye/HawkeyePath.py | 13 +- src/www/bongo/hawkeye/RootView.py | 37 +- src/www/bongo/hawkeye/Server.py | 38 +- src/www/bongo/hawkeye/ServerView.py | 3 +- src/www/bongo/hawkeye/SystemView.py | 2 +- src/www/bongo/sundial/Auth.py | 41 + src/www/bongo/sundial/DeleteView.py | 38 + src/www/bongo/sundial/GetView.py | 55 + src/www/bongo/sundial/OptionsView.py | 35 + src/www/bongo/sundial/PropfindView.py | 112 + src/www/bongo/sundial/PutView.py | 56 + src/www/bongo/sundial/ReportView.py | 159 + src/www/bongo/sundial/Server.py | 52 + src/www/bongo/sundial/SundialHandler.py | 28 + src/www/bongo/sundial/SundialPath.py | 125 + src/www/bongo/sundial/__init__.py | 0 src/www/css/admin.css | 163 +- src/www/css/interpreter.css | 54 - src/www/css/log.css | 106 + src/www/dragonfly-debug.html | 24 +- src/www/dragonfly.html | 10 +- src/www/hawkeye/agents/agentview.tpl | 60 + src/www/hawkeye/agents/index.tpl | 23 +- src/www/hawkeye/aliases/confirmdelete.tpl | 11 + src/www/hawkeye/aliases/edit.tpl | 59 + src/www/hawkeye/aliases/index.tpl | 22 + src/www/hawkeye/antispam/index.tpl | 22 - src/www/hawkeye/footer.tpl | 10 +- src/www/hawkeye/header.tpl | 8 +- src/www/hawkeye/root/index.tpl | 13 + src/www/hawkeye/server/index.tpl | 12 +- src/www/hawkeye/system/index.tpl | 2 + src/www/img/agent-bongoantispam.png | Bin 0 -> 3882 bytes src/www/img/agent-bongoavirus.png | Bin 0 -> 2866 bytes src/www/img/agent-bongocalcmd.png | Bin 0 -> 2017 bytes src/www/img/agent-bongocollector.png | Bin 0 -> 2017 bytes src/www/img/agent-bongoimap.png | Bin 0 -> 3421 bytes src/www/img/agent-bongomailprox.png | Bin 0 -> 3165 bytes src/www/img/agent-bongopluspack.png | Bin 0 -> 703 bytes src/www/img/agent-bongopop3.png | Bin 0 -> 3421 bytes src/www/img/agent-bongoqueue.png | Bin 0 -> 2017 bytes src/www/img/agent-bongosmtp.png | Bin 0 -> 2338 bytes src/www/img/agent-control.png | Bin 0 -> 3386 bytes src/www/img/agent-global.png | Bin 0 -> 4014 bytes src/www/img/agent-unknown.png | Bin 0 -> 2017 bytes src/www/img/document-delete.png | Bin 0 -> 783 bytes src/www/img/document-properties.png | Bin 0 -> 716 bytes src/www/img/list-add.png | Bin 0 -> 400 bytes src/www/img/list-remove.png | Bin 0 -> 215 bytes src/www/img/sbg.png | Bin 32430 -> 32997 bytes src/www/js/AddressBook.js | 38 +- src/www/js/Admin.js | 119 + src/www/js/BongoCalendar.js | 2 +- src/www/js/BrowserCheck.js | 2 +- src/www/js/Calendar.js | 8 +- src/www/js/CalendarDrag.js | 20 +- src/www/js/CalendarEditor.js | 6 +- src/www/js/CalendarLayout.js | 8 +- src/www/js/CalendarWidgets.js | 6 +- src/www/js/Composer.js | 44 +- src/www/js/Dragonfly.js | 88 +- src/www/js/Format.js | 14 +- src/www/js/Gettext.js | 2 +- src/www/js/JCal.js | 30 +- src/www/js/Location.js | 8 +- src/www/js/Log.js | 334 ++ src/www/js/Login.js | 38 +- src/www/js/Mail.js | 20 +- src/www/js/MailConversationView.js | 14 +- src/www/js/MailListView.js | 4 +- src/www/js/MailWidgets.js | 2 +- src/www/js/OccurrenceEditor.js | 8 +- src/www/js/Preferences.js | 30 +- src/www/js/Search.js | 6 +- src/www/js/Util.js | 82 +- src/www/js/ValidatingEntry.js | 4 +- src/www/js/Widgets.js | 64 +- src/www/js/eArea/editableArea.js | 37 +- src/www/js/eArea/icons/switch-mode.png | Bin 889 -> 1331 bytes src/www/js/lib/MochiKit/Logging.js | 290 -- src/www/js/lib/MochiKit/LoggingPane.js | 358 -- src/www/js/lib/MochiKit/interpreter.js | 375 -- 298 files changed, 10738 insertions(+), 18877 deletions(-) delete mode 100644 include/cmlib.h create mode 100644 include/connio-trace.h delete mode 100644 include/management.h create mode 100644 init/bongo.init.rpl.in create mode 100644 init/bongoinit.conf.rpl.in delete mode 100644 man/mdbtool.1 create mode 100644 po/bongo-web/pt_BR.po create mode 100644 po/bongo/pt_BR.po delete mode 100644 src/agents/addressbook/Bongo.rules delete mode 100644 src/agents/addressbook/addressbook.c delete mode 100644 src/agents/addressbook/addressbook.h delete mode 100644 src/agents/addressbook/command.c create mode 100644 src/agents/store/maildir.c create mode 100644 src/apps/config/config/aliases/default_config create mode 100644 src/apps/config/config/global create mode 100644 src/apps/config/config/imap create mode 100644 src/apps/config/config/mailproxy create mode 100644 src/apps/config/config/pop3 create mode 100644 src/apps/config/config/queue create mode 100644 src/apps/config/config/smtp create mode 100644 src/apps/config/hawkeye/history create mode 100644 src/apps/config/store.c create mode 100644 src/apps/storetool/bongo/storetool/BackupCommands.py create mode 100644 src/apps/storetool/bongo/storetool/TestCommands.py create mode 100644 src/libs/connio/sockets.c delete mode 100644 src/libs/mdb-odbc/Makefile.am delete mode 100644 src/libs/mdb-odbc/mdbodbc.c delete mode 100644 src/libs/mdb-odbc/mdbodbcp.h create mode 100644 src/libs/msgapi/auth-backends/README.odbc create mode 100644 src/libs/msgapi/auth-backends/ldap.c create mode 100644 src/libs/msgapi/auth-backends/odbc.c create mode 100644 src/libs/msgapi/auth-backends/sqlite.c create mode 100644 src/libs/msgapi/auth-backends/sqlite.h create mode 100644 src/libs/msgapi/cookie.c create mode 100644 src/libs/msgapi/msgauth.c create mode 100644 src/libs/msgapi/plugin-api.h create mode 100644 src/libs/msgapi/sqldb.c create mode 100644 src/libs/python/libbongo/tests.c create mode 100644 src/www/bongo/commonweb/ElementTree.py create mode 100644 src/www/bongo/hawkeye/AliasView.py delete mode 100644 src/www/bongo/hawkeye/AntispamView.py create mode 100644 src/www/bongo/sundial/Auth.py create mode 100644 src/www/bongo/sundial/DeleteView.py create mode 100644 src/www/bongo/sundial/GetView.py create mode 100644 src/www/bongo/sundial/OptionsView.py create mode 100644 src/www/bongo/sundial/PropfindView.py create mode 100644 src/www/bongo/sundial/PutView.py create mode 100644 src/www/bongo/sundial/ReportView.py create mode 100644 src/www/bongo/sundial/Server.py create mode 100644 src/www/bongo/sundial/SundialHandler.py create mode 100644 src/www/bongo/sundial/SundialPath.py create mode 100644 src/www/bongo/sundial/__init__.py delete mode 100644 src/www/css/interpreter.css create mode 100644 src/www/css/log.css create mode 100644 src/www/hawkeye/agents/agentview.tpl create mode 100644 src/www/hawkeye/aliases/confirmdelete.tpl create mode 100644 src/www/hawkeye/aliases/edit.tpl create mode 100644 src/www/hawkeye/aliases/index.tpl delete mode 100644 src/www/hawkeye/antispam/index.tpl create mode 100644 src/www/img/agent-bongoantispam.png create mode 100644 src/www/img/agent-bongoavirus.png create mode 100644 src/www/img/agent-bongocalcmd.png create mode 100644 src/www/img/agent-bongocollector.png create mode 100644 src/www/img/agent-bongoimap.png create mode 100644 src/www/img/agent-bongomailprox.png create mode 100644 src/www/img/agent-bongopluspack.png create mode 100644 src/www/img/agent-bongopop3.png create mode 100644 src/www/img/agent-bongoqueue.png create mode 100644 src/www/img/agent-bongosmtp.png create mode 100644 src/www/img/agent-control.png create mode 100644 src/www/img/agent-global.png create mode 100644 src/www/img/agent-unknown.png create mode 100644 src/www/img/document-delete.png create mode 100644 src/www/img/document-properties.png create mode 100644 src/www/img/list-add.png create mode 100644 src/www/img/list-remove.png create mode 100644 src/www/js/Admin.js create mode 100644 src/www/js/Log.js delete mode 100644 src/www/js/lib/MochiKit/Logging.js delete mode 100644 src/www/js/lib/MochiKit/LoggingPane.js delete mode 100644 src/www/js/lib/MochiKit/interpreter.js diff --git a/Makefile.am b/Makefile.am index a30d306..8b4ab8f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,41 +10,41 @@ # http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html # -AUTOMAKE_OPTIONS := subdir-objects +AUTOMAKE_OPTIONS = subdir-objects ACLOCAL_AMFLAGS = -I m4 -I macros -NULL := +NULL = -bin_PROGRAMS := -sbin_PROGRAMS := -noinst_PROGRAMS := -check_PROGRAMS := +bin_PROGRAMS = +sbin_PROGRAMS = +noinst_PROGRAMS = +check_PROGRAMS = -sbin_SCRIPTS := +sbin_SCRIPTS = -dist_sbin_SCRIPTS := -dist_noinst_SCRIPTS := -dist_pkglibexec_SCRIPTS := +dist_sbin_SCRIPTS = +dist_noinst_SCRIPTS = +dist_pkglibexec_SCRIPTS = -lib_LTLIBRARIES := +lib_LTLIBRARIES = -nobase_dist_pkgdata_DATA := -dist_noinst_DATA := -noinst_DATA := +nobase_dist_pkgdata_DATA = +dist_noinst_DATA = +noinst_DATA = -noinst_HEADERS := +noinst_HEADERS = -BUILT_SOURCES := -CLEANFILES := +BUILT_SOURCES = +CLEANFILES = -TESTS := +TESTS = -AM_CPPFLAGS := $(ALL_CFLAGS) \ +AM_CPPFLAGS = $(ALL_CFLAGS) \ $(NO_POINTER_SIGN_WARNINGS) \ $(PTHREAD_CFLAGS) \ -I$(top_srcdir)/include $(GNUTLS_CFLAGS) -EXTRA_DIST := \ +EXTRA_DIST = \ config.rpath \ bongo.pc.in \ HACKING \ @@ -62,7 +62,7 @@ localedir = $(datadir)/locale DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA := bongo.pc +pkgconfig_DATA = bongo.pc pkglibexecdir = $(libexecdir)/$(PACKAGE) @@ -86,7 +86,15 @@ docs: doxygen/html clean: clean-recursive rm -rf ./doxygen/html ./doxygen/latex -include_subdirs := \ +# disabled agents +# src/agents/mailprox +# src/agents/rules + +# src/libs/mdb +# src/libs/mdb-file +# src/libs/mdb-xldap + +include_subdirs = \ include \ src/libs/xpl \ src/libs/xpl/tests \ @@ -96,18 +104,13 @@ include_subdirs := \ src/libs/connio \ src/libs/connio/tests \ src/libs/json \ - src/libs/mdb \ - src/libs/mdb-file \ - src/libs/mdb-xldap \ src/libs/logger \ src/libs/streamio \ src/libs/streamio/codec \ src/libs/cal \ src/libs/cal/tests \ src/libs/nmap \ - src/libs/management \ src/libs/msgapi \ - src/libs/connmgr \ src/libs/calcmd \ src/libs/calcmd/tests \ src/libs/python \ @@ -117,30 +120,19 @@ include_subdirs := \ src/agents/avirus \ src/agents/calcmd \ src/agents/collector \ - src/agents/connmgr \ - src/agents/connmgr/cmmodules/user \ - src/agents/connmgr/cmmodules/rbl \ - src/agents/connmgr/cmmodules/rdns \ - src/agents/connmgr/cmmodules/lists \ src/agents/generic \ src/agents/imap \ src/agents/imap/tests \ src/agents/itip \ - src/agents/mailprox \ - src/agents/pluspack \ src/agents/pop \ src/agents/queue \ - src/agents/rules \ src/agents/smtp \ src/agents/store \ src/agents/store/tests \ - src/apps/admin \ src/apps/backup \ src/apps/config \ src/apps/manager \ src/apps/sendmail \ - src/apps/setup \ - src/apps/mdbtool \ src/apps/queuetool \ src/apps/storetool \ src/apps/storetool/demo \ @@ -152,7 +144,7 @@ include_subdirs := \ # src/apps/migrate -DIST_SUBDIRS := $(SUBDIRS) $(include_subdirs) +DIST_SUBDIRS = $(SUBDIRS) $(include_subdirs) include include/Bongo.rules include src/libs/xpl/Bongo.rules @@ -163,52 +155,40 @@ include src/libs/bongoutil/tests/Bongo.rules include src/libs/connio/Bongo.rules include src/libs/connio/tests/Bongo.rules include src/libs/json/Bongo.rules -include src/libs/mdb/Bongo.rules -include src/libs/mdb-file/Bongo.rules -include src/libs/mdb-xldap/Bongo.rules +#include src/libs/mdb/Bongo.rules +#include src/libs/mdb-file/Bongo.rules +#include src/libs/mdb-xldap/Bongo.rules include src/libs/logger/Bongo.rules include src/libs/streamio/Bongo.rules include src/libs/streamio/codec/Bongo.rules include src/libs/cal/Bongo.rules include src/libs/cal/tests/Bongo.rules include src/libs/nmap/Bongo.rules -include src/libs/management/Bongo.rules include src/libs/msgapi/Bongo.rules -include src/libs/connmgr/Bongo.rules include src/libs/calcmd/Bongo.rules include src/libs/calcmd/tests/Bongo.rules include src/libs/python/Bongo.rules include src/libs/python/libbongo/Bongo.rules -include src/agents/addressbook/Bongo.rules include src/agents/alarm/Bongo.rules include src/agents/antispam/Bongo.rules include src/agents/avirus/Bongo.rules include src/agents/calcmd/Bongo.rules include src/agents/collector/Bongo.rules -include src/agents/connmgr/Bongo.rules -include src/agents/connmgr/cmmodules/user/Bongo.rules -include src/agents/connmgr/cmmodules/rbl/Bongo.rules -include src/agents/connmgr/cmmodules/rdns/Bongo.rules -include src/agents/connmgr/cmmodules/lists/Bongo.rules include src/agents/generic/Bongo.rules include src/agents/imap/Bongo.rules include src/agents/imap/tests/Bongo.rules include src/agents/itip/Bongo.rules -include src/agents/mailprox/Bongo.rules -include src/agents/pluspack/Bongo.rules +#include src/agents/mailprox/Bongo.rules include src/agents/pop/Bongo.rules include src/agents/queue/Bongo.rules -include src/agents/rules/Bongo.rules +#include src/agents/rules/Bongo.rules include src/agents/smtp/Bongo.rules include src/agents/store/Bongo.rules include src/agents/store/tests/Bongo.rules -include src/apps/admin/Bongo.rules include src/apps/backup/Bongo.rules include src/apps/config/Bongo.rules include src/apps/manager/Bongo.rules include src/apps/sendmail/Bongo.rules -include src/apps/setup/Bongo.rules -include src/apps/mdbtool/Bongo.rules # include src/apps/migrate/Bongo.rules include src/apps/queuetool/Bongo.rules include src/apps/storetool/Bongo.rules diff --git a/autogen.sh b/autogen.sh index 02d4e44..2656721 100755 --- a/autogen.sh +++ b/autogen.sh @@ -455,7 +455,7 @@ if test x$SVNREV = x; then echo Unable to discern build version echo \#define BONGO_BUILD_BRANCH \"unknown\" > ./include/bongo-buildinfo.h echo \#define BONGO_BUILD_VSTR \"\" >> ./include/bongo-buildinfo.h - echo \#define BONGO_BUILD_VER \"0\" > ./include/bongo-buildinfo.h + echo \#define BONGO_BUILD_VER \"0\" >> ./include/bongo-buildinfo.h else echo SVN Rev at $SVNREV echo \#define BONGO_BUILD_BRANCH \"trunk\" > ./include/bongo-buildinfo.h diff --git a/configure.ac b/configure.ac index 7d27c7a..4736773 100644 --- a/configure.ac +++ b/configure.ac @@ -220,6 +220,10 @@ XPL_DEFAULT_MAIL_DIR=${XPL_DEFAULT_STATE_DIR}/users AC_SUBST(XPL_DEFAULT_MAIL_DIR) AC_DEFINE_UNQUOTED(XPL_DEFAULT_MAIL_DIR, "$XPL_DEFAULT_MAIL_DIR", [Default mail directory]) +XPL_DEFAULT_COOKIE_DIR=${XPL_DEFAULT_STATE_DIR}/dbf/cookies +AC_SUBST(XPL_DEFAULT_COOKIE_DIR) +AC_DEFINE_UNQUOTED(XPL_DEFAULT_COOKIE_DIR, "$XPL_DEFAULT_COOKIE_DIR", [Default cookie directory]) + XPL_DEFAULT_CERT_PATH=${XPL_DEFAULT_STATE_DIR}/dbf/osslcert.pem AC_SUBST(XPL_DEFAULT_CERT_PATH) AC_DEFINE_UNQUOTED(XPL_DEFAULT_CERT_PATH, "$XPL_DEFAULT_CERT_PATH", [Default cert path]) @@ -256,15 +260,29 @@ LIBS=$SAVE_LIBS AC_SUBST(RESOLV_LIBS) have_ldap="no" +info_ldap="No. LDAP auth backend will be unavailable." AC_CHECK_HEADER(ldap.h,[ AC_CHECK_LIB(ldap, ldap_init,[ LDAP_LIBS="-lldap" have_ldap="yes" + info_ldap="Yes. LDAP auth backend will be available." ]) ]) AM_CONDITIONAL(HAVE_LDAP,test "$have_ldap" = "yes") AC_SUBST(LDAP_LIBS) +have_odbc="no" +info_odbc="No. ODBC auth backend will be unavailable." +AC_CHECK_HEADER(odbcinst.h,[ + AC_CHECK_LIB(odbc, SQLConnect,[ + ODBC_LIBS="-lodbc" + have_odbc="yes" + info_odbc="Yes. ODBC auth backend will be available." + ]) +]) +AM_CONDITIONAL(HAVE_ODBC,test "$have_odbc" = "yes") +AC_SUBST(ODBC_LIBS) + have_kstat="no" AC_CHECK_LIB(kstat, kstat_open,[ AC_CHECK_HEADERS(kstat.h, [have_kstat="yes"]) @@ -358,6 +376,18 @@ case "$host" in ;; esac +dnl Check for ElementTree lxml +prog=" +import lxml.etree as et +" + +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC +then + AC_MSG_RESULT([Found ElementTree lxml]) +else + AC_MSG_ERROR([Couldn't find ElementTree lxml module for python]) +fi + LIBS_save="$LIBS" CPPFLAGS_save="$CPPFLAGS" @@ -628,6 +658,15 @@ fi ac_configure_args="$ac_configure_args --enable-threadsafe --enable-cross-thread-connections --disable-tcl" +# disabled agents +# src/agents/mailprox/Makefile +# src/agents/rules/Makefile +# src/agents/pluspack/Makefile + +#src/libs/mdb/Makefile +#src/libs/mdb-file/Makefile +#src/libs/mdb-xldap/Makefile + AC_OUTPUT([ Makefile bongo.pc @@ -638,6 +677,8 @@ include/Makefile init/bongo.init.fc4 init/bongo.init.sles9 init/bongo.init.suse10 +init/bongo.init.rpl +init/bongoinit.conf.rpl init/http-bongo.solaris-smf init/svc-bongo.solaris-smf src/agents/alarm/Makefile @@ -645,31 +686,19 @@ src/agents/antispam/Makefile src/agents/avirus/Makefile src/agents/calcmd/Makefile src/agents/collector/Makefile -src/agents/connmgr/Makefile -src/agents/connmgr/cmmodules/lists/Makefile -src/agents/connmgr/cmmodules/rbl/Makefile -src/agents/connmgr/cmmodules/rdns/Makefile -src/agents/connmgr/cmmodules/user/Makefile src/agents/generic/Makefile src/agents/imap/Makefile src/agents/imap/tests/Makefile src/agents/itip/Makefile -src/agents/mailprox/Makefile -src/agents/pluspack/Makefile src/agents/pop/Makefile src/agents/queue/Makefile src/agents/smtp/Makefile src/agents/store/Makefile src/agents/store/tests/Makefile -src/agents/rules/Makefile -src/apps/setup/Makefile -src/apps/setup/bongo-setup.xml src/apps/manager/Makefile -src/apps/admin/Makefile src/apps/config/Makefile src/apps/sendmail/Makefile src/apps/backup/Makefile -src/apps/mdbtool/Makefile src/apps/queuetool/Makefile src/apps/storetool/Makefile src/apps/storetool/demo/Makefile @@ -684,10 +713,6 @@ src/libs/json/Makefile src/libs/streamio/Makefile src/libs/streamio/codec/Makefile src/libs/logger/Makefile -src/libs/management/Makefile -src/libs/mdb/Makefile -src/libs/mdb-file/Makefile -src/libs/mdb-xldap/Makefile src/libs/memmgr/Makefile src/libs/msgapi/Makefile src/libs/nmap/Makefile @@ -699,7 +724,6 @@ src/libs/bongoutil/Makefile src/libs/bongoutil/tests/Makefile src/libs/xpl/Makefile src/libs/xpl/tests/Makefile -src/libs/connmgr/Makefile src/www/Makefile src/www/bongo.conf zoneinfo/Makefile @@ -717,12 +741,14 @@ AC_MSG_NOTICE([Configured to build Bongo: Bongo user: ${info_bongo_user} Debug CFLAGS: ${info_debug_cflags} -Imported libraries: +Required libraries: CLucene: ${info_clucene} CURL: ${info_curl} SQLite: ${info_sqlite} libical: ${info_libical} Optional libraries: + LDAP: ${info_ldap} + ODBC: ${info_odbc} Check: ${info_check} ]) diff --git a/include/Bongo.rules b/include/Bongo.rules index defc325..906b1eb 100644 --- a/include/Bongo.rules +++ b/include/Bongo.rules @@ -1,10 +1,11 @@ # -*- Makefile -*- bongoincludedir=$(includedir)/bongo -bongoinclude_HEADERS := \ +bongoinclude_HEADERS = \ include/bongo-config.h \ include/calcmd.h \ include/connio.h \ + include/connio-trace.h \ include/bongocal.h \ include/bongocheck.h \ include/bongojson.h \ @@ -13,8 +14,6 @@ bongoinclude_HEADERS := \ include/bongostore.h \ include/bongostream.h \ include/logger.h \ - include/management.h \ - include/mdb.h \ include/memmgr.h \ include/msgaddr.h \ include/msgapi.h \ @@ -37,9 +36,7 @@ bongoinclude_HEADERS := \ include/xplschema.h \ include/xplservice.h \ include/xplthread.h \ - include/xplutil.h \ - include/connmgr.h \ - include/cmlib.h + include/xplutil.h include/all: include/clean: clean diff --git a/include/bongoagent.h b/include/bongoagent.h index a7dc5aa..bf93eae 100644 --- a/include/bongoagent.h +++ b/include/bongoagent.h @@ -25,7 +25,6 @@ #define BONGOAGENT_H #include -#include #include #include #include @@ -57,10 +56,11 @@ typedef enum _BongoAgentStates { } BongoAgentState; #define BA_STARTUP_XPL 0 -#define BA_STARTUP_MDB 1 +#define BA_STARTUP_MSGLIB 1 #define BA_STARTUP_CONNIO 2 #define BA_STARTUP_NMAP 4 #define BA_STARTUP_LOGGER 8 +#define BA_STARTUP_MSGAUTH 16 typedef struct { int interval; @@ -75,7 +75,6 @@ struct _BongoAgent { BongoAgentState state; - MDBHandle directoryHandle; LoggingHandle *loggingHandle; bongo_ssl_context *sslContext; @@ -99,6 +98,7 @@ typedef struct _BongoConfigItem { } BongoConfigItem; BOOL ReadBongoConfiguration(BongoConfigItem *config, char *filename); +BOOL ProcessBongoConfiguration(BongoConfigItem *config, const BongoJsonNode *node); BOOL SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node); void FreeBongoConfiguration(BongoConfigItem *config); @@ -188,6 +188,20 @@ void BongoAgentShutdownFunc (BongoJsonRpcServer *server, BongoArray *args, void *userData); +struct _BongoGlobals { + char *hostname; + char *hostaddr; + char *postmaster; +}; + +extern struct _BongoGlobals BongoGlobals; +static BongoConfigItem GlobalConfig[] = { + { BONGO_JSON_STRING, "o:hostname/s", &BongoGlobals.hostname }, + { BONGO_JSON_STRING, "o:hostaddr/s", &BongoGlobals.hostaddr }, + { BONGO_JSON_STRING, "o:postmaster/s", &BongoGlobals.postmaster }, + { BONGO_JSON_NULL, NULL, NULL } +}; + #define BONGO_ENVELOPE_NEXT(p) \ { (p) = (p) + strlen(p) + 1; \ if (*(p) == '\0') (p)++; \ diff --git a/include/bongojson.h b/include/bongojson.h index 4a7dc2d..210430b 100644 --- a/include/bongojson.h +++ b/include/bongojson.h @@ -220,7 +220,7 @@ BongoJsonResult BongoJsonJPathGetObject(BongoJsonNode *n, const char *path, Bong BongoJsonResult BongoJsonJPathGetArray(BongoJsonNode *n, const char *path, BongoArray **val); BongoJsonResult BongoJsonJPathGetBool(BongoJsonNode *n, const char *path, BOOL *val); BongoJsonResult BongoJsonJPathGetInt(BongoJsonNode *n, const char *path, int *val); -BongoJsonResult BongoJsonJPathGetString(BongoJsonNode *n, const char *path, const char **val); +BongoJsonResult BongoJsonJPathGetString(BongoJsonNode *n, const char *path, char **val); BongoJsonResult BongoJsonJPathGetDouble(BongoJsonNode *n, const char *path, double *val); BongoJsonResult BongoJsonJPathGetFloat(BongoJsonNode *n, const char *path, float *val); diff --git a/include/bongoutil.h b/include/bongoutil.h index 735dd07..4c3ccdf 100644 --- a/include/bongoutil.h +++ b/include/bongoutil.h @@ -174,7 +174,7 @@ BOOL QuickCmp(unsigned char *str1, unsigned char *str2); unsigned char *DecodeBase64(unsigned char *EncodedString); unsigned char *EncodeBase64(const unsigned char *UnencodedString); -BOOL HashCredential(const unsigned char *DN, unsigned char *Credential, unsigned char *Hash); +BOOL HashCredential(unsigned char *Credential, unsigned char *Hash); /* String functions */ @@ -269,7 +269,7 @@ void BongoHashtableDelete(BongoHashtable *table); #define BongoHashTableCount(_tableptr) ((_tableptr)->itemcount) #define BongoCreateStringHashTable(buckets) \ -BongoHashtableCreate(buckets, BongoStringHash, strcmp) +BongoHashtableCreate(buckets, (HashFunction)BongoStringHash, (CompareFunction)strcmp) /* handy string hasher */ uint32_t BongoStringHash (char *s); diff --git a/include/cmlib.h b/include/cmlib.h deleted file mode 100644 index 326d383..0000000 --- a/include/cmlib.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2001 Novell, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you - * may find current contact information at www.novell.com. - * - ****************************************************************************/ - -#ifndef _BONGO_CM_LIBRARY_H -#define _BONGO_CM_LIBRARY_H - -#include - -#include -#include - -/* - CMInitialize() MUST be called before any other call in the library. - If it is not called the other calls will be unable to authenticate - to the connection mananager. -*/ -BOOL CMInitialize(MDBHandle directoryHandle, unsigned char *service); - -/* - Request permission for the specified address to connect to the specified - service. - - CM_RESULT_ALLOWED will be returned if the connection is allowed. If not - CM_RESULT_DENY_TEMPORARY or CM_RESULT_DENY_PERMANENT will be returned. -*/ -int CMVerifyConnect(unsigned long address, unsigned char *comment, BOOL *requireAuth); - -/* - Request permission for the specified address to relay. - - CM_RESULT_ALLOWED will be returned if the connection is allowed. If not - CM_RESULT_DENY_TEMPORARY or CM_RESULT_DENY_PERMANENT will be returned. - - if CM_RESULT_ALLOWED is returned the buffer pointed to by user will be - filled out with the name of the user that authenticated. -*/ -int CMVerifyRelay(unsigned long address, unsigned char *user); - -/* - Inform the Connection Manager that a connection started with CMConnect() - has ended. - - The result will be CM_RESULT_OK if the notification was sent succesfully. -*/ -int CMDisconnected(unsigned long address); - -/* - Inform the Connection Manager that a user has authenticated from the - specified address. - - The result will be CM_RESULT_OK if the notification was sent succesfully. -*/ -int CMAuthenticated(unsigned long address, unsigned char *user); - -int CMDelivered(unsigned long address, unsigned long recipients); -int CMReceived(unsigned long address, unsigned long local, unsigned long invalid, unsigned long remote); -int CMFoundVirus(unsigned long address, unsigned long recipients, unsigned char *name); -int CMSpamFound(unsigned long address, unsigned long recipients); -int CMDOSDetected(unsigned long address, unsigned char *description); - -/* - Send a custom command object to the Connection Manager. You do not - need to fill out the pass field. The library will take care of - authentication for you. If the request was sent succesfully TRUE - will be returned and the result object will be filled out. -*/ -BOOL CMSendCommand(ConnMgrCommand *command, ConnMgrResult *result); - -#endif /* _BONGO_CM_LIBRARY_H */ diff --git a/include/connio-trace.h b/include/connio-trace.h new file mode 100644 index 0000000..3b09db8 --- /dev/null +++ b/include/connio-trace.h @@ -0,0 +1,46 @@ + +#if !defined(_BONGO_CONN_TRACE) + +#define CONN_TRACE_GET_FLAGS() 0 +#define CONN_TRACE_SET_FLAGS(f) +#define CONN_TRACE_INIT(p, n) +#define CONN_TRACE_SHUTDOWN() +#define CONN_TRACE_CREATE_DESTINATION(t) NULL +#define CONN_TRACE_FREE_DESTINATION(d) +#define CONN_TRACE_BEGIN(c, t, d) +#define CONN_TRACE_END(c) +#define CONN_TRACE_EVENT(c, t) +#define CONN_TRACE_ERROR(c, e, l) +#define CONN_TRACE_DATA(c, t, b, l) +#define CONN_TRACE_DATA_AND_ERROR(c, t, b, l, e) + +#else + +void ConnTraceSetFlags(unsigned long flags); +unsigned long ConnTraceGetFlags(void); +void ConnTraceInit(char *path, char *name); +void ConnTraceShutdown(void); +TraceDestination *ConnTraceCreatePersistentDestination(unsigned char type); +void ConnTraceFreeDestination(TraceDestination *destination); +void ConnTraceBegin(Connection *c, unsigned long type, TraceDestination *destination); +void ConnTraceEnd(Connection *c); +void ConnTraceEvent(Connection *c, unsigned long event, char *buffer, long len); + +#define CONN_TRACE_GET_FLAGS() ConnTraceGetFlags() +#define CONN_TRACE_SET_FLAGS(f) ConnTraceSetFlags(f) +#define CONN_TRACE_INIT(p, n) ConnTraceInit(p, n) +#define CONN_TRACE_SHUTDOWN() ConnTraceShutdown() +#define CONN_TRACE_CREATE_DESTINATION(t) ConnTraceCreatePersistentDestination(t) +#define CONN_TRACE_FREE_DESTINATION(d) ConnTraceFreeDestination(d) +#define CONN_TRACE_BEGIN(c, t, d) ConnTraceBegin((c), (t), (d)) +#define CONN_TRACE_END(c) ConnTraceEnd((c)) +#define CONN_TRACE_EVENT(c, t) ConnTraceEvent((c), (t), NULL, 0) +#define CONN_TRACE_ERROR(c, e, l) ConnTraceEvent((c), CONN_TRACE_EVENT_ERROR, (e), (l)) +#define CONN_TRACE_DATA(c, t, b, l) ConnTraceEvent((c), (t), (b), (l)) +#define CONN_TRACE_DATA_AND_ERROR(c, t, b, l, e) if ((l) > 0) { \ + ConnTraceEvent((c), (t), (b), (l)); \ + } else { \ + ConnTraceEvent((c), CONN_TRACE_EVENT_ERROR, (e), (l)); \ + } + +#endif diff --git a/include/connio.h b/include/connio.h index ebb2eed..cee4ab4 100644 --- a/include/connio.h +++ b/include/connio.h @@ -82,30 +82,8 @@ typedef struct { #define SSL_DISABLE_EMPTY_FRAGMENTS (1 << 4) #define SSL_DONT_INSERT_EMPTY_FRAGMENTS (1 << 5) -#define CHOP_NEWLINE(s) \ - { unsigned char *p; p = strchr((s), 0x0A); \ - if (p) { \ - *p = '\0'; \ - } \ - p = strrchr((s), 0x0D); \ - if (p) { \ - *p = '\0'; \ - } \ - } - -#define SET_POINTER_TO_VALUE(p,s) \ - { (p) = (s); \ - while(isspace(*(p))) { \ - (p)++; \ - } \ - if ((*(p) == '=') || (*(p) == ':')) { \ - (p)++; \ - } \ - while(isspace(*(p))) { \ - (p)++; \ - } \ - } - +void CHOP_NEWLINE(unsigned char *s); +void SET_POINTER_TO_VALUE(unsigned char *p, unsigned char *s); // FIXME: Unused? #if defined(_BONGO_LINUX) || defined(S390RH) || defined(SOLARIS) @@ -134,287 +112,12 @@ typedef struct { #define IPgetsockname(s, a, l) getsockname((s), (a), (l)) #define IPgetpeername(s, a, l) getpeername((s), (a), (l)) -#define CONN_TCP_READ(c, b, l, r) \ - { \ - struct pollfd pfd; \ - do { \ - pfd.fd = (int)(c)->socket; \ - pfd.events = POLLIN; \ - (r) = poll(&pfd, 1, (c)->receive.timeOut * 1000); \ - if ((r) > 0) { \ - if ((pfd.revents & (POLLIN | POLLPRI))) { \ - do { \ - (r) = IPrecv((c)->socket, b, l, 0); \ - if ((r) >= 0) { \ - CONN_TRACE_DATA((c), CONN_TRACE_EVENT_READ, (b), (r)); \ - break; \ - } else if (errno == EINTR) { \ - continue; \ - } \ - CONN_TRACE_ERROR((c), "RECV", (r)); \ - (r) = -1; \ - break; \ - } while (TRUE); \ - break; \ - } else if ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL))) { \ - CONN_TRACE_ERROR((c), "POLL EVENT", (r)); \ - (r) = -1; \ - break; \ - } \ - } \ - if (errno == EINTR) { \ - continue; \ - } \ - CONN_TRACE_ERROR((c), "POLL", (r)); \ - (r) = -1; \ - break; \ - } while (TRUE); \ - } - -#define CONN_TCP_WRITE(c, b, l, r) \ - { \ - do { \ - (r) = IPsend((c)->socket, b, l, MSG_NOSIGNAL); \ - if ((r) >= 0) { \ - CONN_TRACE_DATA((c), CONN_TRACE_EVENT_WRITE, (b), (r)); \ - break; \ - } else if (errno == EINTR) { \ - continue; \ - } \ - CONN_TRACE_ERROR((c), "POLL", (r)); \ - (r) = -1; \ - break; \ - } while (TRUE); \ - } - -#elif defined(LIBC) || defined(NETWARE) || defined(WIN32) - -#ifdef WIN32 -typedef int socklen_t; -typedef unsigned int in_addr_t; -#define ETIMEDOUT WSAETIMEDOUT -#define ECONNREFUSED WSAECONNREFUSED -#define ENETUNREACH WSAENETUNREACH -#endif - -#define ConnSockOpt(c, o, v, p, l) setsockopt((c)->socket, (o), (v), (p), (l)) - -#define IPSOCKET SOCKET -#define IPInit() {WSADATA data; WSAStartup(MAKEWORD(1,1), &data);} - -#define IPCleanup() WSACleanup(); -#define IPsocket(domain, type, protocol) socket(domain, type, protocol) -#define IPaccept(s, addr, addrlen) accept(s, addr, addrlen) -#define IPlisten(sock, backlog) listen(sock, backlog) -#define IPbind(sock, addr, addrlen) bind(sock, addr, addrlen) -#define IPconnect(sock, addr, addrlen) connect(sock, addr, addrlen) -#define IPrecv(sock, buf, len, flags) recv(sock, buf, len, flags) -#define IPsend(sock, buf, len, flags) send(sock, buf, len, flags) -#define IPclose(sock) closesocket(sock) -#define IPshutdown(s, how) shutdown(s, how) -#define IPgetsockname(s, addr, addrlen) getsockname(s, addr, addrlen) -#define IPgetpeername(s, addr, addrlen) getpeername(s, addr, addrlen) -#define IPselect(nfds, rfds, wfds, efds, t) select(nfds, rfds, wfds, efds, t) - -#define CONN_TCP_READ(c, b, l, r) \ - { \ - fd_set rfds; \ - struct timeval timeout; \ - FD_ZERO(&rfds); \ - FD_SET((c)->socket, &rfds); \ - timeout.tv_usec = 0; \ - timeout.tv_sec = (c)->receive.timeOut; \ - (r) = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout); \ - if ((r) > 0) { \ - (r) = IPrecv((c)->socket, (b), (l), 0); \ - CONN_TRACE_DATA_AND_ERROR((c), CONN_TRACE_EVENT_READ, (b), (r), "RECV"); \ - } else { \ - CONN_TRACE_ERROR((c), "SELECT", (r)); \ - (r) = -1; \ - } \ - } - -#define CONN_TCP_WRITE(c, b, l, r) \ - (r) = IPsend((c)->socket, (b), (l), 0); \ - CONN_TRACE_DATA_AND_ERROR((c), CONN_TRACE_EVENT_WRITE, (b), (r), "SEND"); - #else #error Connection management library not implemented on this platform. #endif -#define CONN_TCP_SEND(c, b, l, r) \ - { \ - if (!(c)->ssl.enable) { \ - CONN_TCP_WRITE((c), (b), (l), (r)); \ - } else { \ - CONN_SSL_WRITE((c), (b), (l), (r)); \ - } \ - } - -#define CONN_TCP_RECEIVE(c, b, l, r) \ - { \ - if (!(c)->ssl.enable) { \ - CONN_TCP_READ((c), (b), (l), (r)); \ - } else { \ - CONN_SSL_READ((c), (b), (l), (r)); \ - } \ - } - -#define CONN_TCP_FLUSH(c, b, e, r) \ - { \ - if ((b) < (e)) { \ - register char *curPTR = (char *)(b); \ - if (!(c)->ssl.enable) { \ - while (curPTR < (e)) { \ - CONN_TCP_WRITE((c), curPTR, (e) - curPTR, (r)); \ - if ((r) > 0) { \ - curPTR += (r); \ - continue; \ - } \ - break; \ - } \ - } else { \ - while (curPTR < (e)) { \ - CONN_SSL_WRITE((c), curPTR, (e) - curPTR, (r)); \ - if ((r) > 0) { \ - curPTR += (r); \ - continue; \ - } \ - break; \ - } \ - } \ - if (curPTR == (e)) { \ - (r) = (e) - (b); \ - } else { \ - (r) = -1; \ - } \ - } else { \ - (r) = 0; \ - } \ - } - -#define CONN_TCP_CLOSE(c) \ - { \ - if ((c)->receive.buffer) { \ - (c)->receive.remaining = CONN_TCP_MTU; \ - } else { \ - (c)->receive.remaining = 0; \ - } \ - (c)->receive.read = (c)->receive.write = (c)->receive.buffer; \ - if ((c)->send.buffer) { \ - ConnFlush(c); \ - (c)->send.remaining = CONN_TCP_MTU; \ - } else { \ - (c)->send.remaining = 0; \ - } \ - (c)->send.read = (c)->send.write = (c)->send.buffer; \ - if ((c)->ssl.enable) { \ - gnutls_bye((c)->ssl.context, GNUTLS_SHUT_RDWR); \ - gnutls_deinit((c)->ssl.context); \ - (c)->ssl.context = NULL; \ - (c)->ssl.enable = FALSE; \ - } \ - if ((c)->socket != -1) { \ - IPshutdown((c)->socket, 2); \ - IPclose((c)->socket); \ - (c)->socket = -1; \ - } \ - } - -#define CONN_SSL_NEW(c, s) \ - { \ - (c)->ssl.context = __gnutls_new(s); \ - if ((c)->ssl.context) \ - (c)->ssl.enable = TRUE; \ - } else { \ - (c)->ssl.context = NULL; \ - (c)->ssl.enable = FALSE; \ - } \ - } - -#define CONN_SSL_FREE(c) \ - { \ - if ((c)->ssl.enable) { \ - gnutls_deinit((c)->ssl.context); \ - (c)->ssl.context = NULL; \ - (c)->ssl.enable = FALSE; \ - } \ - } - -#define CONN_SSL_ACCEPT(c, s) \ - { \ - (c)->ssl.context = __gnutls_new(s); \ - if ((c)->ssl.context \ - && (gnutls_handshake((c)->ssl.context) == 0)) { \ - (c)->ssl.enable = TRUE; \ - } else { \ - if ((c)->ssl.context) { \ - gnutls_deinit((c)->ssl.context); \ - (c)->ssl.context = NULL; \ - } \ - (c)->ssl.enable = FALSE; \ - } \ - } - -#define CONN_SSL_CONNECT(c, s, r) \ - { \ - (c)->ssl.context = __gnutls_new(s); \ - if ((c)->ssl.context \ - && (gnutls_handshake((c)->ssl.context) == 0)) { \ - (c)->ssl.enable = TRUE; \ - } else { \ - if ((c)->ssl.context) { \ - gnutls_deinit((c)->ssl.context); \ - (c)->ssl.context = NULL; \ - } \ - (c)->ssl.enable = FALSE; \ - } \ - } - -#if !defined(_BONGO_CONN_TRACE) - -#define CONN_TRACE_GET_FLAGS() 0 -#define CONN_TRACE_SET_FLAGS(f) -#define CONN_TRACE_INIT(p, n) -#define CONN_TRACE_SHUTDOWN() -#define CONN_TRACE_CREATE_DESTINATION(t) NULL -#define CONN_TRACE_FREE_DESTINATION(d) -#define CONN_TRACE_BEGIN(c, t, d) -#define CONN_TRACE_END(c) -#define CONN_TRACE_EVENT(c, t) -#define CONN_TRACE_ERROR(c, e, l) -#define CONN_TRACE_DATA(c, t, b, l) -#define CONN_TRACE_DATA_AND_ERROR(c, t, b, l, e) - -#else - -#define CONN_TRACE_GET_FLAGS() ConnTraceGetFlags() -#define CONN_TRACE_SET_FLAGS(f) ConnTraceSetFlags(f) -#define CONN_TRACE_INIT(p, n) ConnTraceInit(p, n) -#define CONN_TRACE_SHUTDOWN() ConnTraceShutdown() -#define CONN_TRACE_CREATE_DESTINATION(t) ConnTraceCreatePersistentDestination(t) -#define CONN_TRACE_FREE_DESTINATION(d) ConnTraceFreeDestination(d) -#define CONN_TRACE_BEGIN(c, t, d) ConnTraceBegin((c), (t), (d)) -#define CONN_TRACE_END(c) ConnTraceEnd((c)) -#define CONN_TRACE_EVENT(c, t) ConnTraceEvent((c), (t), NULL, 0) -#define CONN_TRACE_ERROR(c, e, l) ConnTraceEvent((c), CONN_TRACE_EVENT_ERROR, (e), (l)) -#define CONN_TRACE_DATA(c, t, b, l) ConnTraceEvent((c), (t), (b), (l)) -#define CONN_TRACE_DATA_AND_ERROR(c, t, b, l, e) if ((l) > 0) { \ - ConnTraceEvent((c), (t), (b), (l)); \ - } else { \ - ConnTraceEvent((c), CONN_TRACE_EVENT_ERROR, (e), (l)); \ - } - -#endif - -#define CONN_SSL_READ(c, b, l, r) (r) = gnutls_record_recv((c)->ssl.context, (void *)(b), (l)); \ - CONN_TRACE_DATA_AND_ERROR((c), CONN_TRACE_EVENT_READ, (b), (r), "SSL_READ"); - -#define CONN_SSL_WRITE(c, b, l, r) (r) = gnutls_record_send((c)->ssl.context, (void *)(b), (l)); \ - CONN_TRACE_DATA_AND_ERROR((c), CONN_TRACE_EVENT_WRITE, (b), (r), "SSL_WRITE"); - typedef struct _ConnectionBuffer { char *read; char *write; @@ -523,6 +226,13 @@ typedef struct { unsigned long initialized; } AddressPool; +#include + +void ConnTcpWrite(Connection *c, char *b, size_t l, int *r); +void ConnTcpRead(Connection *c, char *b, size_t l, int *r); +void ConnTcpFlush(Connection *c, char *b, char *e, int *r); +void ConnTcpClose(Connection *c); + void ConnAddressPoolStartup(AddressPool *pool, unsigned long errorThreshold, unsigned long errorTimeThreshold); void ConnAddressPoolShutdown(AddressPool *pool); BOOL ConnAddressPoolAddHost(AddressPool *pool, char *hostName, unsigned short hostPort, unsigned long weight); @@ -576,23 +286,10 @@ int ConnWriteFile(Connection *Conn, FILE *Source); int ConnWriteFromFile(Connection *Conn, FILE *Source, int Count); #define ConnWriteStr(conn, mesg) ConnWrite(conn, mesg, strlen(mesg)) - int ConnFlush(Connection *Conn); BOOL ConnTraceAvailable(void); -#if defined(_BONGO_CONN_TRACE) -void ConnTraceSetFlags(unsigned long flags); -unsigned long ConnTraceGetFlags(void); -void ConnTraceInit(char *path, char *name); -void ConnTraceShutdown(void); -TraceDestination *ConnTraceCreatePersistentDestination(unsigned char type); -void ConnTraceFreeDestination(TraceDestination *destination); -void ConnTraceBegin(Connection *c, unsigned long type, TraceDestination *destination); -void ConnTraceEnd(Connection *c); -void ConnTraceEvent(Connection *c, unsigned long event, char *buffer, long len); -#endif - /* fixme - to be deprecated */ #define XPLNETDB_DEFINE_CONTEXT diff --git a/include/management.h b/include/management.h deleted file mode 100644 index 068d33a..0000000 --- a/include/management.h +++ /dev/null @@ -1,1284 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2001 Novell, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you - * may find current contact information at www.novell.com. - * - ****************************************************************************/ - -#ifndef BONGO_MANAGEMENT_H -#define BONGO_MANAGEMENT_H - -#include -#include - -#define DMC_MANAGER_PORT 21289 -#define DMC_MANAGER_SSL_PORT 21389 -#define DMC_HASH_SIZE 128 - -#define DMC_CONNECTION_TIMEOUT (15 * 60) -#define DMC_MANAGEMENT_STACKSIZE (64 * 1024) -#define DMC_REPORT_PRODUCT_VERSION(d, dl) \ -{ \ - unsigned long cOuNtOfByTeS; \ - cOuNtOfByTeS = strlen(PRODUCT_NAME) + 2 + strlen(PRODUCT_SHORT_NAME) + 17 + strlen(PRODUCT_DESCRIPTION) + 2; \ - if ((d)&& ((dl) > cOuNtOfByTeS)) { \ - (dl) = sprintf((d), "%s (%s: v%d.%d.%d)\r\n%s\r\n", PRODUCT_NAME, PRODUCT_SHORT_NAME, PRODUCT_MAJOR_VERSION, PRODUCT_MINOR_VERSION, PRODUCT_LETTER_VERSION, PRODUCT_DESCRIPTION); \ - } else { \ - (dl) = cOuNtOfByTeS; \ - } \ -} - -enum ManagementStates { - MANAGEMENT_LOADING = 0, - MANAGEMENT_INITIALIZING, - MANAGEMENT_READY, - MANAGEMENT_RUNNING, - MANAGEMENT_STOPPING, - MANAGEMENT_STOPPED, - - MANAGEMENT_MAX_STATES -}; - -typedef BOOL (*DMCReadVariable)(unsigned int Variable, unsigned char *Data, size_t *DataLength); -typedef BOOL (*DMCWriteVariable)(unsigned int Variable, unsigned char *Data, size_t DataLength); -typedef BOOL (*DMCCommand)(unsigned char *Arguments, unsigned char **Response, BOOL *CloseConnection); - -typedef struct _ManagementVariable { - unsigned char *Name; - unsigned char *Help; - - DMCReadVariable Read; - DMCWriteVariable Write; -} ManagementVariables; - -typedef struct _DMC_MANAGEMENT_COMMAND { - unsigned char *Name; - - DMCCommand Execute; -} ManagementCommands; - -typedef struct _AddressBookStatistics{ - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} AddressBookStatistics; - -typedef struct _BONGO_ALIAS_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} AliasStatistics; - -typedef struct _BONGO_ANTISPAM_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} AntiSPAMStatistics; - -typedef struct _BONGO_ANTIVIRUS_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long MessagesScanned; /* AVMV_MESSAGES_SCANNED */ - unsigned long AttachmentsScanned; /* AVMV_ATTACHMENTS_SCANNED */ - unsigned long AttachmentsBlocked; /* AVMV_ATTACHMENTS_BLOCKED */ - unsigned long VirusesFound; /* AVMV_VIRUSES_FOUND */ -} AntiVirusStatistics; - -typedef struct _BONGO_CALENDAR_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} CalendarStatistics; - -typedef struct _BONGO_CAP_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long ConnectionLimit; /* DMCMV_MAX_CONNECTION_COUNT */ -} CAPStatistics; - -typedef struct _BONGO_CONNECTION_MANAGER_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} ConnectionManagerStatistics; - -typedef struct _BONGO_FINGER_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} FingerStatistics; - -typedef struct _BONGO_IMAP_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long ConnectionLimit; /* DMCMV_MAX_CONNECTION_COUNT */ - unsigned long ConnectionsServiced; /* DMCMV_TOTAL_CONNECTIONS */ - unsigned long BadPasswords; /* DMCMV_BAD_PASSWORD_COUNT */ -} IMAPStatistics; - -typedef struct _BONGO_LIST_SERVER_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} ListServerStatistics; - -typedef struct _BONGO_NMAP_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long QueueThreads; /* DMCMV_QUEUE_THREAD_COUNT */ - - struct { - BOOL Disabled; /* NMAPMV_LOAD_MONITOR_DISABLED */ - unsigned long Interval; /* NMAPMV_LOAD_MONITOR_INTERVAL */ - } Monitor; - - struct { - unsigned long Low; /* NMAPMV_LOW_UTILIZATION_THRESHOLD */ - unsigned long High; /* NMAPMV_HIGH_UTILIZATION_THRESHOLD */ - } Utilization; - - struct { - unsigned long Concurrent; /* NMAPMV_QUEUE_LIMIT_CONCURRENT */ - unsigned long Sequential; /* NMAPMV_QUEUE_LIMIT_SEQUENTIAL */ - unsigned long Threshold; /* NMAPMV_QUEUE_LOAD_THRESHOLD */ - } Queue; - - struct { - time_t Interval; /* NMAPMV_BOUNCE_INTERVAL */ - unsigned long Maximum; /* NMAPMV_MAX_BOUNCE_COUNT */ - } Bounce; - - struct { - unsigned long Connections; /* NMAPMV_NMAP_TO_NMAP_CONNECTIONS */ - unsigned long Serviced; /* DMCMV_TOTAL_CONNECTIONS */ - unsigned long Agents; /* NMAPMV_AGENTS_SERVICED */ - } NMAP; - - struct { - unsigned long Queued; /* NMAPMV_MESSAGES_QUEUED_LOCALLY */ - unsigned long SPAMDiscarded; /* NMAPMV_SPAM_MESSAGES_DISCARDED */ - - struct { - unsigned long Count; /* NMAPMV_MESSAGES_STORED_LOCALLY */ - unsigned long Recipients; /* NMAPMV_RECIPIENTS_STORED_LOCALLY */ - unsigned long KiloBytes; /* NMAPMV_BYTES_STORED_LOCALLY */ - } Stored; - - struct { - unsigned long Local; /* NMAPMV_LOCAL_DELIVERY_FAILURES */ - unsigned long Remote; /* NMAPMV_REMOTE_DELIVERY_FAILURES */ - } Failed; - } Messages; -} NMAPStatistics; - -typedef struct _BONGO_PLUSPACK_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} PlusPackStatistics; - -typedef struct _BONGO_POP3_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long ConnectionLimit; /* DMCMV_MAX_CONNECTION_COUNT */ - unsigned long ConnectionsServiced; /* DMCMV_TOTAL_CONNECTIONS */ - unsigned long BadPasswords; /* DMCMV_BAD_PASSWORD_COUNT */ -} POP3Statistics; - -typedef struct _BONGO_PROXY_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long ConnectionsServiced; /* DMCMV_TOTAL_CONNECTIONS */ - unsigned long BadPasswords; /* DMCMV_BAD_PASSWORD_COUNT */ - unsigned long Messages; /* PROXYMV_REMOTE_MESSAGES_PULLED */ - unsigned long KiloBytes; /* PROXYMV_REMOTE_BYTES_PULLED */ -} ProxyStatistics; - -typedef struct _BONGO_RULES_SERVER_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ -} RulesServerStatistics; - -typedef struct _BONGO_SMTP_STATISTICS { - unsigned char Version[256]; /* DMCMV_VERSION */ - - struct { - unsigned long Count; /* Connection Pool Allocation Count */ - unsigned long Size; /* Connection Pool Allocation Size */ - unsigned long Pitches; /* Connection Pool Pitches */ - unsigned long Strikes; /* Connection Pool Strikes */ - } Memory; - - unsigned long ServerThreads; /* DMCMV_SERVER_THREAD_COUNT */ - unsigned long Connections; /* DMCMV_CONNECTION_COUNT */ - unsigned long Idle; /* DMCMV_IDLE_CONNECTION_COUNT */ - unsigned long ConnectionLimit; /* DMCMV_MAX_CONNECTION_COUNT */ - unsigned long QueueThreads; /* DMCMV_QUEUE_THREAD_COUNT */ - unsigned long BadPasswords; /* DMCMV_BAD_PASSWORD_COUNT */ - - struct { - struct { - unsigned long Connections; /* SMTPMV_INCOMING_SERVERS */ - unsigned long Serviced; /* SMTPMV_SERVICED_SERVERS */ - } InBound; - - struct { - unsigned long Connections; /* SMTPMV_OUTGOING_SERVERS */ - unsigned long Serviced; /* SMTPMV_CLOSED_OUT_SERVERS */ - } OutBound; - } Servers; - - struct { - unsigned long Connections; /* SMTPMV_INCOMING_QUEUE_AGENT */ - } NMAP; - - struct { - unsigned long Address; /* SMTPMV_SPAM_ADDRS_BLOCKED */ - unsigned long MAPS; /* SMTPMV_SPAM_MAPS_BLOCKED */ - unsigned long NoDNSEntry; /* SMTPMV_SPAM_NO_DNS_ENTRY */ - unsigned long Routing; /* SMTPMV_SPAM_DENIED_ROUTING */ - unsigned long Queue; /* SMTPMV_SPAM_QUEUE */ - } Blocked; - - struct { - unsigned long Count; /* SMTPMV_LOCAL_MSGS_RECEIVED */ - unsigned long Recipients; /* SMTPMV_LOCAL_RECIP_RECEIVED */ - unsigned long KiloBytes; /* SMTPMV_LOCAL_BYTES_RECEIVED */ - } Local; - - struct { - struct { - unsigned long Received; /* SMTPMV_REMOTE_RECIP_RECEIVED */ - unsigned long Stored; /* SMTPMV_REMOTE_RECIP_STORED */ - } Recipients; - - struct { - unsigned long Received; /* SMTPMV_REMOTE_BYTES_RECEIVED */ - unsigned long Stored; /* SMTPMV_REMOTE_BYTES_STORED */ - } KiloBytes; - - struct { - unsigned long Received; /* SMTPMV_REMOTE_MSGS_RECEIVED */ - unsigned long Stored; /* SMTPMV_REMOTE_MSGS_STORED */ - } Messages; - } Remote; -} SMTPStatistics; - -typedef struct _BongoStatistics { - unsigned long UpTime; - unsigned long ModuleCount; - - AddressBookStatistics AddressBook; - AliasStatistics Alias; - AntiSPAMStatistics AntiSpam; - AntiVirusStatistics AntiVirus; - CalendarStatistics Calendar; - CAPStatistics CAP; - ConnectionManagerStatistics ConnectionManager; - FingerStatistics Finger; - IMAPStatistics IMAP; - ListServerStatistics List; - NMAPStatistics NMAP; - PlusPackStatistics PlusPack; - POP3Statistics POP3; - ProxyStatistics Proxy; - RulesServerStatistics Rules; - SMTPStatistics SMTP; -} BongoStatistics; - -typedef struct _BONGO_STATISTICS { - /* Generic */ - unsigned long ModulesLoaded; - unsigned long Uptime; - unsigned long SystemLoad; - unsigned long SystemMemoryUsed; - unsigned long UnauthorizedAccess; - unsigned long WrongPassword; /* + NMStats->POP3.BadPasswords - + NMStats->IMAP.BadPasswords - + NMStats->SMTP.BadPasswords - + NMStats->Proxy.BadPasswords */ - unsigned long DeliveryFailedLocal; /* NMStats->NMAP.Messages.Failed.Local */ - unsigned long DeliveryFailedRemote; /* NMStats->NMAP.Messages.Failed.Remote */ - - /* Connections */ - unsigned long IncomingClients; /* + NMStats->POP3.Connections - + NMStats->IMAP.Connections */ - unsigned long IncomingServers; /* NMStats->SMTP.Connections */ - unsigned long ServicedClients; /* + NMStats->POP3.ConnectionsServiced - + NMStats->IMAP.ConnectionsServiced */ - unsigned long ServicedServers; /* NMStats->SMTP.Servers.InBound.Serviced */ - unsigned long OutgoingServers; /* NMStats->SMTP.Servers.OutBound.Connections */ - unsigned long ClosedOutServers; /* NMStats->SMTP.Servers.OutBound.Serviced */ - - /* NMAP Agents */ - unsigned long IncomingQueueAgents; /* NMStats->SMTP.NMAP.Connections */ - unsigned long OutgoingQueueAgents; - unsigned long CurrentStoreAgents; /* NMStats->NMAP.Connections */ - unsigned long ServicedStoreAgents; /* NMStats->NMAP.NMAP.Agents */ - unsigned long CurrentNMAPtoNMAPAgents; /* NMStats->NMAP.NMAP.Connections */ - unsigned long ServicedNMAPtoNMAPAgents; /* NMStats->NMAP.NMAP.Serviced */ - - /* Messages */ - unsigned long MsgReceivedLocal; /* NMStats->SMTP.Local.Count */ - unsigned long MsgReceivedRemote; /* NMStats->SMTP.Remote.Messages.Received */ - unsigned long MsgStoredLocal; /* NMStats->NMAP.Messages.Stored.Count */ - unsigned long MsgStoredRemote; /* NMStats->SMTP.Remote.Messages.Stored */ - unsigned long MsgQueuedLocal; /* NMStats->NMAP.Messages.Queued */ - unsigned long MsgQueuedRemote; - - /* Bytes */ - unsigned long ByteReceivedLocal; /* NMStats->SMTP.Local.KiloBytes */ - unsigned long ByteReceivedRemote; /* NMStats->SMTP.Remote.KiloBytes.Received */ - unsigned long ByteStoredLocal; /* NMStats->NMAP.Messages.Stored.KiloBytes */ - unsigned long ByteStoredRemote; /* NMStats->SMTP.Remote.KiloBytes.Stored */ - unsigned long ByteReceivedCount; /* NMStats->SMTP.Local.Count - + NMStats->SMTP.Remote.Messages.Received */ - unsigned long ByteStoredCount; /* NMStats->NMAP.Messages.Stored.Count - + NMStats->SMTP.Remote.KiloBytes.Stored */ - - /* Recipients */ - unsigned long RcptReceivedLocal; /* NMStats->SMTP.Local.Recipients */ - unsigned long RcptReceivedRemote; /* NMStats->SMTP.Remote.Recipients.Received */ - unsigned long RcptStoredLocal; /* NMStats->NMAP.Messages.Stored.Recipients */ - unsigned long RcptStoredRemote; /* NMStats->SMTP.Remote.Recipients.Stored */ -} StatisticsStruct; - -typedef struct _ANTISPAM_STATISTICS { - unsigned long QueueSpamBlocked; /* NMStats->NMAP.Messages.SPAMDiscared - + NMStats->SMTP.Blocked.Queue */ - unsigned long AddressBlocked; /* NMStats->SMTP.Blocked.Address */ - unsigned long MAPSBlocked; /* NMStats->SMTP.Blocked.MAPS */ - unsigned long DeniedRouting; /* NMStats->SMTP.Blocked.Routing */ - unsigned long NoDNSEntry; /* NMStats->SMTP.Blocked.NoDNSEntry */ - unsigned long MessagesScanned; /* NMStats->AntiVirus.MessagesScanned */ - unsigned long AttachmentsScanned; /* NMStats->AntiVirus.AttachmentsScanned */ - unsigned long AttachmentsBlocked; /* NMStats->AntiVirus.AttachmentsBlocked */ - unsigned long VirusesFound; /* NMStats->AntiVirus.VirusesFound */ - unsigned long VirusesBlocked; - unsigned long VirusesCured; -} AntispamStatisticsStruct; - -#define NMSTATS_TO_STATS(n, s) \ - if (s) { \ - memset((s), 0, sizeof(StatisticsStruct)); \ - } \ - if (n) { \ - if (s) { \ - (s)->Uptime = (n)->UpTime; \ - (s)->WrongPassword = (n)->POP3.BadPasswords \ - + (n)->IMAP.BadPasswords \ - + (n)->SMTP.BadPasswords \ - + (n)->Proxy.BadPasswords; \ - (s)->DeliveryFailedLocal = (n)->NMAP.Messages.Failed.Local; \ - (s)->DeliveryFailedRemote = (n)->NMAP.Messages.Failed.Remote; \ - (s)->IncomingClients = + (n)->POP3.Connections \ - + (n)->IMAP.Connections; \ - (s)->IncomingServers = (n)->SMTP.Connections; \ - (s)->ServicedClients = (n)->POP3.ConnectionsServiced \ - + (n)->IMAP.ConnectionsServiced; \ - (s)->ServicedServers = (n)->SMTP.Servers.InBound.Serviced; \ - (s)->OutgoingServers = (n)->SMTP.Servers.OutBound.Connections; \ - (s)->ClosedOutServers = (n)->SMTP.Servers.OutBound.Serviced; \ - (s)->IncomingQueueAgents = (n)->SMTP.NMAP.Connections; \ - (s)->CurrentStoreAgents = (n)->NMAP.Connections; \ - (s)->ServicedStoreAgents = (n)->NMAP.NMAP.Agents; \ - (s)->CurrentNMAPtoNMAPAgents = (n)->NMAP.NMAP.Connections; \ - (s)->ServicedNMAPtoNMAPAgents = (n)->NMAP.NMAP.Serviced; \ - (s)->MsgReceivedLocal = (n)->SMTP.Local.Count; \ - (s)->MsgReceivedRemote = (n)->SMTP.Remote.Messages.Received; \ - (s)->MsgStoredLocal = (n)->NMAP.Messages.Stored.Count; \ - (s)->MsgStoredRemote = (n)->SMTP.Remote.Messages.Stored; \ - (s)->MsgQueuedLocal = (n)->NMAP.Messages.Queued; \ - (s)->ByteReceivedLocal = (n)->SMTP.Local.KiloBytes; \ - (s)->ByteReceivedRemote = (n)->SMTP.Remote.KiloBytes.Received; \ - (s)->ByteStoredLocal = (n)->NMAP.Messages.Stored.KiloBytes; \ - (s)->ByteStoredRemote = (n)->SMTP.Remote.KiloBytes.Stored; \ - (s)->ByteReceivedCount = (n)->SMTP.Local.Count \ - + (n)->SMTP.Remote.Messages.Received; \ - (s)->ByteStoredCount = (n)->NMAP.Messages.Stored.Count \ - + (n)->SMTP.Remote.KiloBytes.Stored; \ - (s)->RcptReceivedLocal = (n)->SMTP.Local.Recipients; \ - (s)->RcptReceivedRemote = (n)->SMTP.Remote.Recipients.Received; \ - (s)->RcptStoredLocal = (n)->NMAP.Messages.Stored.Recipients; \ - (s)->RcptStoredRemote = (n)->SMTP.Remote.Recipients.Stored; \ - } \ - } - -#define NMSTATS_TO_SPAMSTATS(n, sp) \ - if (sp) { \ - memset((sp), 0, sizeof(AntispamStatisticsStruct)); \ - } \ - if (n) { \ - if (sp) { \ - (sp)->QueueSpamBlocked = (n)->NMAP.Messages.SPAMDiscarded \ - + (n)->SMTP.Blocked.Queue; \ - (sp)->AddressBlocked = (n)->SMTP.Blocked.Address; \ - (sp)->MAPSBlocked = (n)->SMTP.Blocked.MAPS; \ - (sp)->DeniedRouting = (n)->SMTP.Blocked.Routing; \ - (sp)->NoDNSEntry = (n)->SMTP.Blocked.NoDNSEntry; \ - (sp)->MessagesScanned = (n)->AntiVirus.MessagesScanned; \ - (sp)->AttachmentsScanned = (n)->AntiVirus.AttachmentsScanned; \ - (sp)->AttachmentsBlocked = (n)->AntiVirus.AttachmentsBlocked; \ - (sp)->VirusesFound = (n)->AntiVirus.VirusesFound; \ - } \ - } - -#define PVCSRevisionToVersion(pvcs, version) \ - { unsigned char *delimPTR; \ - delimPTR = strchr((pvcs), ':'); \ - if (delimPTR) { \ - do { \ - delimPTR++; \ - } while (isspace(*delimPTR)); \ - strcpy((version), delimPTR); \ - delimPTR = strchr((version), '$'); \ - if (delimPTR) { \ - do { \ - delimPTR--; \ - } while (isspace(*delimPTR)); \ - delimPTR[1] = '\0'; \ - } else { \ - strcpy((version), "0.0"); \ - } \ - } else { \ - strcpy((version), "0.0"); \ - } \ - } - -/* Response Codes: - - 10XX Success - 11XX State - - 20XX Server Errors - 21XX Requestor Errors -*/ -#define DMCMSG1000OK "1000 OK\r\n" -#define DMCMSG1000OK_LEN 9 - -#define DMCMSG1001RESPONSES_COMMING "1001-%d responses to follow.\r\n" - -#define DMCMSG1001BYTES_COMING "1001-%d octets to follow.\r\n" - -#define DMCMSG1002SALT_COMING "1002-Salt to follow.\r\n" -#define DMCMSG1002SALT_COMING_LEN 22 - -#define DMCMSG1002SIGNATURE_COMING "1002-Agent signature to follow.\r\n" -#define DMCMSG1002SIGNATURE_COMING_LEN 33 - -#define DMCMSG1003SEND_BYTES "1003-Send %d octets.\r\n" - -#define DMCMSG1003SEND_VARIABLES "1003-Send variables.\r\n" -#define DMCMSG1003SEND_VARIABLES_LEN 22 - -#define DMCMSG1003SEND_COMMANDS "1003-Send commands.\r\n" -#define DMCMSG1003SEND_COMMANDS_LEN 21 - -#define DMCMSG1004NEGOTIATE_TLS "1001-Begin TLS negotiation.\r\n" -#define DMCMSG1004NEGOTIATE_TLS_LEN 29 - -#define DMCMSG1003SEND_VALUE "1003-Send value.\r\n" -#define DMCMSG1003SEND_VALUE_LEN 18 - -#define DMCMSG1100USE_AUTH ": Authentication required, use LOGIN\r\n" -#define DMCMSG1100USE_AUTH_LEN 38 - -#define DMCMSG1101AUTHORIZED ": Authorized [%s]\r\n" - -#define DMCMSG1102MANAGING_SERVER ": Managing \"%s\"\r\n" - -#define DMCMSG1102MANAGING_AGENT ": Managing \"%s\" [\"%s\"]\r\n" - -#define DMCMSG1103BAD_STATE ": Invalid state; use EXIT\r\n" -#define DMCMSG1103BAD_STATE_LEN 27 - -#define DMCMSG1104SERVER_DEREGISTERED "1104 Server has deregistered.\r\n" -#define DMCMSG1104SERVER_DEREGISTERED_LEN 31 - -#define DMCMSG1104AGENT_DEREGISTERED "1104 Agent has deregistered.\r\n" -#define DMCMSG1104AGENT_DEREGISTERED_LEN 30 - -#define DMCMSG2000NOMEMORY "2000 Out of memory.\r\n" -#define DMCMSG2000NOMEMORY_LEN 21 - -#define DMCMSG2000NOT_IMPLEMENTED "2000 Command not implemented.\r\n" -#define DMCMSG2000NOT_IMPLEMENTED_LEN 31 - -#define DMCMSG2001NOT_MANAGER "2001 Not a configured manager.\r\n" -#define DMCMSG2001NOT_MANAGER_LEN 32 - -#define DMCMSG2001NEGOTIATE_FAILED "2001 TLS negotiation failed.\r\n" -#define DMCMSG2001NEGOTIATE_FAILED_LEN 30 - -#define DMCMSG2002READ_ERROR "2002 Error reading variable value.\r\n" -#define DMCMSG2002READ_ERROR_LEN 36 - -#define DMCMSG2002WRITE_ERROR "2002 Error writing variable value.\r\n" -#define DMCMSG2002WRITE_ERROR_LEN 36 - -#define DMCMSG2003CONNECTION_CLOSED "2003 Connection with resource interrupted.\r\n" -#define DMCMSG2003CONNECTION_CLOSED_LEN 44 - -#define DMCMSG2004SERVER_DOWN "2004 Server shutting down.\r\n" - -#define DMCMSG2005SERVER_TOO_MANY "2005 Connection limit reached." - -#define DMCMSG2006SERVER_NO_ACCEPT "2006 Connections not accepted at this time." - -#define DMCMSG2100BADCOMMAND "2100 Command unrecognized.\r\n" -#define DMCMSG2100BADCOMMAND_LEN 28 - -#define DMCMSG2100BADRESPONSE "2100 Unexpected resource response of \"%s\".\r\n" - -#define DMCMSG2101BADPARAMS "2101 Invalid command parameters.\r\n" -#define DMCMSG2101BADPARAMS_LEN 34 - -#define DMCMSG2102BADSTATE "2102 Invalid connection state for command.\r\n" -#define DMCMSG2102BADSTATE_LEN 44 - -#define DMCMSG2103RESET "2103 Already managing; use RESET to stop managing.\r\n" -#define DMCMSG2103RESET_LEN 52 - -#define DMCMSG2104NOT_WRITEABLE "2104 Variable not settable.\r\n" -#define DMCMSG2104NOT_WRITEABLE_LEN 29 - -#define DMCMSG2105PORT_DISABLED "2105 No communications port configured.\r\n" -#define DMCMSG2105PORT_DISABLED_LEN 41 - -#define DMCMSG2106CONNECT_FAILED "2106 Connection attempt failed.\r\n" -#define DMCMSG2106CONNECT_FAILED_LEN 33 - -#define DMCMSG3242BADAUTH "3242 Bad authentication!\r\n" -#define DMCMSG2106BADAUTH_LEN 26 - -/* Common Managed Variables */ -#define DMCMV_CONNECTION_COUNT "Connection Count" -#define DMCMV_CONNECTION_COUNT_HELP "Count of active connection threads.\r\n" - -#define DMCMV_IDLE_CONNECTION_COUNT "Idle Connection Count" -#define DMCMV_IDLE_CONNECTION_COUNT_HELP "Count of idle connection threads.\r\n" - -#define DMCMV_MAX_CONNECTION_COUNT "Maximum Connections" -#define DMCMV_MAX_CONNECTION_COUNT_HELP "The maximum number of connections allowed.\r\n" - -#define DMCMV_SERVER_THREAD_COUNT "Server Thread Count" -#define DMCMV_SERVER_THREAD_COUNT_HELP "Count of active agent server threads.\r\n" - -#define DMCMV_QUEUE_THREAD_COUNT "Queue Thread Count" -#define DMCMV_QUEUE_THREAD_COUNT_HELP "Count of active message queue processing threads.\r\n" - -#define DMCMV_HOSTNAME "Host Name" -#define DMCMV_HOSTNAME_HELP "The agent's configured host name.\r\n" - -#define DMCMV_OFFICIAL_NAME "Official Name" -#define DMCMV_OFFICIAL_NAME_HELP "The official domain name for the agent.\r\n" - -#define DMCMV_REVISIONS "Revisions" -#define DMCMV_REVISIONS_HELP "Report the agent's source file revision information.\r\n" - -#define DMCMV_VERSION "Version" -#define DMCMV_VERSION_HELP "Report the agent's version information.\r\n" - -#define DMCMV_DBF_DIRECTORY "DBF Directory" -#define DMCMV_DBF_DIRECTORY_HELP "The agent's configured DBF directory {What does DBF stand for?}.\r\n" - -#define DMCMV_NLS_DIRECTORY "NLS Directory" -#define DMCMV_NLS_DIRECTORY_HELP "The agent's configured NLS directory {what does NLS stand for?}.\r\n" - -#define DMCMV_MAIL_DIRECTORY "Mail Directory" -#define DMCMV_MAIL_DIRECTORY_HELP "The agent's configured Mail directory.\r\n" - -#define DMCMV_SCMS_DIRECTORY "SCMS Directory" -#define DMCMV_SCMS_DIRECTORY_HELP "The agent's configured Single Copy Message Store directory.\r\n" - -#define DMCMV_SPOOL_DIRECTORY "Spool Directory" -#define DMCMV_SPOOL_DIRECTORY_HELP "The agent's configured Spool directory.\r\n" - -#define DMCMV_WORK_DIRECTORY "Work Directory" -#define DMCMV_WORK_DIRECTORY_HELP "The configured working directory used by the agent.\r\n" - -#define DMCMV_NMAP_QUEUE "Registered NMAP Queue" -#define DMCMV_NMAP_QUEUE_HELP "The NMAP Queue the agent registered for.\r\n" - -#define DMCMV_NMAP_ADDRESS "NMAP Address" -#define DMCMV_NMAP_ADDRESS_HELP "The address of the NMAP server to which the agent registered.\r\n" - -#define DMCMV_NOTIFY_POSTMASTER "Notify Postmaster" - -#define DMCMV_POSTMASTER "PostMaster" -#define DMCMV_POSTMASTER_HELP "The messaging user desginated as the PostMaster.\r\n" - -#define DMCMV_RECEIVER_DISABLED "Block Connections" -#define DMCMV_RECEIVER_DISABLED_HELP "Set to TRUE to block connection attempts to the agent.\r\n" - -#define DMCMV_MESSAGE "Message" - -#define DMCMV_SESSION_COUNT "Session Count" -#define DMCMV_SESSION_COUNT_HELP "Number of active sessions.\r\n" - -#define DMCMV_TOTAL_CONNECTIONS "Connections Serviced" -#define DMCMV_TOTAL_CONNECTIONS_HELP "Number of connections serviced by the agent.\r\n" - -#define DMCMV_BAD_PASSWORD_COUNT "Bad Passwords" -#define DMCMV_BAD_PASSWORD_COUNT_HELP "Number of bad passwords received by the agent.\r\n" - -#define DMCMV_UTC_OFFSET "UTC Offset" -#define DMCMV_UTC_OFFSET_HELP "Universal Time-Coordinated offset used by the agent.\r\n" - -#define DMCMV_SSL_ENABLED "Allow SSL" -#define DMCMV_SSL_ENABLED_HELP "Support SSL connections.\r\n" - -#define DMCMV_PORT "Port" -#define DMCMV_PORT_HELP "TCP port used to receive requests.\r\n" - -#define DMCMV_SSL_PORT "SSL Port" -#define DMCMV_SSL_PORT_HELP "TCP port used to receive SSL or TLS encrypted requests.\r\n" - -#define DMCMV_MESSAGING_SERVER_DN "Server DN" -#define DMCMV_MESSAGING_SERVER_DN_HELP "The complete directory name for the messaging server object.\r\n" - -#define DMCMV_CLIENT_POOL_STATISTICS "Client Pool Statistics" -#define DMCMV_CLIENT_POOL_STATISTICS_HELP "Client memory pool usage statistics" - -#define DMCMV_MEM_STATISTICS "Mem Statistics" -#define DMCMV_MEM_STATISTICS_HELP "Memory Manager usage statistics" - -/* Common Managed Commands */ -#define DMCMC_UNKOWN_COMMAND "Unknown agent command.\r\n" - -#define DMCMC_HELP "Help" -#define DMCMC_HELP_HELP "Help Stats Unload\r\n" - -#define DMCMC_SHUTDOWN "Shutdown" -#define DMCMC_SHUTDOWN_HELP "Initiate an agent shutdown and automatic unload of the module.\r\n" - -#define DMCMC_STATS "Stats" -#define DMCMC_STATS_HELP "Agent name, version and current values of statistics variables.\r\n" - -#define DMCMC_DUMP_MEMORY_USAGE "Memory" -#define DMCMC_DUMP_MEMORY_USAGE_HELP "Summary of memory usage by address space.\r\n" - -#define DMCMC_CONN_TRACE_USAGE "ConnTrace" -#define DMCMC_CONN_TRACE_USAGE_HELP "Used to designate which network events should be traced. \r\n\r\nUsage: 'CMD CONNTRACE FLAG <+|-> [ <+|->...]'\r\n where flags are:\r\n ALL, OUTBOUND, INBOUND, NMAP, CONNECT, CLOSE,\r\n SSLCONNECT, SSLSHUTDOWN, READ, WRITE, ERROR\r\n\r\nUsage: 'CMD CONNTRACE ADDR (<+|->ALL | <+|-> ...)'\r\n" - -/* Address Book Managed Variables */ -#define ADBKMV_LDAP_LISTEN_PORT "LDAP Port" -#define ADBKMV_LDAP_LISTEN_PORT_HELP "Agent TCP port to receive LDAP requests.\r\n" - -#define ADBKMV_LDAP_SSL_LISTEN_PORT "LDAP SSL Port" -#define ADBKMV_LDAP_SSL_LISTEN_PORT_HELP "Agent TCP port to receive LDAP SSL encrypted requests.\r\n" - -#define ADBKMV_LDIF_DATABASE "LDIF Database" -#define ADBKMV_LDIF_DATABASE_HELP "The agent's LDIF database filename.\r\n" - -#define ADBKMV_LDIF_WORKBASE "LDIF Workbase" -#define ADBKMV_LDIF_WORKBASE_HELP "The agent's LDIF work database filename.\r\n" - -#define ADBKMV_DBCYCLE_TIME "Database Interval" -#define ADBKMV_DBCYCLE_TIME_HELP "The agent's interval between directory dredges.\r\n" - -#define ADBKMV_DO_LDAP "LDAP Enabled" -#define ADBKMV_DO_LDAP_HELP "Enable the agent's LDAP server.\r\n" - -#define ADBKMV_DO_LDIF "LDIF Enabled" -#define ADBKMV_DO_LDIF_HELP "Enable the agent's LDIF export.\r\n" - -#define ADBKMV_DO_PERSONAL "Personal Lookup Enabled" -#define ADBKMV_DO_PERSONAL_HELP "Enable personal address book entry lookup.\r\n" - -#define ADBKMV_LDAP_REQUIRE_BASEDN "Require Base Name" -#define ADBKMV_LDAP_REQUIRE_BASEDN_HELP "Require a base name for LDAP searches.\r\n" - -#define ADBKMV_LDAP_REQUIRE_AUTH "Require LDAP Authentication" -#define ADBKMV_LDAP_REQUIRE_AUTH_HELP "Require LDAP authenticate for LDAP searches.\r\n" - -#define ADBKMV_USE_USER_BASEDN "Use User Base Name" -#define ADBKMV_USE_USER_BASEDN_HELP "Use the user's base name as the LDAP base name.\r\n" - -/* Alias Managed Variables */ -#define ALASMV_DO_FIRSTLAST "Enable FirstLast" -#define ALASMV_DO_FIRSTLAST_HELP "Enable creation of \"FirstLast\" alias names.\r\n" - -#define ALASMV_DO_FLASTNAME "Enable FLastname" -#define ALASMV_DO_FLASTNAME_HELP "Enable creation of \"FLastname\" alias names.\r\n" - -#define ALASMV_DO_FIRSTDLAST "Enable FirstDLast" -#define ALASMV_DO_FIRSTDLAST_HELP "Enable creation of \"FirstDLast\" alias names.\r\n" - -#define ALASMV_DO_FULLDOT "Enable FullDot" -#define ALASMV_DO_FULLDOT_HELP "Enable creation of \"FullDot\" alias names.\r\n" - -#define ALASMV_DO_FULLUNDER "Enable FullUnder" -#define ALASMV_DO_FULLUNDER_HELP "Enable creation of \"FullUnder\" alias names.\r\n" - -#define ALASMV_AUTO_POPULATE "Enable AutoPopulation" -#define ALASMV_AUTO_POPULATE_HELP "Enable the auto population of messaging users directory email address.\r\n" - -#define ALASMV_POPULATE_DEFAULT "Enable Populate Defaults" -#define ALASMV_POPULATE_DEFAULT_HELP "Use the messaging username and official domain as the directory object's email address.\r\n" - -#define ALASMV_POPULATE_FIRSTLAST "Enable Populate FirstLast" -#define ALASMV_POPULATE_FIRSTLAST_HELP "Populate directory entries with \"FirstLast\".\r\n" - -#define ALASMV_POPULATE_FLASTNAME "Enable Populate FLastname" -#define ALASMV_POPULATE_FLASTNAME_HELP "Populate directory entries with \"FLastname\".\r\n" - -#define ALASMV_POPULATE_FIRSTDLAST "Enable Populate FirstDLast" -#define ALASMV_POPULATE_FIRSTDLAST_HELP "Populate directory entries with \"FirstDLast\".\r\n" - -#define ALASMV_POPULATE_FULLDOT "Enable Populate FullDot" -#define ALASMV_POPULATE_FULLDOT_HELP "Populate directory entries with \"FullDot\".\r\n" - -#define ALASMV_POPULATE_FULLUNDER "Enable Populate FullUnder" -#define ALASMV_POPULATE_FULLUNDER_HELP "Populate directory entries with \"FullUnder\".\r\n" - -#define ALASMV_DBCYCLE_TIME "Database Interval" -#define ALASMV_DBCYCLE_TIME_HELP "The agent's interval in seconds between directory dredges.\r\n" - -/* AntiSPAM Managed Variables */ -#define ASPMMV_DO_RTS "Enable RTS" -#define ASPMMV_DO_RTS_HELP "Enable return SPAM to sender.\r\n" - -#define ASPMMV_NOTIFY_POSTMASTER "Notify the PostMaster of a SPAM message.\r\n" - -#define ASPMMV_BLACK_LIST_ARRAY "BlackList" -#define ASPMMV_BLACK_LIST_ARRAY_HELP "The agent's current list of known SPAM hosts.\r\n" - -/* AntiVirus Managed Variables */ -#define AVMV_DO_INCOMING "Enable Incoming" -#define AVMV_DO_INCOMING_HELP "Enable anti-virus scanning of all incoming messages.\r\n" - -#define AVMV_NOTIFY_SENDER "Notify Sender" -#define AVMV_NOTIFY_SENDER_HELP "Notify sender of virus infected messages.\r\n" - -#define AVMV_NOTIFY_RECIPIENT "Notify Recipient" -#define AVMV_NOTIFY_RECIPIENT_HELP "Notify recipient of virus infected messages.\r\n" - -#define AVMV_CARRIER_SCAN_HOST "Carrier Scan Host" -#define AVMV_CARRIER_SCAN_HOST_HELP "TCP/IP address of the anti-virus scanner.\r\n" - -#define AVMV_CARRIER_SCAN_PORT "Carrier Scan Port" -#define AVMV_CARRIER_SCAN_PORT_HELP "UDP port of the anti-virus scanner.\r\n" - -#define AVMV_WORK_DIRECTORY "Work Directory" -#define AVMV_WORK_DIRECTORY_HELP "The agent's configured working directory.\r\n" - -#define AVMV_PATTERN_FILE_DIRECTORY "Pattern File Directory" -#define AVMV_PATTERN_FILE_DIRECTORY_HELP "The agent's pattern file directory for the anti-virus scanner.\r\n" - -#define AVMV_MESSAGES_SCANNED "Messages Scanned" -#define AVMV_MESSAGES_SCANNED_HELP "The number of messages sent to the anti-virus scanner.\r\n" - -#define AVMV_ATTACHMENTS_SCANNED "Attachments Scanned" -#define AVMV_ATTACHMENTS_SCANNED_HELP "The number of attachments sent to the anti-virus scanner.\r\n" - -#define AVMV_ATTACHMENTS_BLOCKED "Attachments Blocked" -#define AVMV_ATTACHMENTS_BLOCKED_HELP "The number of attachments blocked due to virus infections.\r\n" - -#define AVMV_VIRUSES_FOUND "Virus Count" -#define AVMV_VIRUSES_FOUND_HELP "The number of virus infections encountered.\r\n" - -/* Finger Managed Variables */ -#define FNGRMV_FINGER_MESSAGE_HELP "The default finger message.\r\n" - -/* Forward Managed Variables */ -#define FWDMV_FORWARD_MESSAGE_HELP "The default forward message.\r\n" - -/* Connection Manager Managed Variables */ -#define CMMV_MAX_AGE "Maximum Age" -#define CMMV_MAX_AGE_HELP "The maximum time in seconds to retain entries in the connection table.\r\n" - -/* IMAP Managed Variables */ -#define IMAPMV_ACL_ENABLED "ACL Supported" -#define IMAPMV_ACL_ENABLED_HELP "Set to TRUE if the IMAP ACL extension is supported.\r\n" - -#define IMAPMV_MANAGEMENT_URL "Management URL" -#define IMAPMV_MANAGEMENT_URL_HELP "Account URL reported in the IMAP Netscape extension command.\r\n" - -/* List Server Managed Variables */ -#define LISTMV_DIGEST_HOUR "Digest Hour" -#define LISTMV_DIGEST_HOUR_HELP "The hour to begin digest enumeration through the directory (24 hour format).\r\n" - -#define LISTMV_SERVER_NAME "List Server Name" -#define LISTMV_SERVER_NAME_HELP "The server name used by the list.\r\n" - -#define LISTMV_BOUNCE_NAME "List Bounce Name" -#define LISTMV_BOUNCE_NAME_HELP "The bounce name used by the list.\r\n" - -#define LISTMV_MODERATOR_NAME "List Moderator Name" -#define LISTMV_MODERATOR_NAME_HELP "The moderator name used by the list.\r\n" - -#define LISTMV_CONTROL_NAME "List Control Name" -#define LISTMV_CONTROL_NAME_HELP "The control name used by the list.\r\n" - -/* NMAP Managed Variables */ -#define NMAPMV_QUEUE_SLEEP_INTERVAL "Queue Sleep Interval" -#define NMAPMV_QUEUE_SLEEP_INTERVAL_HELP "The maximum number of seconds to sleep before restarting after completing a pass through the queue.\r\n" - -#define NMAPMV_BYTES_PER_BLOCK "Bytes Per Block" -#define NMAPMV_BYTES_PER_BLOCK_HELP "The number of bytes per block for the mail store on this host.\r\n" - -#define NMAPMV_TRUSTED_HOSTS "Trusted Hosts" -#define NMAPMV_TRUSTED_HOSTS_HELP "The list of IP addresses trusted by the agent.\r\n" - -#define NMAPMV_TRUSTED_HOST_COUNT "Trusted Hosts Count" -#define NMAPMV_TRUSTED_HOST_COUNT_HELP "The count of trusted hosts for the agent.\r\n" - -#define NMAPMV_SCMS_USER_THRESHOLD "SCMS Recipient Threshold" -#define NMAPMV_SCMS_USER_THRESHOLD_HELP "The minimum number of recipients required to consider SCMS usage.\r\n" - -#define NMAPMV_SCMS_SIZE_THRESHOLD "SCMS Size Threshold" -#define NMAPMV_SCMS_SIZE_THRESHOLD_HELP "The minimum message size required to consider SCMS usage.\r\n" - -#define NMAPMV_USE_SYSTEM_QUOTA "Enable System Quota" -#define NMAPMV_USE_SYSTEM_QUOTA_HELP "Enforce the configured system quota for users with no quota.\r\n" - -#define NMAPMV_USE_USER_QUOTA "Enable User Quota" -#define NMAPMV_USE_USER_QUOTA_HELP "Set to TRUE to enforce the user's configured quota.\r\n" - -#define NMAPMV_QUOTA_MESSAGE "Quota Message" -#define NMAPMV_QUOTA_MESSAGE_HELP "The message that will be sent when a quota is reached.\r\n" - -#define NMAPMV_QUOTA_WARNING "Quota Warning" -#define NMAPMV_QUOTA_WARNING_HELP "The message sent when a user is within 10 percent of the quota limit.\r\n" - -#define NMAPMV_MINIMUM_FREE_SPACE "Minimum Free Space" -#define NMAPMV_MINIMUM_FREE_SPACE_HELP "The minimum amount of free space in bytes before rejecting incoming messages.\r\n" - -#define NMAPMV_DISK_SPACE_LOW "Disk Space Low" -#define NMAPMV_DISK_SPACE_LOW_HELP "Set to TRUE to indicate that a message queue is low on disk space.\r\n" - -#define NMAPMV_DO_DEFERRED_DELIVERY "Enable Deferred Delivery" -#define NMAPMV_DO_DEFERRED_DELIVERY_HELP "Set to TRUE to enable support for deferred delivery during the configured time of day.\r\n" - -#define NMAPMV_LOAD_MONITOR_DISABLED "Disable Load Monitor" -#define NMAPMV_LOAD_MONITOR_DISABLED_HELP "Set to TRUE to disable the NMAP load monitor.\r\n" - -#define NMAPMV_LOAD_MONITOR_INTERVAL "Load Monitor Interval" -#define NMAPMV_LOAD_MONITOR_INTERVAL_HELP "The number of seconds between checking the host load.\r\n" - -#define NMAPMV_LOW_UTILIZATION_THRESHOLD "Low Utilization Threshold" -#define NMAPMV_LOW_UTILIZATION_THRESHOLD_HELP "The low utilization watermark used by the load monitor.\r\n" - -#define NMAPMV_HIGH_UTILIZATION_THRESHOLD "High Utilization Threshold" -#define NMAPMV_HIGH_UTILIZATION_THRESHOLD_HELP "The high utilization watermark used by the load monitor.\r\n" - -#define NMAPMV_QUEUE_LOAD_THRESHOLD "Queue Threshold" -#define NMAPMV_QUEUE_LOAD_THRESHOLD_HELP "The maximum number of queued messages before entering sequential message processing.\r\n" - -#define NMAPMV_NEW_SHARE_MESSAGE "Share Message" -#define NMAPMV_NEW_SHARE_MESSAGE_HELP "The message that will be sent to a user that is granted a shared resource.\r\n" - -#define NMAPMV_USER_NAMESPACE_PREFIX "User NameSpace" -#define NMAPMV_USER_NAMESPACE_PREFIX_HELP "The IMAP user namespace extension prefix.\r\n" - -#define NMAPMV_QUEUE_LIMIT_CONCURRENT "Concurrent Limit" -#define NMAPMV_QUEUE_LIMIT_CONCURRENT_HELP "The concurrent thread limit for queued message processing.\r\n" - -#define NMAPMV_QUEUE_LIMIT_SEQUENTIAL "Sequential Limit" -#define NMAPMV_QUEUE_LIMIT_SEQUENTIAL_HELP "The sequential thread limit for queued message processing.\r\n" - -#define NMAPMV_RTS_HANDLING "RTS Handling" -#define NMAPMV_RTS_HANDLING_HELP "The current RTS handling flags. Flag value of '1' indicates the message should be returned; flag value '2' indicates the message should be copied to the PostMaster.\r\n" - -#define NMAPMV_RTS_MAX_BODY_SIZE "RTS Body Size" -#define NMAPMV_RTS_MAX_BODY_SIZE_HELP "The maximum number of bytes in the message body to be copied into a message that is returned to the sender.\r\n" - -#define NMAPMV_FORWARD_UNDELIVERABLE_ADDR "Forward Undeliverable Address" -#define NMAPMV_FORWARD_UNDELIVERABLE_ADDR_HELP "The address to which forward undeliverable messages should be sent.\r\n" - -#define NMAPMV_FORWARD_UNDELIVERABLE "Forward Undeliverable" -#define NMAPMV_FORWARD_UNDELIVERABLE_HELP "Set to TRUE to forward undeliverable messages.\r\n" - -#define NMAPMV_BLOCK_RTS_SPAM "Block RTS SPAM" -#define NMAPMV_BLOCK_RTS_SPAM_HELP "Set to TRUE to discard queued return to sender messages.\r\n" - -#define NMAPMV_BOUNCE_INTERVAL "Bounce Interval" -#define NMAPMV_BOUNCE_INTERVAL_HELP "The interval used when determining if an excessive number of bounce messages are being queued.\r\n" - -#define NMAPMV_MAX_BOUNCE_COUNT "Max Bounce Count" -#define NMAPMV_MAX_BOUNCE_COUNT_HELP "The maximum number of bounce messages to queue during the bounce interval.\r\n" - -#define NMAPMV_NMAP_TO_NMAP_CONNECTIONS "NMAP to NMAP" -#define NMAPMV_NMAP_TO_NMAP_CONNECTIONS_HELP "The count of current NMAP to NMAP connections.\r\n" - -#define NMAPMV_BYTES_STORED_LOCALLY "Bytes Stored Locally" -#define NMAPMV_BYTES_STORED_LOCALLY_HELP "Number of kilobytes stored in the local mail store.\r\n" - -#define NMAPMV_MESSAGES_STORED_LOCALLY "Messages Stored" -#define NMAPMV_MESSAGES_STORED_LOCALLY_HELP "The count of messages stored in the local mail store.\r\n" - -#define NMAPMV_RECIPIENTS_STORED_LOCALLY "Recipients Stored" -#define NMAPMV_RECIPIENTS_STORED_LOCALLY_HELP "The count of recipients stored in the local mail store.\r\n" - -#define NMAPMV_MESSAGES_QUEUED_LOCALLY "Messages Queued" -#define NMAPMV_MESSAGES_QUEUED_LOCALLY_HELP "The count of messages queued in the spool directory.\r\n" - -#define NMAPMV_SPAM_MESSAGES_DISCARDED "SPAM Discarded" -#define NMAPMV_SPAM_MESSAGES_DISCARDED_HELP "The count of SPAM messages discarded.\r\n" - -#define NMAPMV_LOCAL_DELIVERY_FAILURES "Delivery Failures" -#define NMAPMV_LOCAL_DELIVERY_FAILURES_HELP "The count of failed local delivery attempts.\r\n" - -#define NMAPMV_REMOTE_DELIVERY_FAILURES "Remote Delivery Failures" -#define NMAPMV_REMOTE_DELIVERY_FAILURES_HELP "The count of failed remote delivery attempts.\r\n" - -#define NMAPMV_REGISTERED_AGENTS_ARRAY "Registered Agents" -#define NMAPMV_REGISTERED_AGENTS_ARRAY_HELP "The currently registered NMAP agents.\r\n" - -#define NMAPMV_AGENTS_SERVICED "Agents Serviced" -#define NMAPMV_AGENTS_SERVICED_HELP "The number of NMAP agents serviced.\r\n" - -/* PlusPack Managed Variables */ -#define PPACKMV_SIGNATURE "Signature" -#define PPACKMV_SIGNATURE_HELP "The text signature to be appended to all outbound messages.\r\n" - -#define PPACKMV_HTML_SIGNATURE "HTML Signature" -#define PPACKMV_HTML_SIGNATURE_HELP "The HTML signature to be appended to all outbound messages.\r\n" - -#define PPACKMV_BIGBROTHER_USER "Global Message Copy User Name" -#define PPACKMV_BIGBROTHER_USER_HELP "The name of the messaging user to receive copied messages.\r\n" - -#define PPACKMV_BIGBROTHER_USE_MAILBOX "Use Global Message Copy" -#define PPACKMV_BIGBROTHER_USE_MAILBOX_HELP "Set to TRUE to copy all outbound messages to another mailbox.\r\n" - -#define PPACKMV_BIGBROTHER_MAILBOX "Global Message Copy Mailbox" -#define PPACKMV_BIGBROTHER_MAILBOX_HELP "The mailbox to which all inbound messages will be copied.\r\n" - -#define PPACKMV_BIGBROTHER_SENTBOX "Global Message Copy Sent Items Mailbox" -#define PPACKMV_BIGBROTHER_SENTBOX_HELP "The mailbox to which all outbound messages will be copied.\r\n" - -#define PPACKMV_ACL_GROUP "Authorized Group" -#define PPACKMV_ACL_GROUP_HELP "The eDirectory group containing user membership for external message delivery.\r\n" - -/* POP3 Managed Variables */ -#define POP3MV_MANAGEMENT_URL "Management URL" -#define POP3MV_MANAGEMENT_URL_HELP "Account URL listed in the POP3 account administration URL.\r\n" - -/* Proxy Managed Variables */ -#define PROXMV_MAXIMUM_ACCOUNTS "Maximum Accounts" -#define PROXMV_MAXIMUM_ACCOUNTS_HELP "The maximum number of accounts a user can configure for mail proxy.\r\n" - -#define PROXMV_MAXIMUM_PARALLEL_THREADS "Maximum Threads" -#define PROXMV_MAXIMUM_PARALLEL_THREADS_HELP "The maximum number of simultaneous mail proxies.\r\n" - -#define PROXMV_CONNECTION_TIMEOUT "Timeout" -#define PROXMV_CONNECTION_TIMEOUT_HELP "The maximum number of seconds to wait for a reply from a remote server while attempting to proxy messages.\r\n" - -#define PROXMV_RUN_INTERVAL "Interval" -#define PROXMV_RUN_INTERVAL_HELP "The number of seconds between proxy enumerations. If the current enumeration exceeds the interval length, the next enumeration begins upon the conclusion of the current enumeration.\r\n" - -#define PROXYMV_REMOTE_MESSAGES_PULLED "Remote Messages Retrieved" -#define PROXYMV_REMOTE_MESSAGES_PULLED_HELP "The number of remote messages retrieved.\r\n" - -#define PROXYMV_REMOTE_BYTES_PULLED "Remote Kilo-Bytes Stored" -#define PROXYMV_REMOTE_BYTES_PULLED_HELP "The number of kilo-bytes of remote messages delivered.\r\n" - -/* Rule Server Managed Variables */ -#define RULEMV_USE_USER_RULES "User Rules" -#define RULEMV_USE_USER_RULES_HELP "Set to TRUE to process user configured rules.\r\n" - -#define RULEMV_USE_SYSTEM_RULES "System Rules" -#define RULEMV_USE_SYSTEM_RULES_HELP "Set to TRUE to process system configured rules.\r\n" - -/* SMTP Managed Variables */ -#define SMTPMV_INCOMING_QUEUE_AGENT "Incoming Queue Agent" -#define SMTPMV_INCOMING_QUEUE_AGENT_HELP "The number of incoming NMAP connections being serviced.\r\n" - -#define SMTPMV_SERVICED_SERVERS "SMTP Servers" -#define SMTPMV_SERVICED_SERVERS_HELP "The total number of SMTP server connections that have been serviced.\r\n" - -#define SMTPMV_INCOMING_SERVERS "Incoming Server" -#define SMTPMV_INCOMING_SERVERS_HELP "The number of cumulative SMTP connections.\r\n" - -#define SMTPMV_CLOSED_OUT_SERVERS "NMAP Servers" -#define SMTPMV_CLOSED_OUT_SERVERS_HELP "The total number of NMAP server connections that have been serviced.\r\n" - -#define SMTPMV_OUTGOING_SERVERS "Outgoing Servers" -#define SMTPMV_OUTGOING_SERVERS_HELP "The number of remote SMTP connections being used.\r\n" - -#define SMTPMV_SPAM_ADDRS_BLOCKED "SPAM Addresses Blocked" -#define SMTPMV_SPAM_ADDRS_BLOCKED_HELP "The number of SMTP connections blocked using the Blocked Addresses list.\r\n" - -#define SMTPMV_SPAM_MAPS_BLOCKED "SPAM MAPS Blocked" -#define SMTPMV_SPAM_MAPS_BLOCKED_HELP "The number of SMTP connections blocked using the RBL List.\r\n" - -#define SMTPMV_SPAM_NO_DNS_ENTRY "SPAM No DNS Entry" -#define SMTPMV_SPAM_NO_DNS_ENTRY_HELP "The number of SMTP connection blocked due to missing reverse DNS entries.\r\n" - -#define SMTPMV_SPAM_DENIED_ROUTING "SPAM Denied Routing" -#define SMTPMV_SPAM_DENIED_ROUTING_HELP "The number of SMTP relay attempts blocked.\r\n" - -#define SMTPMV_SPAM_QUEUE "SPAM Queue" -#define SMTPMV_SPAM_QUEUE_HELP "The number of discarded RTS messages.\r\n" - -#define SMTPMV_REMOTE_RECIP_RECEIVED "Remote Recipient Received" -#define SMTPMV_REMOTE_RECIP_RECEIVED_HELP "The number of remote recipients received for delivery.\r\n" - -#define SMTPMV_LOCAL_RECIP_RECEIVED "Local Recipient Received" -#define SMTPMV_LOCAL_RECIP_RECEIVED_HELP "The number of local recipients received for delivery.\r\n" - -#define SMTPMV_REMOTE_RECIP_STORED "Remote Recipient Stored" -#define SMTPMV_REMOTE_RECIP_STORED_HELP "The number of remote recipients delivered.\r\n" - -#define SMTPMV_REMOTE_BYTES_RECEIVED "Remote Kilo-Bytes Received" -#define SMTPMV_REMOTE_BYTES_RECEIVED_HELP "The number of kilobytes of messages received for remote delivery.\r\n" - -#define SMTPMV_LOCAL_BYTES_RECEIVED "Local Kilo-Bytes Received" -#define SMTPMV_LOCAL_BYTES_RECEIVED_HELP "The number of kilobytes of messages received for local delivery.\r\n" - -#define SMTPMV_REMOTE_BYTES_STORED "Remote Kilo-Bytes Stored" -#define SMTPMV_REMOTE_BYTES_STORED_HELP "The number of kilobytes of remote messages delivered.\r\n" - -#define SMTPMV_REMOTE_MSGS_RECEIVED "Remote Messages Received" -#define SMTPMV_REMOTE_MSGS_RECEIVED_HELP "The number of messages received for remote delivery.\r\n" - -#define SMTPMV_LOCAL_MSGS_RECEIVED "Local Messages Received" -#define SMTPMV_LOCAL_MSGS_RECEIVED_HELP "The number of messages received for local delivery.\r\n" - -#define SMTPMV_REMOTE_MSGS_STORED "Remote Messages Stored" -#define SMTPMV_REMOTE_MSGS_STORED_HELP "The number of remote messages delivered.\r\n" - -#define SMTPMV_MAX_MX_SERVERS "Maximum MX Servers" -#define SMTPMV_MAX_MX_SERVERS_HELP "The maximum number of MX servers to process before aborting delivery.\r\n" - -#define SMTPMV_MAX_BOUNCE_COUNT "Maximum Bounce Count" -#define SMTPMV_MAX_BOUNCE_COUNT_HELP "The maximum number of RTS messages permitted per bounce interval.\r\n" - -#define SMTPMV_BOUNCE_COUNT "Bounce Count" -#define SMTPMV_BOUNCE_COUNT_HELP "The current number of RTS messages received for this bounce interval.\r\n" - -#define SMTPMV_MESSAGE_LIMIT "Message Limit" -#define SMTPMV_MESSAGE_LIMIT_HELP "The maximum allowed message size.\r\n" - -#define SMTPMV_MAX_RECIPS "Maximum Recipients" -#define SMTPMV_MAX_RECIPS_HELP "The maximum allowed recipients per message.\r\n" - -#define SMTPMV_MAX_NULL_SENDER_RECIPS "Maximum NULL Sender Recipients" -#define SMTPMV_MAX_NULL_SENDER_RECIPS_HELP "The maximum number of recipients per RTS message.\r\n" - -#define SMTPMV_LOCAL_IP_ADDRESS "Local IP Address" -#define SMTPMV_LOCAL_IP_ADDRESS_HELP "The host TCP/IP address; for example 127.0.0.1.\r\n" - -#define SMTPMV_BLOCKED_ADDRESSES "Blocked Addresses" -#define SMTPMV_BLOCKED_ADDRESSES_HELP "The blocked addresses list.\r\n" - -#define SMTPMV_ALLOWED_ADDRESSES "Allowed Addresses" -#define SMTPMV_ALLOWED_ADDRESSES_HELP "The allowed addresses list.\r\n" - -#define SMTPMV_HOST_ADDRESS "Host Address" -#define SMTPMV_HOST_ADDRESS_HELP "The bracketed host TCP/IP address; for example [127.0.0.1].\r\n" - -#define SMTPMV_RELAY_HOST "Relay Host" -#define SMTPMV_RELAY_HOST_HELP "The SMTP server to be used for relaying when delivering messages.\r\n" - -#define SMTPMV_DOMAINS_ARRAY "Domains" -#define SMTPMV_DOMAINS_ARRAY_HELP "The agent's configured domain list.\r\n" - -#define SMTPMV_USER_DOMAINS_ARRAY "User Domains" -#define SMTPMV_USER_DOMAINS_ARRAY_HELP "The agent's configured user domain list.\r\n" - -#define SMTPMV_RELAY_DOMAINS_ARRAY "Relay Domains" -#define SMTPMV_RELAY_DOMAINS_ARRAY_HELP "The agent's configured relay domain list.\r\n" - -#define SMTPMV_RBL_HOSTS_ARRAY "RBL Hosts" -#define SMTPMV_RBL_HOSTS_ARRAY_HELP "The agent's configured RBL list.\r\n" - -#define SMTPMV_RBL_COMMENTS_ARRAY "RBL Comments" -#define SMTPMV_RBL_COMMENTS_ARRAY_HELP "The agent's configured comments per RBL list entry.\r\n" - -#define SMTPMV_USE_RELAY_HOST "Use Relay Host" -#define SMTPMV_USE_RELAY_HOST_HELP "Set to TRUE if the SMTP Relay Host is to be used for remote delivery.\r\n" - -#define SMTPMV_ALLOW_EXPN "Allow EXPN" -#define SMTPMV_ALLOW_EXPN_HELP "Set to TRUE to activate support for the SMTP EXPN command; not recommended.\r\n" - -#define SMTPMV_ALLOW_VRFY "Allow Verify" -#define SMTPMV_ALLOW_VRFY_HELP "Set to TRUE to activate support for the SMTP VRFY command; not recommended.\r\n" - -#define SMTPMV_CHECK_RCPT "Validate Recipient" -#define SMTPMV_CHECK_RCPT_HELP "Set to TRUE to validate recipients addresses during message delivery.\r\n" - -#define SMTPMV_SEND_ETRN "Send ETRN" -#define SMTPMV_SEND_ETRN_HELP "Set to TRUE to deliver ETRN messages.\r\n" - -#define SMTPMV_ACCEPT_ETRN "Accept ETRN" -#define SMTPMV_ACCEPT_ETRN_HELP "Set to TRUE to accept ETRN messages.\r\n" - -#define SMTPMV_BLOCK_RTS_SPAM "Block RTS SPAM" -#define SMTPMV_BLOCK_RTS_SPAM_HELP "Set to TRUE to block recipients in RTS messages if the count exceeds the \"Maximum NULL Send Recipients\" value.\r\n" - -#define SMTPMV_BYTE_STORED_COUNT "Remote Messages Delivered" -#define SMTPMV_BYTE_STORED_COUNT_HELP "The number of remote messages delivered.\r\n" - -BOOL ManagementInit(const unsigned char *Identity, MDBHandle DirectoryHandle); -void ManagementShutdown(void); -enum ManagementStates ManagementState(void); - -BOOL ManagementSetVariables(ManagementVariables *Variables, unsigned long Count); -BOOL ManagementSetCommands(ManagementCommands *Commands, unsigned long Count); - -void ManagementServer(void *param); - -EXPORT void MsgSendTrap(int type, unsigned char *message); - -BOOL ManagementMemoryStats(unsigned char *Arguments, unsigned char **Response, BOOL *CloseConnection); -BOOL ManagementConnTrace(unsigned char *Arguments, unsigned char **Response, BOOL *CloseConnection); - -#endif /* BONGO_MANAGEMENT_H */ diff --git a/include/msgaddr.h b/include/msgaddr.h index 2b4df11..8f497e4 100644 --- a/include/msgaddr.h +++ b/include/msgaddr.h @@ -17,6 +17,7 @@ * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * + * (C) 2007 Patrick Felt ****************************************************************************/ #ifndef MSGADDR_H @@ -108,7 +109,7 @@ EXPORT const unsigned char MsgAddressCharacters[]; -EXPORT BOOL MsgIsAddress(unsigned char *AddressLine, size_t AddressLineLength, unsigned char *Delimiters, unsigned char **LineOut); +EXPORT BOOL MsgParseAddress(unsigned char *AddressLine, size_t AddressLineLength, unsigned char **local_part, unsigned char **domain); EXPORT int MsgIsComment(unsigned char *Base, unsigned char *Limit, unsigned char **Out); EXPORT BOOL MsgIsXText(unsigned char *In, unsigned char *Limit, unsigned char **Out); @@ -126,7 +127,8 @@ IMPORT BOOL MsgIsXText(unsigned char *In, unsigned char *Limit, unsigned char ** extern const unsigned char MsgAddressCharacters[]; -BOOL MsgIsAddress(unsigned char *AddressLine, size_t AddressLineLength, unsigned char *Delimiters, unsigned char **LineOut); +BOOL MsgParseAddress(unsigned char *AddressLine, size_t AddressLineLength, unsigned char **local_part, unsigned char **domain); +//BOOL MsgIsAddress(unsigned char *AddressLine, size_t AddressLineLength, unsigned char *Delimiters, unsigned char **LineOut); int MsgIsComment(unsigned char *Base, unsigned char *Limit, unsigned char **Out); BOOL MsgIsXText(unsigned char *In, unsigned char *Limit, unsigned char **Out); diff --git a/include/msgapi.h b/include/msgapi.h index f81ce12..0ba5353 100644 --- a/include/msgapi.h +++ b/include/msgapi.h @@ -22,94 +22,117 @@ #ifndef MSGAPI_H #define MSGAPI_H -#include #include +#include #include #include -#define MSGSRV_LOCAL_SERVER NULL -#define MSGSRV_SELECTED_CONTEXT "." +// Auth functions +EXPORT int MsgAuthInit(void); +EXPORT int MsgAuthInstall(void); +EXPORT int MsgAuthFindUser(const char *user); +EXPORT BOOL MsgAuthVerifyPassword(const char *user, const char *password); +EXPORT int MsgAuthChangePassword(const char *user, const char *oldpassword, const char *newpassword); +EXPORT int MsgAuthSetPassword(const char *user, const char *password); +EXPORT int MsgAuthGetUserStore(const char *user, struct sockaddr_in *store); +EXPORT int MsgAuthInitDB(void); +EXPORT int MsgAuthAddUser(const char *user); -#define MSGSRV_ROOT "Bongo Services" +// Auth / cookie functions -#define MSGSRV_LIST_ROOT "Mailing Lists" -#define MSGSRV_PARENT_ROOT "Communities" -#define MSGSRV_TEMPLATE_ROOT "Templates" -#define MSGSRV_USER_SETTINGS_ROOT "User Settings" +#define MSGAUTH_COOKIE_LEN 32 -#define MSGSRV_C_ROOT "BongoServices" -#define MSGSRV_C_SERVER "BongoMessagingServer" -#define MSGSRV_C_WEBADMIN "BongoWebAdminServer" -#define MSGSRV_C_ADDRESSBOOK "BongoAddressbookAgent" -#define MSGSRV_C_AGENT "BongoAgent" -#define MSGSRV_C_ALIAS "BongoAliasAgent" -#define MSGSRV_C_ANTISPAM "BongoAntiSpamAgent" -#define MSGSRV_C_FINGER "BongoFingerAgent" -#define MSGSRV_C_GATEKEEPER "BongoConnMgrAgent" -#define MSGSRV_C_CONNMGR "BongoConnMgrAgent" -#define MSGSRV_C_IMAP "BongoIMAPAgent" -#define MSGSRV_C_LIST "BongoList" -#define MSGSRV_C_NDSLIST "BongoNDSList" -#define MSGSRV_C_LISTCONTAINER "BongoListContainer" -#define MSGSRV_C_LISTUSER "BongoListUser" -#define MSGSRV_C_LISTAGENT "BongoListAgent" -#define MSGSRV_C_STORE "BongoStoreAgent" -#define MSGSRV_C_QUEUE "BongoQueueAgent" -#define MSGSRV_C_POP "BongoPOPAgent" -#define MSGSRV_C_PROXY "BongoProxyAgent" -#define MSGSRV_C_RULESRV "BongoRuleAgent" -#define MSGSRV_C_SIGNUP "BongoSignupAgent" -#define MSGSRV_C_SMTP "BongoSMTPAgent" -#define MSGSRV_C_PARENTCONTAINER "BongoCommunityContainer" -#define MSGSRV_C_PARENTOBJECT "BongoCommunity" -#define MSGSRV_C_TEMPLATECONTAINER "BongoTemplateContainer" -#define MSGSRV_C_ITIP "BongoItipAgent" -#define MSGSRV_C_ANTIVIRUS "BongoAntiVirusAgent" -#define MSGSRV_C_RESOURCE "BongoResource" -#define MSGSRV_C_CONNMGR_MODULE "BongoConnMgrModule" -#define MSGSRV_C_CM_USER_MODULE "BongoCMUserModule" -#define MSGSRV_C_CM_LISTS_MODULE "BongoCMListsModule" -#define MSGSRV_C_CM_RBL_MODULE "BongoCMRBLModule" -#define MSGSRV_C_CM_RDNS_MODULE "BongoCMRDNSModule" -#define MSGSRV_C_CALCMD "BongoCalCmdAgent" -#define MSGSRV_C_COLLECTOR "BongoCollectorAgent" +typedef struct { + char token[MSGAUTH_COOKIE_LEN]; + uint64_t expiration; +} MsgAuthCookie; -/* TODO: Remove MSGSRV_C_USER - This has been deprecated in favor of C_USER with MSGSRV_C_USER_SETTINGS */ -#define MSGSRV_C_USER "BongoUser" +EXPORT BOOL MsgAuthCreateCookie(const char *username, MsgAuthCookie *cookie, uint64_t timeout); +EXPORT int MsgAuthFindCookie(const char *username, const char *token); +EXPORT BOOL MsgAuthDeleteCookie(const char *username, const char *token); -#define MSGSRV_C_USER_SETTINGS "BongoUserSettings" -#define MSGSRV_C_USER_SETTINGS_CONTAINER "BongoUserSettingsContainer" -#define MSGSRV_C_ORGANIZATIONAL_ROLE "BongoOrganizationalRole" -#define MSGSRV_C_ORGANIZATION "BongoOrganization" -#define MSGSRV_C_ORGANIZATIONAL_UNIT "BongoOrganizationalUnit" -#define MSGSRV_C_GROUP "BongoGroup" +// SQL Routines -#define MSGSRV_NLM_ADDRESSBOOK "BONGOMSGLDAP.NLM" -#define MSGSRV_NLM_ALIAS "BONGOMSGALIAS.NLM" -#define MSGSRV_NLM_ANTISPAM "BONGOANTISPAM.NLM" -#define MSGSRV_NLM_FINGER "BONGOFINGER.NLM" -#define MSGSRV_NLM_GATEKEEPER "BONGOGKEEPER.NLM" -#define MSGSRV_NLM_CALCMD "BONGOCALCMD.NLM" -#define MSGSRV_NLM_CONNMGR "BONGOCONNMGR.NLM" -#define MSGSRV_NLM_IMAP "BONGOIMAP.NLM" -#define MSGSRV_NLM_LISTAGENT "BONGOIMSLIST.NLM" -#define MSGSRV_NLM_STORE "BONGOSTORE.NLM" -#define MSGSRV_NLM_QUEUE "BONGOQUEUE.NLM" -#define MSGSRV_NLM_POP "BONGOPOP3.NLM" -#define MSGSRV_NLM_PROXY "BONGOMAILPROX.NLM" -#define MSGSRV_NLM_RULESRV "BONGORULES.NLM" -#define MSGSRV_NLM_SIGNUP "BONGOMSGSGNUP.NLM" -#define MSGSRV_NLM_SMTP "BONGOSMTP.NLM" -#define MSGSRV_NLM_ITIP "BONGOITIP.NLM" -#define MSGSRV_NLM_ANTIVIRUS "BONGOAVIRUS.NLM" -#define MSGSRV_NLM_DMC "BONGODMC.NLM" -#define MSGSRV_NLM_CMUSER "BONGOCMUSER.NLM" -#define MSGSRV_NLM_CMLISTS "BONGOCMLISTS.NLM" -#define MSGSRV_NLM_CMRBL "BONGOCMRBL.NLM" -#define MSGSRV_NLM_CMRDNS "BONGOCMRDNS.NLM" -#define MSGSRV_NLM_WEBADMIN "BONGOWEBADMIN.NLM" +typedef struct _MsgSQLStatement { + sqlite3_stmt *stmt; + void *userdata; +} MsgSQLStatement; + +typedef struct _MsgSQLHandle { + sqlite3 *db; + struct { + /* NOTE: begin and end must be the first and last stmts (see DStoreClose()) */ + MsgSQLStatement begin; + MsgSQLStatement abort; + MsgSQLStatement end; + } stmts; + + BongoMemStack *memstack; + int transactionDepth; + int lockTimeoutMs; +} MsgSQLHandle; + +typedef enum { + MSGAPI_DIR_START, + MSGAPI_DIR_BIN, + MSGAPI_DIR_CACHE, + MSGAPI_DIR_CERT, + MSGAPI_DIR_COOKIE, + MSGAPI_DIR_DATA, + MSGAPI_DIR_DBF, + MSGAPI_DIR_LIB, + MSGAPI_DIR_MAIL, + MSGAPI_DIR_SCMS, + MSGAPI_DIR_SPOOL, + MSGAPI_DIR_STATE, + MSGAPI_DIR_STORESYSTEM, + MSGAPI_DIR_WORK, + MSGAPI_DIR_END +} MsgApiDirectory; + +typedef enum { + MSGAPI_FILE_START, + MSGAPI_FILE_PUBKEY, + MSGAPI_FILE_PRIVKEY, + MSGAPI_FILE_DHPARAMS, + MSGAPI_FILE_RSAPARAMS, + MSGAPI_FILE_RANDSEED, + MSGAPI_FILE_END +} MsgApiFile; + +EXPORT const unsigned char * +MsgGetFile(MsgApiFile file, char *buffer, size_t buffer_size); +EXPORT const unsigned char * +MsgGetDir(MsgApiDirectory directory, char *buffer, size_t buffer_size); + +#define MSGSQL_STMT_SLEEP_MS 250 + +MsgSQLHandle *MsgSQLOpen(char *path, BongoMemStack *memstack, int locktimeoutms); +BongoMemStack *MsgSQLGetMemStack(MsgSQLHandle *handle); +MsgSQLStatement *MsgSQLPrepare(MsgSQLHandle *handle, const char *statement, MsgSQLStatement *stmt); +void MsgSQLClose(MsgSQLHandle *handle); +void MsgSQLSetMemStack(MsgSQLHandle *handle, BongoMemStack *memstack); +void MsgSQLSetLockTimeout(MsgSQLHandle *handle, int timeoutms); +void MsgSQLReset(MsgSQLHandle *handle); +int MsgSQLBeginTransaction(MsgSQLHandle *handle); +int MsgSQLCommitTransaction(MsgSQLHandle *handle); +int MsgSQLAbortTransaction(MsgSQLHandle *handle); +int MsgSQLCancelTransactions(MsgSQLHandle *handle); +int MsgSQLBindString(MsgSQLStatement *stmt, int var, const char *str, BOOL nullify); +int MsgSQLExecute(MsgSQLHandle *handle, MsgSQLStatement *_stmt); +int MsgSQLResults(MsgSQLHandle *handle, MsgSQLStatement *_stmt); +void MsgSQLFinalize(MsgSQLStatement *stmt); + + +// Misc. util functions + +EXPORT BOOL MsgSetRecoveryFlag(unsigned char *agent_name); +EXPORT BOOL MsgGetRecoveryFlag(unsigned char *agent_name); +EXPORT BOOL MsgClearRecoveryFlag(unsigned char *agent_name); + +EXPORT BOOL MsgGetServerCredential(char *buffer); +EXPORT BOOL MsgSetServerCredential(void); #define MSGSRV_AGENT_ADDRESSBOOK "Address Book Agent" #define MSGSRV_AGENT_ALIAS "Alias Agent" @@ -136,284 +159,6 @@ #define MSGSRV_AGENT_CMRDNS "RDNS Module" #define MSGSRV_AGENT_COLLECTOR "Collector Agent" -#define MSGSRV_A_AGENT_STATUS "BongoAgentStatus" -#define MSGSRV_A_ALIAS "BongoAlias" -#define MSGSRV_A_AUTHENTICATION_REQUIRED "BongoAuthenticationRequired" -#define MSGSRV_A_CONFIGURATION "BongoConfiguration" -#define MSGSRV_A_CLIENT "BongoClient" -#define MSGSRV_A_CONTEXT "BongoContext" -#define MSGSRV_A_DOMAIN "BongoDomain" -#define MSGSRV_A_EMAIL_ADDRESS "BongoEMailAddress" -#define MSGSRV_A_DISABLED "BongoDisabled" -#define MSGSRV_A_FINGER_MESSAGE "BongoFingerMessage" -#define MSGSRV_A_HOST "BongoHost" -#define MSGSRV_A_IP_ADDRESS "BongoIPAddress" -#define MSGSRV_A_LDAP_SERVER "BongoLDAPServer" -#define MSGSRV_A_LDAP_NMAP_SERVER "BongoLDAPNMAPServer" -#define MSGSRV_A_LDAP_SEARCH_DN "BongoLDAPSearchDN" -#define MSGSRV_A_MESSAGE_LIMIT "BongoMessageLimit" -#define MSGSRV_A_MESSAGING_SERVER "BongoMessagingServerDN" -#define MSGSRV_A_MODULE_NAME "BongoModuleName" -#define MSGSRV_A_MODULE_VERSION "BongoModuleVersion" -#define MSGSRV_A_MONITORED_QUEUE "BongoMonitoredQueue" -#define MSGSRV_A_QUEUE_SERVER "BongoQueueServer" -#define MSGSRV_A_STORE_SERVER "BongoStoreServer" -#define MSGSRV_A_OFFICIAL_NAME "BongoOfficialName" -#define MSGSRV_A_QUOTA_MESSAGE "BongoQuotaMessage" -#define MSGSRV_A_POSTMASTER "BongoPostmaster" -#define MSGSRV_A_REPLY_MESSAGE "BongoReplyMessage" -#define MSGSRV_A_URL "BongoURL" -#define MSGSRV_A_RESOLVER "BongoResolver" -#define MSGSRV_A_ROUTING "BongoRouting" -#define MSGSRV_A_SERVER_STATUS "BongoServerStatus" -#define MSGSRV_A_QUEUE_INTERVAL "BongoQueueInterval" -#define MSGSRV_A_QUEUE_TIMEOUT "BongoQueueTimeout" -#define MSGSRV_A_UID "BongoUID" -#define MSGSRV_A_VACATION_MESSAGE "BongoVacationMessage" -#define MSGSRV_A_WORD "BongoWord" -#define MSGSRV_A_MESSAGE_STORE "BongoMessageStore" -#define MSGSRV_A_FORWARDING_ADDRESS "BongoForwardingAddress" -#define MSGSRV_A_FORWARDING_ENABLED "BongoForwardingEnabled" -#define MSGSRV_A_AUTOREPLY_ENABLED "BongoVacationMessageEnabled" -#define MSGSRV_A_AUTOREPLY_MESSAGE "BongoReplyMessage" -#define MSGSRV_A_PORT "BongoPort" -#define MSGSRV_A_SSL_PORT "BongoSSLPort" -#define MSGSRV_A_SNMP_DESCRIPTION "BongoSNMPDescription" -#define MSGSRV_A_SNMP_VERSION "BongoSNMPVersion" -#define MSGSRV_A_SNMP_ORGANIZATION "BongoSNMPOrganization" -#define MSGSRV_A_SNMP_LOCATION "BongoSNMPLocation" -#define MSGSRV_A_SNMP_CONTACT "BongoSNMPContact" -#define MSGSRV_A_SNMP_NAME "BongoSNMPName" -#define MSGSRV_A_MESSAGING_DISABLED "BongoMessagingDisabled" -#define MSGSRV_A_STORE_TRUSTED_HOSTS "BongoStoreTrustedHosts" -#define MSGSRV_A_QUOTA_VALUE "BongoQuotaValue" -#define MSGSRV_A_SCMS_USER_THRESHOLD "BongoSCMSUserThreshold" -#define MSGSRV_A_SCMS_SIZE_THRESHOLD "BongoSCMSSizeThreshold" -#define MSGSRV_A_SMTP_VERIFY_ADDRESS "BongoSMTPVerifyAddress" -#define MSGSRV_A_SMTP_ALLOW_AUTH "BongoSMTPAllowAUTH" -#define MSGSRV_A_SMTP_ALLOW_VRFY "BongoSMTPAllowVRFY" -#define MSGSRV_A_SMTP_ALLOW_EXPN "BongoSMTPAllowEXPN" -#define MSGSRV_A_WORK_DIRECTORY "BongoWorkDirectory" -#define MSGSRV_A_LOGLEVEL "BongoLoglevel" -#define MSGSRV_A_MINIMUM_SPACE "BongoMinimumFreeSpace" -#define MSGSRV_A_SMTP_SEND_ETRN "BongoSMTPSendETRN" -#define MSGSRV_A_SMTP_ACCEPT_ETRN "BongoSMTPAcceptETRN" -#define MSGSRV_A_LIMIT_REMOTE_PROCESSING "BongoLimitRemoteProcessing" -#define MSGSRV_A_LIMIT_REMOTE_START_WD "BongoLimitRemoteBegWeekday" -#define MSGSRV_A_LIMIT_REMOTE_END_WD "BongoLimitRemoteEndWeekday" -#define MSGSRV_A_LIMIT_REMOTE_START_WE "BongoLimitRemoteBegWeekend" -#define MSGSRV_A_LIMIT_REMOTE_END_WE "BongoLimitRemoteEndWeekend" -#define MSGSRV_A_PRODUCT_VERSION "BongoProductVersion" -#define MSGSRV_A_PROXY_LIST "BongoProxyList" -#define MSGSRV_A_MAXIMUM_ITEMS "BongoMaximumItems" -#define MSGSRV_A_TIME_INTERVAL "BongoTimeInterval" -#define MSGSRV_A_RELAYHOST "BongoRelayHost" -#define MSGSRV_A_ALIAS_OPTIONS "BongoAliasOptions" -#define MSGSRV_A_LDAP_OPTIONS "BongoLDAPOptions" -#define MSGSRV_A_CUSTOM_ALIAS "BongoCustomAlias" -#define MSGSRV_A_ADVERTISING_CONFIG "BongoAdvertisingConfig" -#define MSGSRV_A_LANGUAGE "BongoLanguage" -#define MSGSRV_A_PREFERENCES "BongoPreferences" -#define MSGSRV_A_QUOTA_WARNING "BongoQuotaWarning" -#define MSGSRV_A_QUEUE_TUNING "BongoQueueTuning" -#define MSGSRV_A_TIMEOUT "BongoTimeout" -#define MSGSRV_A_PRIVACY "BongoPrivacy" -#define MSGSRV_A_THREAD_LIMIT "BongoThreadLimit" -#define MSGSRV_A_DBF_PAGESIZE "BongoDBFPageSize" -#define MSGSRV_A_DBF_KEYSIZE "BongoDBFKeySize" -#define MSGSRV_A_ADDRESSBOOK_CONFIG "BongoAddressbookConfig" -#define MSGSRV_A_ADDRESSBOOK_URL_SYSTEM "BongoAddressbookURLSystem" -#define MSGSRV_A_ADDRESSBOOK_URL_PUBLIC "BongoAddressbookURLPublic" -#define MSGSRV_A_ADDRESSBOOK "BongoAddressbook" -#define MSGSRV_A_SERVER_STANDALONE "BongoServerStandalone" -#define MSGSRV_A_FORWARD_UNDELIVERABLE "BongoForwardUndeliverable" -#define MSGSRV_A_PHRASE "BongoPhrase" -#define MSGSRV_A_ACCOUNTING_ENABLED "BongoAccountingEnabled" -#define MSGSRV_A_ACCOUNTING_DATA "BongoAccountingData" -#define MSGSRV_A_BILLING_DATA "BongoBillingData" -#define MSGSRV_A_BLOCKED_ADDRESS "BongoBlockedAddress" -#define MSGSRV_A_ALLOWED_ADDRESS "BongoAllowedAddress" -#define MSGSRV_A_RECIPIENT_LIMIT "BongoRecipientLimit" -#define MSGSRV_A_RBL_HOST "BongoRBLHost" -#define MSGSRV_A_SIGNATURE "BongoSignature" -#define MSGSRV_A_CONNMGR "BongoConnMgr" -#define MSGSRV_A_CONNMGR_CONFIG "BongoConnMgrConfig" -#define MSGSRV_A_USER_DOMAIN "BongoUserDomain" -#define MSGSRV_A_RTS_ANTISPAM_CONFIG "BongoRTSAntispamConfig" -#define MSGSRV_A_SPOOL_DIRECTORY "BongoSpoolDirectory" -#define MSGSRV_A_SCMS_DIRECTORY "BongoSCMSDirectory" -#define MSGSRV_A_STORE_SYSTEM_DIRECTORY "BongoStoreSystemDirectory" -#define MSGSRV_A_DBF_DIRECTORY "BongoDBFDirectory" -#define MSGSRV_A_NLS_DIRECTORY "BongoNLSDirectory" -#define MSGSRV_A_BIN_DIRECTORY "BongoBinDirectory" -#define MSGSRV_A_LIB_DIRECTORY "BongoLibDirectory" -#define MSGSRV_A_DEFAULT_CHARSET "BongoDefaultCharset" -#define MSGSRV_A_RULE "BongoRule" -#define MSGSRV_A_RELAY_DOMAIN "BongoRelayDomain" -#define MSGSRV_A_LIST_DIGESTTIME "BongoListDigestTime" -#define MSGSRV_A_LIST_ABSTRACT "BongoListAbstract" -#define MSGSRV_A_LIST_DESCRIPTION "BongoListDescription" -#define MSGSRV_A_LIST_CONFIGURATION "BongoListConfiguration" -#define MSGSRV_A_LIST_STORE "BongoListStore" -#define MSGSRV_A_LIST_NMAPSTORE "BongoListNMAPStore" -#define MSGSRV_A_LIST_MODERATOR "BongoListModerator" -#define MSGSRV_A_LIST_OWNER "BongoListOwner" -#define MSGSRV_A_LIST_SIGNATURE "BongoListSignature" -#define MSGSRV_A_LIST_SIGNATURE_HTML "BongoListSignatureHTML" -#define MSGSRV_A_LIST_DIGEST_VERSION "BongoListDigestVersion" -#define MSGSRV_A_LIST_MEMBERS "BongoListMembers" -#define MSGSRV_A_LISTUSER_OPTIONS "BongoListUserOptions" -#define MSGSRV_A_LISTUSER_ADMINOPTIONS "BongoListUserAdminOptions" -#define MSGSRV_A_LISTUSER_PASSWORD "BongoListUserPassword" -#define MSGSRV_A_FEATURE_SET "BongoFeatureSet" -#define MSGSRV_A_PRIVATE_KEY_LOCATION "BongoPKeyFile" -#define MSGSRV_A_CERTIFICATE_LOCATION "BongoCAFile" -#define MSGSRV_A_CONFIG_CHANGED "BongoConfigVersion" -#define MSGSRV_A_LISTSERVER_NAME "BongoListServerName" -#define MSGSRV_A_LIST_WELCOME_MESSAGE "BongoListWelcomeMessage" -#define MSGSRV_A_PARENT_OBJECT "BongoCommunityDN" -#define MSGSRV_A_FEATURE_INHERITANCE "BongoFeatureInheritance" -#define MSGSRV_A_TEMPLATE "BongoTemplate" -#define MSGSRV_A_TIMEZONE "BongoTimezone" -#define MSGSRV_A_LOCALE "BongoLocale" -#define MSGSRV_A_PASSWORD_CONFIGURATION "BongoPasswordConfig" -#define MSGSRV_A_TITLE "BongoTitle" -#define MSGSRV_A_DEFAULT_TEMPLATE "BongoDefaultTemplate" -#define MSGSRV_A_TOM_MANAGER "BongoCommunityManager" -#define MSGSRV_A_TOM_CONTEXTS "BongoCommunityContexts" -#define MSGSRV_A_TOM_DOMAINS "BongoCommunityDomains" -#define MSGSRV_A_TOM_OPTIONS "BongoCommunityOptions" -#define MSGSRV_A_DESCRIPTION "BongoDescription" -#define MSGSRV_A_STATSERVER_1 "BongoStatServer1" -#define MSGSRV_A_STATSERVER_2 "BongoStatServer2" -#define MSGSRV_A_STATSERVER_3 "BongoStatServer3" -#define MSGSRV_A_STATSERVER_4 "BongoStatServer4" -#define MSGSRV_A_STATSERVER_5 "BongoStatServer5" -#define MSGSRV_A_STATSERVER_6 "BongoStatServer6" -#define MSGSRV_A_NEWS "BongoNews" -#define MSGSRV_A_MANAGER "BongoManager" -#define MSGSRV_A_AVAILABLE_SHARES "BongoAvailableShares" -#define MSGSRV_A_OWNED_SHARES "BongoOwnedShares" -#define MSGSRV_A_NEW_SHARE_MESSAGE "BongoNewShareMessage" -#define MSGSRV_A_AVAILABLE_PROXIES "BongoAvailableProxies" -#define MSGSRV_A_OWNED_PROXIES "BongoOwnedProxies" -#define MSGSRV_A_RESOURCE_MANAGER "BongoManager" -#define MSGSRV_A_BONGO_MESSAGING_SERVER "BongoMessagingServer" -#define MSGSRV_A_ACL "BongoACL" -#define MSGSRV_A_WA_DEFAULT_TEMPLATE "WebAdminDefaultTemplate" -#define MSGSRV_A_WA_ALLOWED_TEMPLATES "WebAdminAllowedTemplates" -#define MSGSRV_A_WA_DISALLOWED_TEMPLATES "WebAdminDisallowedTemplates" -#define MSGSRV_A_SMS_AUTHORIZED_PHONES "BongoSMSAuthorizedPhones" -#define MSGSRV_A_CALCMD_ADDRESS_SUFFIX "BongoCalCmdAddressSuffix" -#define MSGSRV_A_SPAMD_ENABLED "BongoSpamdEnabled" -#define MSGSRV_A_SPAMD_TIMEOUT "BongoSpamdConnectionTimeout" -#define MSGSRV_A_SPAMD_THRESHOLD_HEAD "BongoSpamdHeaderThreshold" -#define MSGSRV_A_SPAMD_THRESHOLD_DROP "BongoSpamdDropThreshold" -#define MSGSRV_A_SPAMD_QUARANTINE_Q "BongoSpamdQuarantineQueue" -#define MSGSRV_A_SPAMD_HOST "BongoSpamdHost" -#define MSGSRV_A_SPAMD_FEEDBACK_HOST "BongoSpamdFeedbackHost" -#define MSGSRV_A_SPAMD_FEEDBACK_ENABLED "BongoSpamdFeedbackEnabled" -#define MSGSRV_A_MAX_LOAD "BongoMaxLoad" -#define MSGSRV_A_ACL_ENABLED "BongoACLEnabled" -#define MSGSRV_A_UBE_SMTP_AFTER_POP "BongoUBESMTPAfterPOP" -#define MSGSRV_A_UBE_REMOTE_AUTH_ONLY "BongoUBERemoteAuthOnly" -#define MSGSRV_A_MAX_FLOOD_COUNT "BongoMaxFloodCount" -#define MSGSRV_A_MAX_NULL_SENDER_RECIPS "BongoMaxNullSenderRecips" -#define MSGSRV_A_MAX_MX_SERVERS "BongoMaxMXServers" -#define MSGSRV_A_RELAY_LOCAL_MAIL "BongoRelayLocalMail" -#define MSGSRV_A_CLUSTERED "BongoClustered" -#define MSGSRV_A_FORCE_BIND "BongoForceBind" -#define MSGSRV_A_SSL_TLS "BongoSSLTLS" -#define MSGSRV_A_SSL_ALLOW_CHAINED "BongoSSLAllowChained" -#define MSGSRV_A_BOUNCE_RETURN "BongoBounceReturn" -#define MSGSRV_A_BOUNCE_CC_POSTMASTER "BongoBounceCCPostmaster" -#define MSGSRV_A_QUOTA_USER "BongoQuotaUser" -#define MSGSRV_A_QUOTA_SYSTEM "BongoQuotaSystem" -#define MSGSRV_A_REGISTER_QUEUE "BongoRegisterQueue" -#define MSGSRV_A_QUEUE_LIMIT_BOUNCES "BongoQueueLimitBounces" -#define MSGSRV_A_LIMIT_BOUNCE_ENTRIES "BongoLimitBounceEntries" -#define MSGSRV_A_LIMIT_BOUNCE_INTERVAL "BongoLimitBounceInterval" -#define MSGSRV_A_DOMAIN_ROUTING "BongoDomainRouting" -#define MSGSRV_A_MONITOR_INTERVAL "BongoMonitorInterval" -#define MSGSRV_A_MANAGER_PORT "BongoManagerPort" -#define MSGSRV_A_MANAGER_SSL_PORT "BongoManagerSSLPort" - -#define PLUSPACK_AGENT "PlusPack Agent" -#define PLUSPACK_C "PlusPackAgent" -#define PLUSPACK_NLM "BONGOPLUSPACK.NLM" -#define PLUSPACK_A_ACL_GROUP "PlusPackACLGroup" -#define PLUSPACK_A_COPY_USER "PlusPackCopyUser" -#define PLUSPACK_A_COPY_MBOX "PlusPackCopyMBOX" - -#define MSGSRV_LOAD_AGENT 1 -#define MSGSRV_UNLOAD_AGENT 2 -#define MSGSRV_RESTART_AGENT 3 -#define MSGSRV_GET_STATS 4 -#define MSGSRV_RESET_STATS 5 -#define MSGSRV_GET_SPAM_STATS 6 - -#define MSGSRV_SUCCESS 1 -#define MSGSRV_NOT_AUTHORIZED 2 -#define MSGSRV_UNKNOWN_REQUEST 3 -#define MSGSRV_WRONG_ARGUMENTS 4 - -#define MSGSRV_MODULES_LOADED 0 /* Private */ -#define MSGSRV_UNAUTHORIZED 1 /* Increments */ -#define MSGSRV_WRONG_PASSWORD 2 /* Increments */ -#define MSGSRV_DELIVERY_FAILED_LOCAL 3 /* Increments */ -#define MSGSRV_DELIVERY_FAILED_REMOTE 4 /* Increments */ - -#define MSGSRV_INCOMING_CLIENT 5 /* Increments */ -#define MSGSRV_INCOMING_SERVER 6 /* Increments */ -#define MSGSRV_SERVICED_CLIENT 7 /* Increments, also decrements MSGSRV_INCOMING_CLIENTS */ -#define MSGSRV_SERVICED_SERVER 8 /* Increments, also decrements MSGSRV_INCOMING_SERVERS */ -#define MSGSRV_OUTGOING_SERVER 9 /* Increments */ -#define MSGSRV_CLOSED_OUT_SERVER 10 /* Increments, also decrements MSGSRV_OUTGOING_SERVERS */ - -#define MSGSRV_INCOMING_Q_AGENT 11 /* Increments/Decrements */ -#define MSGSRV_OUTGOING_Q_AGENT 12 /* Increments/Decrements */ -#define MSGSRV_STORE_AGENT 13 /* Increments */ - -#define MSGSRV_MSG_RECEIVED_LOCAL 15 /* Value +/- */ -#define MSGSRV_MSG_RECEIVED_REMOTE 16 /* Value +/- */ -#define MSGSRV_MSG_STORED_LOCAL 17 /* Value +/- */ -#define MSGSRV_MSG_STORED_REMOTE 18 /* Value +/- */ -#define MSGSRV_MSG_QUEUED_LOCAL 19 /* Value +/- */ -#define MSGSRV_MSG_QUEUED_REMOTE 20 /* Value +/- */ - -#define MSGSRV_BYTE_RECEIVED_LOCAL 21 /* Value +/- */ -#define MSGSRV_BYTE_RECEIVED_REMOTE 22 /* Value +/- */ -#define MSGSRV_BYTE_STORED_LOCAL 23 /* Value +/- */ -#define MSGSRV_BYTE_STORED_REMOTE 24 /* Value +/- */ - -#define MSGSRV_RCPT_RECEIVED_LOCAL 25 /* Value +/- */ -#define MSGSRV_RCPT_RECEIVED_REMOTE 26 /* Value +/- */ -#define MSGSRV_RCPT_STORED_LOCAL 27 /* Value +/- */ -#define MSGSRV_RCPT_STORED_REMOTE 28 /* Value +/- */ - -#define MSGSRV_SPAM_QUEUESPAM 29 /* Increments */ -#define MSGSRV_SPAM_ADDRESS_BLOCKED 30 /* Increments */ -#define MSGSRV_SPAM_MAPS_BLOCKED 31 /* Increments */ -#define MSGSRV_SPAM_DENIED_ROUTING 32 /* Increments */ -#define MSGSRV_SPAM_NO_DNS_ENTRY 33 /* Increments */ - -#define MSGSRV_NMAP_TO_NMAP_AGENT 34 /* Increments */ - -#define MSGSRV_SPAM_MESSAGES_SCANNED 35 /* Increments */ -#define MSGSRV_SPAM_ATTACHMENTS_SCANNED 36 /* Increments */ -#define MSGSRV_SPAM_ATTACHMENTS_BLOCKED 37 /* Increments */ -#define MSGSRV_SPAM_VIRUSES_FOUND 38 /* Increments */ -#define MSGSRV_SPAM_VIRUSES_BLOCKED 39 /* Increments */ -#define MSGSRV_SPAM_VIRUSES_CURED 40 /* Increments */ - -#define MSGSRV_MAX_STAT_COUNT 41 /* How many stat entries are there? */ - -#define MSGSRV_STAT_UP 1 -#define MSGSRV_STAT_DOWN -1 - -#define MSGSRV_TRAP_ILLEGALACCESS 3 -#define MSGSRV_TRAP_OTHER 4 - /* Global configuration file. See MsgGetConfigProperty() */ #define MSGSRV_CONFIG_FILENAME "bongo.conf" #define MSGSRV_CONFIG_MAX_PROP_CHARS 255 @@ -432,57 +177,15 @@ extern "C" { #endif -typedef BOOL (*FindObjectCacheType)(const unsigned char *, unsigned char *, unsigned char *, struct sockaddr_in *, MDBValueStruct *); -typedef BOOL (*FindObjectCacheExType)(const unsigned char *, unsigned char *, unsigned char *, struct sockaddr_in *, BOOL *, MDBValueStruct *); -typedef const unsigned char *(*FindObjectStoreCacheType)(const unsigned char *User, const unsigned char *DefaultPath); - -typedef struct _MSGCacheInitStruct { - MDBHandle *DirectoryHandle; - - XplRWLock *ConfigLock; - - struct sockaddr_in *ServerAddr; - MDBValueStruct *ServerContexts; - MDBValueStruct *StorePath; - - FindObjectCacheType DefaultFindObject; - FindObjectCacheExType DefaultFindObjectEx; - FindObjectStoreCacheType DefaultFindObjectStore; - - unsigned char DefaultPathChar; -} MSGCacheInitStruct; - -typedef BOOL (*FindObjectCacheInitType)(MSGCacheInitStruct *initData, unsigned char *description); -typedef BOOL (*FindObjectCacheShutdownType)(void); - -EXPORT MDBHandle MsgInit(void); +EXPORT void MsgInit(void); EXPORT BOOL MsgShutdown(void); -EXPORT MDBHandle MsgGetSystemDirectoryHandle(void); EXPORT const unsigned char *MsgGetServerDN(unsigned char *buffer); -EXPORT MDBHandle MsgDirectoryHandle(void); EXPORT BOOL MsgGetConfigProperty(unsigned char *Buffer, unsigned char *Property); -EXPORT BOOL MsgFindObject(const unsigned char *name, unsigned char *dn, unsigned char *type, struct sockaddr_in *nmap, MDBValueStruct *v); -EXPORT BOOL MsgFindObjectEx(const unsigned char *name, unsigned char *dn, unsigned char *type, struct sockaddr_in *nmap, BOOL *disabled, MDBValueStruct *v); EXPORT const unsigned char *MsgFindUserStore(const unsigned char *user, const unsigned char *defaultPath); EXPORT BOOL MsgFindUserNmap(const unsigned char *user, unsigned char *nmap, int nmap_len, unsigned short *port); -EXPORT BOOL MsgReadIP(const unsigned char *object, unsigned char *type, MDBValueStruct *v); - -EXPORT const unsigned char *MsgGetDBFDir(char *directory); -EXPORT const unsigned char *MsgGetWorkDir(char *directory); -EXPORT const unsigned char *MsgGetNLSDir(char *directory); -EXPORT const unsigned char *MsgGetLibDir(char *directory); -EXPORT const unsigned char *MsgGetBinDir(char *directory); -EXPORT const unsigned char *MsgGetTLSCertPath(char *path); -EXPORT const unsigned char *MsgGetTLSKeyPath(char *path); -EXPORT unsigned char *MsgGetUserEmailAddress(const unsigned char *userDn, MDBValueStruct *userData, unsigned char *buffer, unsigned long bufLen); -EXPORT unsigned char *MsgGetUserDisplayName(const unsigned char *userDn, MDBValueStruct *userData); -EXPORT BOOL MsgGetUserSettingsDN(const unsigned char *userDn, unsigned char *configDn, MDBValueStruct *v, BOOL create); -EXPORT long MsgGetUserSetting(const unsigned char *userDn, unsigned char *attribute, MDBValueStruct *vOut); -EXPORT BOOL MsgSetUserSetting(const unsigned char *userDn, unsigned char *attribute, MDBValueStruct *vIn); -EXPORT BOOL MsgAddUserSetting(const unsigned char *userDn, unsigned char *attribute, unsigned char *value, MDBValueStruct *vIn); EXPORT unsigned long MsgGetHostIPAddress(void); EXPORT unsigned long MsgGetAgentBindIPAddress(void); diff --git a/include/msgftrs.h b/include/msgftrs.h index 0d741be..287e508 100644 --- a/include/msgftrs.h +++ b/include/msgftrs.h @@ -85,10 +85,6 @@ extern "C" { #endif -/* The MSG Feature API Description */ -EXPORT BOOL MsgGetUserFeature(const unsigned char *UserDN, unsigned char FeatureRow, unsigned long FeatureCol, unsigned char *Attribute, MDBValueStruct *VReturn); -EXPORT BOOL MsgDomainExists(const unsigned char *Domain, unsigned char *DomainObjectDN); - #ifdef __cplusplus } #endif diff --git a/include/nmlib.h b/include/nmlib.h index 6f7f4e8..ab4e53d 100644 --- a/include/nmlib.h +++ b/include/nmlib.h @@ -23,7 +23,6 @@ #ifndef _BONGO_NMAP_LIBRARY_H #define _BONGO_NMAP_LIBRARY_H -#include #include #include #include @@ -128,7 +127,7 @@ typedef struct { /* */ -BOOL NMAPInitialize(MDBHandle directoryHandle); +BOOL NMAPInitialize(); void NMAPSetEncryption(bongo_ssl_context *context); bongo_ssl_context *NMAPSSLContextAlloc(void); @@ -181,11 +180,12 @@ BOOL NMAPEncrypt(Connection *conn, unsigned char *response, int length, BOOL for BOOL NMAPAuthenticateToStore(Connection *conn, unsigned char *response, int length); BOOL NMAPAuthenticateToQueue(Connection *conn, unsigned char *response, int length); -int NMAPAuthenticateWithCookie(Connection *conn, const char *user, const char *cookie, - unsigned char *buffer, int length); +int NMAPAuthenticateWithCookie(Connection *conn, const char *user, const char *cookie, unsigned char *buffer, int length); +BOOL NMAPAuthenticateThenUserAndStore(Connection *conn, unsigned char *user); + void NMAPQuit(Connection *conn); -RegistrationStates NMAPRegister(const unsigned char *dn, unsigned long queue, unsigned short port); +RegistrationStates QueueRegister(const unsigned char *dn, unsigned long queue, unsigned short port); #endif /* _BONGO_NMAP_LIBRARY_H */ diff --git a/init/bongo.init.rpl.in b/init/bongo.init.rpl.in new file mode 100644 index 0000000..5ce0b00 --- /dev/null +++ b/init/bongo.init.rpl.in @@ -0,0 +1,63 @@ +#!/bin/sh +# +#Startup script for the Bongo server +# +# chkconfig: 2345 22 01 +# description: This script starts your Bongo server +# processname: bongo +# pidfile: /var/spool/bongo/work/bongo-manager.pid + +[ -f @prefix@/sbin/bongo-manager ] || exit 0 + +# Include bongoproject defaults if available +if [ -f /etc/default/bongoinit.conf ] ; then + . /etc/default/bongoinit.conf +fi + +set -e + +start() { + echo -n "Starting Bongo: " + @prefix@/sbin/bongo-manager & + if [ "1$RUN_STANDALONE" -eq "11" ]; then + sleep 3 + @prefix@/sbin/bongo-standalone $RUN_STANDALONE_OPTS & + fi + echo "Bongo." +} + +stop() { + echo -n "Stopping Bongo: " + if [ "1$RUN_STANDALONE" -eq "11" ]; then + pkill -f bongo-standalone || echo -n . + fi + @prefix@/sbin/bongo-manager -s + echo "Bongo." +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|force-reload) + # + # If the "reload" option is implemented, move the "force-reload" + # option to the "reload" entry above. If not, "force-reload" is + # just the same as "restart". + # + stop + start + echo "Bongo." + ;; + *) + N=/etc/init.d/$NAME + # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/init/bongoinit.conf.rpl.in b/init/bongoinit.conf.rpl.in new file mode 100644 index 0000000..92970a8 --- /dev/null +++ b/init/bongoinit.conf.rpl.in @@ -0,0 +1,11 @@ +# Defaults for bongoproject initscript +# sourced by /etc/init.d/bongo +# installed at /usr/etc/bongo/bongoinit.conf by the maintainer scripts +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="-f -k" +RUN_STANDALONE=0 +RUN_STANDALONE_OPTS=" -p 8080" diff --git a/man/Bongo.rules b/man/Bongo.rules index 654ccbd..d121f0d 100644 --- a/man/Bongo.rules +++ b/man/Bongo.rules @@ -7,7 +7,6 @@ mannormal = man/bongo-admin.1 \ man/bongo-sendmail.1 \ man/bongo-standalone.1 \ man/bongo-storetool.1 \ - man/mdbtool.1 \ man/bongoagents.8 mansymlinked = man/bongoaddressbook.8 \ diff --git a/man/mdbtool.1 b/man/mdbtool.1 deleted file mode 100644 index 39bada2..0000000 --- a/man/mdbtool.1 +++ /dev/null @@ -1,69 +0,0 @@ -.TH "mdbtool" 1 "Bongo Project" "http://bongo-project.org/" -.SH NAME -mdbtool \- Manges the Bongo MDB agent -.SH SYNOPSIS -.B mdbtool -.RI [ options ] -.I COMMAND -.SH DESCRIPTION -.B mdbtool -manages the operation of the Bongo MDB agent. It takes a -.I COMMAND -on execution to specify its action. -.SH OPTIONS -.TP -.BR \-h ", " \-\^\-help -Show help message and exit. -.TP -.BI \-p " PASSWORD" "\fR,\fP \-\^\-password=" PASSWORD -Use password -.I PASSWORD -for authentication. -.TP -.BI \-u " USERNAME" "\fR,\fP \-\^\-username=" USERNAME -Use username -.I USERNAME -for authentication. -.SH "COMMANDS" -.TP -.BR getbasedn -.TP -.BI "getattrs " OBJECT " " ATTRNAME -.TP -.BI "getdnattrs " OBJECT " " ATTRNAME -.TP -.BI "addattr " OBJECT " " ATTRNAME " " VALUE -.TP -.BI "setattr " OBJECT " " ATTRNAME " " VALUE -.TP -.BI "addobject " OBJECT " " CLASS " \fR[attr1=value1 attr2=...]\fP" -.TP -.BI "delobject " OBJECT " \fR[\fP " true " \fR|\fP " false " \fR]\fP" -.TP -.BI "listobjects " OBJECT -.TP -.BI "setpassword " OBJECT " \fR[\fP " PASSWORD " \fR|\fP \-f " PWFILE " \fR]\fP" -.TP -.BI "verifypassword " OBJECT " " PASSWORD -.TP -.BI "isobject " OBJECT -.TP -.BI "defattr " ATTRNAME " " ASN1 " \fR[opt1=val1 opt2=...]\fP" -.TP -.BI "defclass " CLASSNAME " " ASN1 " \fR[opt1=val1 opt2=...]\fP" -.TP -.BI "defclassattr " CLASSNAME " " ATTRNAME -.TP -.BI "delattrdef " ATTRNAME -.TP -.BI "delclassdef " CLASSNAME -.TP -.BI "grantobj " OBJECT " " TRUSTEE " \fR[opt=val1 opt2=...]\fP" -.TP -.BI "grantattr " OBJECT " " ATTRNAME " " TRUSTEE " \fR[opt1=val1 opt2=...]\fP" -.TP -.BI "gethostipaddr " -.SH "AUTHOR" -This man page was written by Jonny Lamb . -.SH "SEE ALSO" -bongo-setup(1), bongo-admin(1) diff --git a/po/bongo-web/pt_BR.po b/po/bongo-web/pt_BR.po new file mode 100644 index 0000000..e2f3c0b --- /dev/null +++ b/po/bongo-web/pt_BR.po @@ -0,0 +1,872 @@ +# Translation of Bongo Project Web interface +# Copyright (C) 2007 +# This file is distributed under the same license as the Bongo package. +# Igor Morgado , 2007 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: bongo-devel@gna.org\n" +"POT-Creation-Date: 2007-07-13 11:46+0100\n" +"PO-Revision-Date: 2007-11-08 17:47+BRST\n" +"Last-Translator: Igor Morgado \n" +"Language-Team: Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=pt_BR.UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/www/js/AddressBook.js:232 +msgid "Add Contact" +msgstr "Adicionar contato" + +#: src/www/js/AddressBook.js:322 src/www/js/AddressBook.js:446 +msgid "Show Conversations" +msgstr "Mostrar conversas" + +#: src/www/js/AddressBook.js:323 src/www/js/CalendarEditor.js:127 +#: src/www/js/OccurrenceEditor.js:826 src/www/js/Widgets.js:1128 +msgid "Add" +msgstr "Adicionar" + +#: src/www/js/AddressBook.js:336 src/www/js/AddressBook.js:641 +#: src/www/js/CalendarEditor.js:969 src/www/js/OccurrenceEditor.js:176 +#: src/www/js/OccurrenceEditor.js:218 +msgid "Saving changes..." +msgstr "Salvando mudanças..." + +#: src/www/js/AddressBook.js:352 src/www/js/AddressBook.js:629 +#: src/www/js/AddressBook.js:657 src/www/js/CalendarEditor.js:975 +#: src/www/js/OccurrenceEditor.js:187 src/www/js/OccurrenceEditor.js:228 +msgid "Changes saved." +msgstr "Mudanças salvas." + +#: src/www/js/AddressBook.js:445 src/www/js/AddressBook.js:610 +#: src/www/js/AddressBook.js:675 src/www/js/CalendarEditor.js:913 +#: src/www/js/CalendarEditor.js:951 src/www/js/CalendarEditor.js:1026 +#: src/www/js/Mail.js:154 src/www/js/Mail.js:304 +#: src/www/js/OccurrenceEditor.js:109 src/www/js/OccurrenceEditor.js:142 +#: src/www/js/OccurrenceEditor.js:262 src/www/js/OccurrenceEditor.js:281 +#: src/www/js/OccurrenceEditor.js:823 src/www/js/Widgets.js:1080 +msgid "Delete" +msgstr "Apagar" + +#: src/www/js/AddressBook.js:447 src/www/js/CalendarEditor.js:953 +#: src/www/js/OccurrenceEditor.js:110 +msgid "Edit" +msgstr "Editar" + +#: src/www/js/AddressBook.js:606 +msgid "This is Me" +msgstr "Este sou eu" + +#: src/www/js/AddressBook.js:608 src/www/js/AddressBook.js:675 +#: src/www/js/CalendarEditor.js:808 src/www/js/CalendarEditor.js:914 +#: src/www/js/OccurrenceEditor.js:137 src/www/js/OccurrenceEditor.js:143 +#: src/www/js/OccurrenceEditor.js:262 src/www/js/Widgets.js:1079 +#: src/www/js/Widgets.js:1126 +msgid "Cancel" +msgstr "Cancelar" + +#: src/www/js/AddressBook.js:608 src/www/js/CalendarEditor.js:915 +#: src/www/js/OccurrenceEditor.js:138 src/www/js/OccurrenceEditor.js:144 +#: src/www/js/OccurrenceEditor.js:281 +msgid "Save" +msgstr "Salvar" + +#: src/www/js/AddressBook.js:671 +msgid "" +"Are you sure you want to delete the contact \"{0}\"? This cannot be undone." +msgstr "Você tem certeza que quer apagar o contato \"{0}\"? Isto não pode ser desfeito." + +#: src/www/js/CalendarEditor.js:14 +msgid "Share this calendar" +msgstr "Compartilhe este calendário" + +#: src/www/js/CalendarEditor.js:73 src/www/js/CalendarEditor.js:100 +#: src/www/js/CalendarEditor.js:623 src/www/js/CalendarEditor.js:642 +#: src/www/js/Login.js:108 +msgid "Name:" +msgstr "Nome:" + +#: src/www/js/CalendarEditor.js:76 src/www/js/CalendarEditor.js:626 +msgid "Color:" +msgstr "Cor:" + +#: src/www/js/CalendarEditor.js:83 +msgid "Import ICS:" +msgstr "Importar ICS:" + +#: src/www/js/CalendarEditor.js:92 src/www/js/CalendarEditor.js:637 +msgid "Allow other users to search for this calendar" +msgstr "Permitir que outros usuários busquem por este calendário" + +#: src/www/js/CalendarEditor.js:95 src/www/js/CalendarEditor.js:640 +msgid "Password protect this calendar" +msgstr "Proteger este calendário com senha" + +#: src/www/js/CalendarEditor.js:103 +msgid "Current password:" +msgstr "Senha atual:" + +#: src/www/js/CalendarEditor.js:106 src/www/js/CalendarEditor.js:645 +#: src/www/js/Login.js:109 +msgid "Password:" +msgstr "Senha:" + +#: src/www/js/CalendarEditor.js:109 +msgid "Password (again):" +msgstr "Senha (de novo):" + +#: src/www/js/CalendarEditor.js:121 src/www/js/CalendarEditor.js:139 +#: src/www/js/CalendarEditor.js:952 +msgid "Send invitation..." +msgstr "Enviar convite..." + +#: src/www/js/CalendarEditor.js:123 +msgid "Basic" +msgstr "Básico" + +#: src/www/js/CalendarEditor.js:127 +msgid "Email:" +msgstr "Correio:" + +#: src/www/js/CalendarEditor.js:133 +msgid "Remove" +msgstr "Remover" + +#: src/www/js/CalendarEditor.js:136 +msgid "Select:" +msgstr "Selecionar:" + +#: src/www/js/CalendarEditor.js:136 src/www/js/Mail.js:239 +msgid "All" +msgstr "Todos" + +#: src/www/js/CalendarEditor.js:136 +msgid "None" +msgstr "Nenhum" + +#: src/www/js/CalendarEditor.js:142 +msgid "Detailed" +msgstr "Detalhado" + +#: src/www/js/CalendarEditor.js:160 src/www/js/CalendarEditor.js:661 +msgid "Loading calendar data..." +msgstr "Lendo dados de calendário..." + +#: src/www/js/CalendarEditor.js:165 src/www/js/CalendarEditor.js:240 +#: src/www/js/CalendarEditor.js:666 src/www/js/CalendarEditor.js:696 +#: src/www/js/Dragonfly.js:810 +msgid "New Calendar" +msgstr "Novo calendário" + +#: src/www/js/CalendarEditor.js:340 +msgid "a username is required" +msgstr "um nome de usuário é necessário" + +#: src/www/js/CalendarEditor.js:343 +msgid "the passwords do not match" +msgstr "as senhas não são iguais" + +#: src/www/js/CalendarEditor.js:346 +msgid "a password is required" +msgstr "uma senha é necessária" + +#: src/www/js/CalendarEditor.js:536 +msgid "Someone wants to share their calendar with you." +msgstr "Alguém que compartilhar este calendário com você." + +#: src/www/js/CalendarEditor.js:537 +msgid "You can view it in a few different ways:" +msgstr "Voce pode vê-lo de outras maneiras:" + +#: src/www/js/CalendarEditor.js:538 +msgid "ICS" +msgstr "ICS" + +#: src/www/js/CalendarEditor.js:539 +msgid "CalDAV" +msgstr "CalDAV" + +#: src/www/js/CalendarEditor.js:540 +msgid "Web Browser" +msgstr "Navegador de internet" + +#: src/www/js/CalendarEditor.js:541 +msgid "If a password is needed, please ask me for it." +msgstr "Se uma senha é necessária, por favor pergunte me." + +#: src/www/js/CalendarEditor.js:633 src/www/js/CalendarEditor.js:775 +#: src/www/js/CalendarEditor.js:806 +msgid "URL:" +msgstr "URL:" + +#: src/www/js/CalendarEditor.js:809 src/www/js/CalendarEditor.js:1029 +#: src/www/js/Dragonfly.js:811 +msgid "Subscribe" +msgstr "Assinar" + +#: src/www/js/CalendarEditor.js:839 src/www/js/CalendarEditor.js:1081 +msgid "Subscribing to {0}..." +msgstr "Assinando {0}..." + +#: src/www/js/CalendarEditor.js:848 +msgid "Error subscribing to calendar {0}: {1}" +msgstr "Erro assinando calendário {0}: {1}" + +#: src/www/js/CalendarEditor.js:993 +msgid "Saving calendar" +msgstr "Salvando calendário" + +#: src/www/js/CalendarEditor.js:1014 +msgid "{0} has invited you to a calendar called {1}." +msgstr "{0} convidou voce para um calendário chamado {1}." + +#: src/www/js/CalendarEditor.js:1020 +msgid "" +"You should only subscribe to this calendar if you trust this person and the " +"server {0}." +msgstr "" +"Você deve assinar este calendário somente se voce confia nesta pessoa e no " +"servidor {0}." + +#: src/www/js/CalendarEditor.js:1027 src/www/js/Mail.js:155 +#: src/www/js/Mail.js:303 src/www/js/OccurrenceEditor.js:824 +msgid "Junk" +msgstr "Lixo" + +#: src/www/js/CalendarEditor.js:1028 src/www/js/OccurrenceEditor.js:825 +msgid "Ignore" +msgstr "Ignorar" + +#: src/www/js/CalendarEditor.js:1041 src/www/js/CalendarEditor.js:1052 +#: src/www/js/CalendarEditor.js:1062 +msgid "genericSavingChanges" +msgstr "" + +#: src/www/js/CalendarEditor.js:534 +msgid "Invitation to {0}" +msgstr "Convite para {0}" + +#: src/www/js/Calendar.js:91 +msgid "Yesterday" +msgstr "Ontem" + +#: src/www/js/Calendar.js:93 +msgid "Today" +msgstr "Hoje" + +#: src/www/js/Calendar.js:95 +msgid "Tomorrow" +msgstr "Amanhã" + +#: src/www/js/Calendar.js:346 +msgid "View:" +msgstr "Visão:" + +#: src/www/js/Calendar.js:347 +msgid "Day" +msgstr "Dia" + +#: src/www/js/Calendar.js:349 +msgid "Upcoming" +msgstr "Vindouro" + +#: src/www/js/Calendar.js:351 +msgid "Week" +msgstr "Semana" + +#: src/www/js/Calendar.js:353 +msgid "Month" +msgstr "Mês" + +#: src/www/js/CalendarView.js:79 src/www/js/CalendarView.js:252 +msgid "Prev" +msgstr "Anterior" + +#: src/www/js/CalendarView.js:81 src/www/js/CalendarView.js:255 +msgid "Next" +msgstr "Posterior" + +#: src/www/js/CalendarWidgets.js:161 +msgid "S" +msgstr "D" + +#: src/www/js/CalendarWidgets.js:162 +msgid "M" +msgstr "S" + +#: src/www/js/CalendarWidgets.js:163 +msgid "T" +msgstr "T" + +#: src/www/js/CalendarWidgets.js:164 +msgid "W" +msgstr "Q" + +#: src/www/js/CalendarWidgets.js:165 +#msgid "T" +#msgstr "Q" + +#: src/www/js/CalendarWidgets.js:166 +msgid "F" +msgstr "S" + +#: src/www/js/CalendarWidgets.js:167 +#msgid "S" +#msgstr "S" + +#: src/www/js/CalendarWidgets.js:205 +msgid "Show Today" +msgstr "Mostrar hoje" + +#: src/www/js/CalendarWidgets.js:363 +msgid "View in Calendar" +msgstr "Ver no calendário" + +#: src/www/js/Composer.js:121 +msgid "To:" +msgstr "Para:" + +#: src/www/js/Composer.js:125 +msgid "CC:" +msgstr "CC:" + +#: src/www/js/Composer.js:129 +msgid "BCC:" +msgstr "BCC:" + +#: src/www/js/Composer.js:133 +msgid "Subject:" +msgstr "Assunto:" + +#: src/www/js/Composer.js:134 +msgid "From:" +msgstr "De:" + +#: src/www/js/Composer.js:135 +msgid "Attachments:" +msgstr "Anexos:" + +#: src/www/js/Composer.js:157 +msgid "mailAttachLabel" +msgstr "Etiqueta de anexo da mensagem" + +#: src/www/js/Composer.js:161 +msgid "Discard" +msgstr "Discartar" + +#: src/www/js/Composer.js:162 +msgid "Save Draft" +msgstr "Salvar rascunho" + +#: src/www/js/Composer.js:163 +msgid "Send" +msgstr "Enviar" + +#: src/www/js/Composer.js:321 +msgid "Untitled" +msgstr "Sem título" + +#: src/www/js/Composer.js:324 +msgid "Saving draft \"{0}\"..." +msgstr "Salvando rascunho \"{0}\"" + +#: src/www/js/Composer.js:328 +msgid "Saved draft" +msgstr "Rascunho salvo" + +#: src/www/js/Composer.js:359 +msgid "Error saving draft:" +msgstr "Erro salvando rascunho:" + +#: src/www/js/Composer.js:459 +msgid "Message sent." +msgstr "Mensagem enviada." + +#: src/www/js/Composer.js:471 +msgid "Error sending message: " +msgstr "Erro enviando mensagem: " + +#: src/www/js/Composer.js:774 +msgid "Remove attachment" +msgstr "Remover anexo" + +#: src/www/js/Composer.js:839 +msgid "Uploading {0}..." +msgstr "Enviando {0}..." + +#: src/www/js/Composer.js:872 +msgid "Error saving attachment" +msgstr "Erro salvando anexo" + +#: src/www/js/Dragonfly.js:893 +msgid "Administration" +msgstr "Administração" + +#: src/www/js/Dragonfly.js:894 +msgid "Preferences" +msgstr "Preferências" + +#: src/www/js/Dragonfly.js:895 src/www/js/Dragonfly.js:896 +msgid "Search" +msgstr "Procurar" + +#: src/www/js/Dragonfly.js:899 src/www/js/Dragonfly.js:900 +#: src/www/js/OccurrenceEditor.js:449 +msgid "Summary" +msgstr "Resumo" + +#: src/www/js/Dragonfly.js:901 +msgid "Look at an overview of your mail and events." +msgstr "Veja um resumo de suas mensagens e tarefas." + +#: src/www/js/Dragonfly.js:903 src/www/js/Dragonfly.js:904 +msgid "Mail" +msgstr "Correio" + +#: src/www/js/Dragonfly.js:905 +msgid "Read your mail." +msgstr "Ler seu correio." + +#: src/www/js/Dragonfly.js:906 +msgid "Compose new mail" +msgstr "Criar nova mensagem" + +#: src/www/js/Dragonfly.js:908 src/www/js/Dragonfly.js:909 +msgid "Calendar" +msgstr "Calendário" + +#: src/www/js/Dragonfly.js:910 +msgid "View your calendar." +msgstr "Ver seu calendário." + +#: src/www/js/Dragonfly.js:911 +msgid "Create new event" +msgstr "Criar novo evento" + +#: src/www/js/Dragonfly.js:925 +msgid "Logged in: loading contacts and calendars..." +msgstr "Conectado: lendo contatos e calendários..." + +#: src/www/js/Dragonfly.js:940 +msgid "Logged in: loading" +msgstr "Conectado: carregando" + +#: src/www/js/Dragonfly.js:953 +msgid "Log out" +msgstr "Desconectado" + +#: src/www/js/Dragonfly.js:998 +msgid "" +"Bongo has finished saving changes. It is OK to browse to another location." +msgstr "" +"Bongo terminou de salvar as mudancas. Você já pode navergar outras páginas." + +#: src/www/js/Dragonfly.js:1001 +msgid "Bongo is still busy with a few things, but we should be done shortly." +msgstr "" +"Bongo ainda está ocupado com algumas outras coisasa, mas vamos acabar logo." + +#: src/www/js/Dragonfly.js:1002 +msgid "" +"Please click Cancel and wait until we are finished, otherwise your changes " +"may be lost." +msgstr "" +"Por favor, clique Cancelar e espere até finalizar, ou suas mudanças podem " +"ser perdidas." + +#: src/www/js/Dragonfly.js:1004 +msgid "Bongo needs some help from you before it's safe to leave." +msgstr "Bongo precisa de alguma ajuda sua antes de ficar seguro para sair" + +#: src/www/js/Dragonfly.js:1005 +msgid "" +"Please click Cancel and tie up any loose ends otherwise your changes may be " +"lost." +msgstr "" +"Por favor clique Cancelar e corrija quaisquer falhas eventuais, do contrário " +"suas mudanças podem ser perdidas" + +#: src/www/js/Dragonfly.js:1036 src/www/js/Login.js:113 +msgid "You have logged out successfully." +msgstr "Você desconectou com sucesso." + +#: src/www/js/Login.js:69 +msgid "Incorrect username or password." +msgstr "Usuário ou senhas incorretos." + +#: src/www/js/Login.js:71 +msgid "Some error occured while logging in - check the logs." +msgstr "" +"Algum erro ocorreu enquanto conectando - verifique os registros de sistema" + +#: src/www/js/Login.js:110 +msgid "Language" +msgstr "Língua" + +#: src/www/js/Login.js:111 +msgid "Remember me" +msgstr "Lembrar de mim" + +#: src/www/js/Login.js:112 +msgid "Login" +msgstr "Usuário" + +#: src/www/js/MailConversationView.js:226 +msgid "Reply" +msgstr "Responder" + +#: src/www/js/MailConversationView.js:237 +msgid "Reply to All" +msgstr "Responder à todos" + +#: src/www/js/MailConversationView.js:248 +msgid "Reply to List" +msgstr "Responder para a lista" + +#: src/www/js/MailConversationView.js:256 +msgid "Forward" +msgstr "Encaminhar" + +#: src/www/js/MailConversationView.js:280 +msgid "to" +msgstr "para" + +#: src/www/js/Mail.js:153 +msgid "Unarchive" +msgstr "Desarquivar" + +#: src/www/js/Mail.js:153 src/www/js/Mail.js:302 +msgid "Archive" +msgstr "Arquivar" + +#: src/www/js/Mail.js:154 +msgid "Undelete" +msgstr "Recuperar" + +#: src/www/js/Mail.js:155 +msgid "Not Junk" +msgstr "Não é lixo" + +#: src/www/js/Mail.js:156 +msgid "Unstar" +msgstr "Retirar estrela" + +#: src/www/js/Mail.js:156 src/www/js/Mail.js:305 +msgid "Star" +msgstr "Estrela" + +#: src/www/js/Mail.js:240 +msgid "To Me" +msgstr "Para mim" + +#: src/www/js/Mail.js:241 +msgid "From My Contacts" +msgstr "Dos meus contatos" + +#: src/www/js/Mail.js:242 +msgid "Mailing Lists" +msgstr "Listas de correio" + +#: src/www/js/Mail.js:307 +msgid "Select All" +msgstr "Selecionar todos" + +#: src/www/js/Mail.js:308 +msgid "Deselect All" +msgstr "Deselencionar todos" + +#: src/www/js/Mail.js:552 +msgid "Conversation" +msgstr "Conversação" + +#: src/www/js/Mail.js:552 src/www/js/Mail.js:560 +msgid "List" +msgstr "Lista" + +#: src/www/js/Mail.js:552 +msgid "View" +msgstr "Ver" + +#: src/www/js/Mail.js:560 +msgid "Item" +msgstr "Item" + +#: src/www/js/Mail.js:662 +msgid "To" +msgstr "Para" + +#: src/www/js/Mail.js:662 +msgid "From" +msgstr "De" + +#: src/www/js/MailListView.js:101 src/www/js/MailListView.js:182 +msgid "No messages here." +msgstr "Nenhuma mensagem aqui." + +#: src/www/js/MailListView.js:193 +msgid "more..." +msgstr "mais..." + +#: src/www/js/OccurrenceEditor.js:45 +msgid "Enter free-form text for example:" +msgstr "Entre um texto sem formatação, por exemplo:" + +#: src/www/js/OccurrenceEditor.js:46 +msgid "lunch with Joe tomorrow at noon" +msgstr "almoçar com Lulu amanhã ao meio-dia" + +#: src/www/js/OccurrenceEditor.js:47 +msgid "or," +msgstr "ou" + +#: src/www/js/OccurrenceEditor.js:47 +msgid "enter details instead" +msgstr "entre detalhes ao invés" + +#: src/www/js/OccurrenceEditor.js:48 +msgid "Add Event" +msgstr "Adicionar evento" + +#: src/www/js/OccurrenceEditor.js:259 +msgid "Are you sure you want to delete the event" +msgstr "Tem certeza que você quer apagar o evento" + +#: src/www/js/OccurrenceEditor.js:261 +msgid "? This cannot be undone." +msgstr "? Isto não pode ser desfeito." + +#: src/www/js/OccurrenceEditor.js:272 +msgid "This event is part of a series. Would you like" +msgstr "Este evento é parte de uma série. Você gostaria " + +#: src/www/js/OccurrenceEditor.js:273 +msgid "changes to apply to" +msgstr "de aplicar as mudanças para" + +#: src/www/js/OccurrenceEditor.js:273 +msgid "to delete" +msgstr "para apagar" + +#: src/www/js/OccurrenceEditor.js:275 +msgid "only this event" +msgstr "somente este evento" + +#: src/www/js/OccurrenceEditor.js:276 +msgid "this and following events" +msgstr "este e os próximos eventos" + +#: src/www/js/OccurrenceEditor.js:277 +msgid "all events in series" +msgstr "todos os eventos na série" + +#: src/www/js/OccurrenceEditor.js:280 src/www/js/Preferences.js:304 +msgid "genericCancel" +msgstr "Cancelar" + +#: src/www/js/OccurrenceEditor.js:366 +msgid "all day" +msgstr "todo dia" + +#: src/www/js/OccurrenceEditor.js:380 +msgid "includeEventLabel" +msgstr "Incluir Evento" + +#: src/www/js/OccurrenceEditor.js:407 +msgid "Publish this event on its own" +msgstr "Publicar este evento no seu próprio" + +#: src/www/js/OccurrenceEditor.js:432 +msgid "Event" +msgstr "Evento" + +#: src/www/js/OccurrenceEditor.js:433 +msgid "Sharomg" +msgstr "Compartilhando" + +#: src/www/js/OccurrenceEditor.js:434 +msgid "Repeat" +msgstr "Repetir" + +#: src/www/js/OccurrenceEditor.js:450 +msgid "Location" +msgstr "Local" + +#: src/www/js/OccurrenceEditor.js:451 +msgid "Notes" +msgstr "Notas" + +#: src/www/js/OccurrenceEditor.js:584 +msgid "Repeat:" +msgstr "Repetir:" + +#: src/www/js/OccurrenceEditor.js:594 +msgid "Every:" +msgstr "Cada:" + +#: src/www/js/OccurrenceEditor.js:600 src/www/js/OccurrenceEditor.js:606 +#: src/www/js/OccurrenceEditor.js:612 +msgid "On:" +msgstr "Em:" + +#: src/www/js/OccurrenceEditor.js:627 +msgid "Ending:" +msgstr "Terminando:" + +#: src/www/js/OccurrenceEditor.js:628 +msgid "Never" +msgstr "Nunca" + +#: src/www/js/OccurrenceEditor.js:628 +msgid "On date" +msgstr "Na data" + +#: src/www/js/OccurrenceEditor.js:629 +msgid "After repeating" +msgstr "Depois de repetir" + +#: src/www/js/OccurrenceEditor.js:644 +msgid "Caution" +msgstr "Cuidado" + +#: src/www/js/OccurrenceEditor.js:645 +msgid "" +"This event has a schedule that cannot be edited with Bongo; choosing to edit " +"will replace the existing schedule." +msgstr "" +"Este evento tem uma agenda que não pode ser editada com Bongo; ao escolher " +" editar você irá sobrescrever o compromisso atual." + +#: src/www/js/OccurrenceEditor.js:646 +msgid "Edit Anyway" +msgstr "Editar mesmo assim" + +#: src/www/js/OccurrenceEditor.js:810 +msgid "{0} has invited you to:" +msgstr "{0} convidou você para:" + +#: src/www/js/OccurrenceEditor.js:812 +msgid "Calendar:" +msgstr "Calendário:" + +#: src/www/js/Preferences.js:304 +msgid "genericSave" +msgstr "Salvar" + +#: src/www/js/Search.js:303 +msgid "Sorry, but your query returned no results." +msgstr "Sinto muito, mas sua busca não retornou resultados." + +#: src/www/js/Search.js:304 +msgid "Here are some tips for getting better results:" +msgstr "Aqui vão algumas dicas para ter melhores resultados:" + +#: src/www/js/Search.js:306 +msgid "Make sure all words are spelt correctly." +msgstr "Certifique-se que todas as palavras estão corretas." + +#: src/www/js/Search.js:307 +msgid "Try different keywords." +msgstr "Tente palavras diferentes." + +#: src/www/js/Search.js:308 +msgid "Be less specific in your search." +msgstr "Seja menos específico." + +#: src/www/js/Search.js:338 +msgid "Search results for {0}" +msgstr "Resultados da pesquisa para {0}" + +#: src/www/js/Summary.js:43 +msgid "Starred Mail" +msgstr "Mensagens com estrela" + +#: src/www/js/Summary.js:47 +msgid "Mail to Me" +msgstr "Mensagens para mim" + +#: src/www/js/Summary.js:51 +msgid "Mail from my contacts" +msgstr "Mensagens dos meus contatos" + +#: src/www/js/Summary.js:55 +msgid "Mail from mailing lists" +msgstr "Mensagens de listas de discussão" + +#: src/www/js/Summary.js:60 +msgid "You do not seem to have any new or unread emails." +msgstr "Parece que voce não tem nenhuma mensagem nova ou não lida" + +#: src/www/js/Summary.js:65 +msgid "Invitations" +msgstr "Convites" + +#: src/www/js/Summary.js:70 +msgid "Upcoming events" +msgstr "Eventos futuros" + +#: src/www/js/Summary.js:328 +msgid "summaryInviteFrom" +msgstr "" + +#: src/www/js/ValidatingEntry.js:438 +msgid "Start on:" +msgstr "Começar em:" + +#: src/www/js/ValidatingEntry.js:440 src/www/js/ValidatingEntry.js:448 +msgid "at:" +msgstr "em:" + +#: src/www/js/ValidatingEntry.js:446 +msgid "dateEndOn" +msgstr "data acaba em" + +#: src/www/js/Widgets.js:648 +msgid "You have unsaved changes." +msgstr "Você tem mudanças não salvas" + +#: src/www/js/Widgets.js:696 +msgid "An error has occured:" +msgstr "Um erro ocorreu:" + +#: src/www/js/Widgets.js:698 +msgid "Great." +msgstr "Grande." + +#: src/www/js/Widgets.js:950 +msgid "Add timezone..." +msgstr "Adicione um fuso horário" + +#: src/www/js/Widgets.js:952 +msgid "Edit list..." +msgstr "Edite a lista..." + +#: src/www/js/Widgets.js:955 +msgid "Other..." +msgstr "Outro..." + +#: src/www/js/Widgets.js:1081 +msgid "Set as Default" +msgstr "Configure como padrão" + +#: src/www/js/Widgets.js:1082 +msgid "Add..." +msgstr "Adicionar..." + +#: src/www/js/Widgets.js:1118 +msgid "Region" +msgstr "Região" + +#: src/www/js/Widgets.js:1118 +msgid "Timezone" +msgstr "Fuso horário" + +#: src/www/js/Widgets.js:1129 +msgid "Add as Default" +msgstr "Adicionar como padrão" + +#: src/www/js/Widgets.js:1131 +msgid "Set" +msgstr "Configurar" diff --git a/po/bongo/pt_BR.po b/po/bongo/pt_BR.po new file mode 100644 index 0000000..b443231 --- /dev/null +++ b/po/bongo/pt_BR.po @@ -0,0 +1,893 @@ +# Translation of Bongo Project +# Copyright (C) 2007 +# This file is distributed under the same license as the Bongo package. +# Igor Morgado , 2007 +# +# Detalhes sobre a traducao (Igor Morgado) +# - Na palavra STORE manti a traducao como estoque, devido a descricao +# de um dos desenvolvedores, a saber: +# " It's a data store, yeah. We refer to it as +# "the store" because store can mean "place you put things" " +# - Respeitei todo texto contido, inclusive os erros (propositais ou nao) +# + +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: bongo-devel@gna.org\n" +"POT-Creation-Date: 2007-07-13 11:46+0100\n" +"PO-Revision-Date: 2007-11-08 15:00+BRST\n" +"Last-Translator: Igor Morgado \n" +"Language-Team: Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=pt_BR.UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/apps/config/config.c:48 +#, c-format +msgid "bongo-config: Could not drop to unpriviliged user '%s'\n" +msgstr "bongo-config: Não pude me tornar o usuário desprivilegiado '%s'\n" + +#: src/apps/config/config.c:113 +msgid "ERROR: Couldn't write data\n" +msgstr "ERRO: Não pude escrever os dados\n" + +#: src/apps/config/config.c:115 +msgid "ERROR: Wouldn't accept data\n" +msgstr "ERRO: Não pude aceitar os dados\n" + +#: src/apps/config/config.c:130 +msgid "ERROR: Couldn't create collection\n" +msgstr "ERRO: Não pude criar coleção\n" + +#: src/apps/config/config.c:134 +msgid "ERROR: Couldn't set acls on /config\n" +msgstr "ERRO: Não pude configurar ACLs em /config\n" + +#: src/apps/config/config.c:140 +msgid "ERROR: Couldn't load default config set\n" +msgstr "ERRO: Não pude ler o grupo de configurações default\n" + +#: src/apps/config/config.c:175 +msgid "ERROR: Couldn't write\n" +msgstr "ERRO: Não pude escrever\n" + +#: src/apps/config/config.c:178 +msgid "ERROR: rigts\n" +msgstr "ERRO: Direitos\n" + +#: src/apps/config/config.c:198 +msgid "Initializing calendar data...\n" +msgstr "Iniciando dados de calendário...\n" + +#: src/apps/config/config.c:201 +msgid "ERROR: Couldn't initialise calendar library\n" +msgstr "ERRO: Não pude iniciar a biblioteca de calendário\n" + +#: src/apps/config/config.c:205 +msgid "Initializing store...\n" +msgstr "Iniciando o estoque...\n" + +#: src/apps/config/config.c:217 +msgid "ERROR: Couldn't start the store!\n" +msgstr "ERRO: Não pude iniciar o estoque!\n" + +#: src/apps/config/config.c:226 +msgid "ERROR: Out of memory\n" +msgstr "ERRO: Falta de memória\n" + +#: src/apps/config/config.c:231 +msgid "ERROR: Could not connect to store\n" +msgstr "ERRO: Não pude me conectar ao estoque\n" + +#: src/apps/config/config.c:235 +msgid "ERROR: Could not authenticate to store\n" +msgstr "ERRO: Não pude me autenticar com o estoque\n" + +#: src/apps/config/config.c:240 +msgid "ERROR: Couldn't access store\n" +msgstr "ERRO: Não pude acessar o estoque\n" + +#: src/apps/config/config.c:244 +msgid "Setting default agent configuration...\n" +msgstr "Configurando o agente de configuração padrão\n" + +#: src/apps/config/config.c:248 +msgid "ERROR: Couldn't setup default configuration\n" +msgstr "ERRO: Não pude fazer a configuração padrão\n" + +#: src/apps/config/config.c:250 +msgid "Complete.\n" +msgstr "Completo.\n" + +#: src/apps/config/config.c:258 +msgid "ERROR: Couldn't shut down store\n" +msgstr "ERRO: Não pude fechar o estoque\n" + +#: src/apps/config/config.c:305 +msgid "Couldn't create data directory!\n" +msgstr "Não pude criar o diretório de dados!\n" + +#: src/apps/config/config.c:308 +msgid "IP address to run on" +msgstr "Endereço IP para usar" + +#: src/apps/config/config.c:309 +msgid "DNS name to use:" +msgstr "Nome DNS para usar:" + +#: src/apps/config/config.c:312 +msgid "Creating random seed...\n" +msgstr "Criando a fonte de aleatoriedade...\n" + +#: src/apps/config/config.c:316 +msgid "Creating DH parameters...\n" +msgstr "Criando parâmetros DH...\n" + +#: src/apps/config/config.c:327 +#, c-format +msgid "ERROR: Couldn't write DH params to %s\n" +msgstr "ERRO: Não pude escrever parâmetros DH em %s\n" + +#: src/apps/config/config.c:331 +msgid "Creating RSA parameters...\n" +msgstr "Criando parâmetros RSA...\n" + +#: src/apps/config/config.c:342 +#, c-format +msgid "ERROR: Couldn't write RSA params to %s\n" +msgstr "ERRO: Não pude escrever parâmetros RSA em %s\n" + +#: src/apps/config/config.c:347 +msgid "Creating private key...\n" +msgstr "Criando chave privada...\n" + +#: src/apps/config/config.c:350 src/apps/config/config.c:380 +#, c-format +msgid "ERROR: %s\n" +msgstr "ERRO: %s\n" + +#: src/apps/config/config.c:355 +#, c-format +msgid "ERROR: Couldn't create private key. %s\n" +msgstr "ERRO: Não pude criar a chave privada. %s\n" + +#: src/apps/config/config.c:361 +#, c-format +msgid "ERROR: Couldn't export private key. %s\n" +msgstr "ERRO: Não pude exportar a chave privada.%s\n" + +#: src/apps/config/config.c:362 +#, c-format +msgid " Size: %d, Ret: %d\n" +msgstr " Tam.: %d, Ret: %d\n" + +#: src/apps/config/config.c:371 +#, c-format +msgid "ERROR: Couldn't write private key to %s\n" +msgstr "ERRO: Não pude escrever a chave privada em %s\n" + +#: src/apps/config/config.c:377 +msgid "Creating SSL/TLS certificate...\n" +msgstr "Criando o certificado SSL/TLS...\n" + +#: src/apps/config/config.c:411 +#, c-format +msgid "ERROR: Couldn't self-sign certificate. %s\n" +msgstr "ERRO: Não pude auto-assinar o certificado. %s\n" + +#: src/apps/config/config.c:418 +#, c-format +msgid "ERROR: Couldn't create certificate. %s\n" +msgstr "ERRO: Não pude criar o certificado. %s\n" + +#: src/apps/config/config.c:426 +#, c-format +msgid "ERROR: Couldn't write certificate to %s\n" +msgstr "ERRO: Não pude escrever o certificado em %s\n" + +#: src/apps/config/config.c:446 +#, c-format +msgid "Can't get information on current build!\n" +msgstr "Não pude pegar a informação da versão atual!\n" + +#: src/apps/config/config.c:449 +#, c-format +msgid "Installed build: %s %s%d\n" +msgstr "Versão instalada: %s %s%d\n" + +#: src/apps/config/config.c:451 +#, c-format +msgid "This is modified software.\n" +msgstr "Este é um software modificado.\n" + +#: src/apps/config/config.c:454 +#, c-format +msgid "Version currently available: unable to request online information.\n" +msgstr "Versão disponível atualmente: incapaz de requisitar informação online.\n" + +#: src/apps/config/config.c:456 +#, c-format +msgid "Version currently available: %s%d\n" +msgstr "Verão disponível atualmente: %s%d\n" + +#: src/apps/config/config.c:531 +msgid "ERROR : Couldn't initialize Bongo libraries\n" +msgstr "ERRO : Não pude iniciar bibliotecas Bongo\n" + +#: src/apps/backup/backup.c:63 src/apps/backup/backup.c:918 +#: src/apps/backup/backup.c:971 +#, c-format +msgid "Couldn't close file (%s)\n" +msgstr "Não pude fechar arquivo (%s)\n" + +#: src/apps/backup/backup.c:70 src/apps/backup/backup.c:86 +msgid "Couldn't open user database\n" +msgstr "Não pude abrir base de dados do usuário\n" + +#: src/apps/backup/backup.c:79 +msgid "Failed to initialize database file\n" +msgstr "Falhei ao iniciar arquivo de base de dados\n" + +#: src/apps/backup/backup.c:93 +msgid "User database does not exist\n" +msgstr "Base de dados do usuário não existe\n" + +#: src/apps/backup/backup.c:113 +msgid "Couldn't delete prepared statement (QUERY_PROP_VAL)\n" +msgstr "Não pude deletar declaração preparada (QUERY_PROP_VAL)\n" + +#: src/apps/backup/backup.c:125 +msgid "Couldn't delete prepared statement (QUERY_HIST_EVENT)\n" +msgstr "Não pude deletar declaração preparada (QUERY_HIST_EVENT)\n" + +#: src/apps/backup/backup.c:137 +msgid "Couldn't delete prepared statement (QUERY_DOC_ATTRS)\n" +msgstr "Não pude deletar declaração preparada (QUERY_DOC_ATTRS)\n" + +#: src/apps/backup/backup.c:149 +msgid "Couldn't delete prepared statement (QUERY_DOC_INFO)\n" +msgstr "Não pude deletar declaração preparada (QUERY_DOC_INFO)\n" + +#: src/apps/backup/backup.c:158 +msgid "Couldn't close database\n" +msgstr "Não pude fechar banco de dados\n" + +#: src/apps/backup/backup.c:177 +msgid "Couldn't create prepared statement (QUERY_PROP_VAL)\n" +msgstr "Não pude criar declaração preparada (QUERY_PROP_VAL)\n" + +#: src/apps/backup/backup.c:190 +msgid "Couldn't bind to prepared statement (QUERY_PROP_VAL)\n" +msgstr "Não pude me ligar a declaração preparada (QUERY_PROP_VAL)\n" + +#: src/apps/backup/backup.c:201 src/apps/backup/backup.c:647 +msgid "Insufficient memory available\n" +msgstr "Memória disponível insuficiente\n" + +#: src/apps/backup/backup.c:212 +msgid "Query failed to execute (QUERY_PROP_VAL)\n" +msgstr "Pedido falhou em executar (QUERY_PROP_VAL)\n" + +#: src/apps/backup/backup.c:219 +msgid "Couldn't reset prepared statement (QUERY_PROP_VAL)\n" +msgstr "Não puder resetar declaração preparada (QUERY_PROP_VAL)\n" + +#: src/apps/backup/backup.c:236 +msgid "Couldn't create prepared statement (QUERY_DOC_ATTRS)\n" +msgstr "Não pude criar declaração preparada (QUERY_DOC_ATTRS)\n" + +#: src/apps/backup/backup.c:247 +msgid "Couldn't bind to prepared statement (QUERY_DOC_ATTRS)\n" +msgstr "Não pude me ligar à declaração preparada (QUERY_DOC_ATTRS)\n" + +#: src/apps/backup/backup.c:264 +msgid "Query failed to execute (QUERY_DOC_ATTRS)\n" +msgstr "Pedido falhou em executar (QUERY_DOC_ATTRS)\n" + +#: src/apps/backup/backup.c:271 +msgid "Couldn't reset prepared statement (QUERY_DOC_ATTRS)\n" +msgstr "Não puder resetar declaração preparada (QUERY_DOC_ATTRS)\n" + +#: src/apps/backup/backup.c:291 +msgid "Couldn't create prepared statement (QUERY_ALL_PROPS)\n" +msgstr "Não pude criar declaração preparada (QUERY_ALL_PROPS)\n" + +#: src/apps/backup/backup.c:302 +msgid "Couldn't bind to prepared statement (QUERY_ALL_PROPS)\n" +msgstr "Não pude me ligar à declaração preparada (QUERY_ALL_PROPS)\n" + +#: src/apps/backup/backup.c:331 src/apps/backup/backup.c:1128 +msgid "Query failed to execute (QUERY_ALL_PROPS)\n" +msgstr "Pedido falou em executar (QUERY_ALL_PROPS)\n" + +#: src/apps/backup/backup.c:342 +msgid "Couldn't reset prepared statement (QUERY_ALL_PROPS)\n" +msgstr "Não pude resetar declaração preparada (QUERY_ALL_PROPS)\n" + +#: src/apps/backup/backup.c:359 +msgid "Couldn't create prepared statement (QUERY_HIST_EVENT)\n" +msgstr "Não pude criar declaração preparada (QUERY_HIST_EVENT)\n" + +#: src/apps/backup/backup.c:370 +msgid "Couldn't bind to prepared statement (QUERY_HIST_EVENT)\n" +msgstr "Não pude me ligar à declaração preparada (QUERY_HIST_EVENT)\n" + +#: src/apps/backup/backup.c:383 +msgid "Query failed to execute (QUERY_HIST_EVENT)\n" +msgstr "Query falhou em executar (QUERY_HIST_EVENT)\n" + +#: src/apps/backup/backup.c:390 +msgid "Couldn't reset prepared statement (QUERY_HIST_EVENT)\n" +msgstr "Não pude resetar declaração preparada (QUERY_HIST_EVENT)\n" + +#: src/apps/backup/backup.c:460 +#, c-format +msgid "Connection to host %s failed\n" +msgstr "Conexão ao computador %s falhou\n" + +#: src/apps/backup/backup.c:468 +#, c-format +msgid "Connection to host %s failed" +msgstr "Conexão ao computador %s falhou" + +#: src/apps/backup/backup.c:479 +#, c-format +msgid "NMAP command failed (PASS): %s\n" +msgstr "Comando NMAP falhou (PASS): %s\n" + +#: src/apps/backup/backup.c:489 +#, c-format +msgid "NMAP command failed (MANAGE): %s\n" +msgstr "Comando NMAP falhou (MANAGE): %s\n" + +#: src/apps/backup/backup.c:513 src/apps/backup/backup.c:568 +#, c-format +msgid "No such user on this host (%s)\n" +msgstr "Usuário não existe neste computador (%s)\n" + +#: src/apps/backup/backup.c:521 +msgid "Couldn't parse NMAP response (VRFY)\n" +msgstr "Não pude interpretar resposta NMAP (VRFY)\n" + +#: src/apps/backup/backup.c:529 +#, c-format +msgid "Unrecognized NMAP response (VRFY): %s\n" +msgstr "Resposta NMAP desconhecida (VRFY): %s\n" + +#: src/apps/backup/backup.c:538 +msgid "NMAP connection error (VRFY)\n" +msgstr "Erro de conexão NMAP (VRFY)\n" + +#: src/apps/backup/backup.c:549 +#, c-format +msgid "NMAP command failed (RSET): %s\n" +msgstr "Comando NMAP falhou (RSET): %s\n" + +#: src/apps/backup/backup.c:560 +#, c-format +msgid "NMAP command failed (USER): %s\n" +msgstr "Comando NMAP falhou (USER): %s\n" + +#: src/apps/backup/backup.c:618 src/apps/backup/backup.c:655 +#: src/apps/backup/backup.c:1229 +msgid "NMAP connection error (DPGET)\n" +msgstr "Erro de conexão NMAP (DPGET)\n" + +#: src/apps/backup/backup.c:633 +msgid "Could not parse NMAP response (DPGET)\n" +msgstr "Não pude interpretar resposta NMAP (DPGET)\n" + +#: src/apps/backup/backup.c:681 +msgid "Database query failure (QUERY_INS_HIST)\n" +msgstr "Falha no pedido ao banco de dados (QUERY_INS_HIST)\n" + +#: src/apps/backup/backup.c:695 +msgid "Database query failure (QUERY_INS_PROP)\n" +msgstr "Falha no pedido ao banco de dados (QUERY_INS_PROP)\n" + +#: src/apps/backup/backup.c:719 +#, c-format +msgid "Unrecognized NMAP response (DPGET): %s\n" +msgstr "Resposta NMAP desconhecida (DPGET): %s\n" + +#: src/apps/backup/backup.c:732 src/apps/backup/backup.c:750 +msgid "NMAP connection error (DREAD)\n" +msgstr "Erro de conexão NMAP (DREAD)\n" + +#: src/apps/backup/backup.c:758 +msgid "Database query failure (QUERY_INS_DOC)\n" +msgstr "Falha no pedido ao banco de dados (QUERY_INS_DOC)\n" + +#: src/apps/backup/backup.c:773 +#, c-format +msgid "Unrecognized NMAP response (DREAD): %s\n" +msgstr "Resposta NMAP desconhecida (DREAD): %s\n" + +#: src/apps/backup/backup.c:810 +msgid "NMAP connection error (DINFO)\n" +msgstr "Erro de conexão NMAP: (DINFO)\n" + +#: src/apps/backup/backup.c:835 +msgid "Could not parse NMAP response (DINFO)\n" +msgstr "Não pude interpretar resposta NMAP (DINFO)\n" + +#: src/apps/backup/backup.c:854 +#, c-format +msgid "Unrecognized NMAP response (DINFO): %s\n" +msgstr "Resposta NMAP desconhecida (DINGO): %s\n" + +#: src/apps/backup/backup.c:925 src/apps/backup/backup.c:978 +#: src/apps/backup/backup.c:1302 src/apps/backup/backup.c:1345 +#, c-format +msgid "Couldn't open file (%s)\n" +msgstr "Não pude abrir arquivo (%s)\n" + +#: src/apps/backup/backup.c:1030 src/apps/backup/backup.c:1052 +msgid "NMAP connection error (DSTOR)\n" +msgstr "Erro de conexão NMAP (DSTOR)\n" + +#: src/apps/backup/backup.c:1037 +msgid "Couldn't set file position\n" +msgstr "Não pude definir a posição do arquivo\n" + +#: src/apps/backup/backup.c:1044 +#, c-format +msgid "Unrecognized NMAP response (DSTOR): %s\n" +msgstr "Resposta NMAP desconhecida (DSTOR): %s\n" + +#: src/apps/backup/backup.c:1064 +#, c-format +msgid "Unrecognized NMAP response (DCREA): %s\n" +msgstr "Resposta NMAP desconhecida (DCREA): %s\n" + +#: src/apps/backup/backup.c:1071 +msgid "NMAP connection error (DCREA)\n" +msgstr "Erro de conexão NMAP (DCREA)\n" + +#: src/apps/backup/backup.c:1100 src/apps/backup/backup.c:1117 +msgid "NMAP connection error (DPSET)\n" +msgstr "Erro de conexão NMAP (DPSET)\n" + +#: src/apps/backup/backup.c:1108 +#, c-format +msgid "Unrecognized NMAP response (DPSET): %s\n" +msgstr "Resposta NMAP desconhecida (DPSET): %s\n" + +#: src/apps/backup/backup.c:1136 +msgid "Couldn't delete prepared statement (QUERY_ALL_PROPS)\n" +msgstr "Nao pude deletar a declaração preparada (QUERY_ALL_PROPS)\n" + +#: src/apps/backup/backup.c:1143 src/apps/backup/backup.c:1152 +msgid "Document not found in store\n" +msgstr "Documento não encontrado no estoque\n" + +#: src/apps/backup/backup.c:1190 +msgid "Couldn't create prepared statement (QUERY_DOCS_MOD)\n" +msgstr "Não pude criar a declaração preparada (QUERY_DOCS_MOD)\n" + +#: src/apps/backup/backup.c:1198 +msgid "Couldn't bind to prepared statement (QUERY_DOCS_MOD)\n" +msgstr "Não pude me ligar a declaração preparada (QUERY_DOCS_MOD)\n" + +#: src/apps/backup/backup.c:1217 +msgid "Couldn't parse NMAP response (DPGET)\n" +msgstr "Não pude interpretar resposta NMAP (DPGET)\n" + +#: src/apps/backup/backup.c:1254 +msgid "Database query failure (QUERY_DOCS_MOD)\n" +msgstr "Falha no pedido ao banco de dados (QUERY_DOCS_MOD)\n" + +#: src/apps/backup/backup.c:1263 +msgid "Couldn't delete prepared statement (QUERY_DOCS_MOD)\n" +msgstr "Não pude deletar a declaração preparada (QUERY_DOCS_MOD)\n" + +#: src/apps/backup/backup.c:1441 +msgid "" +"bongobackup - Backup & restore a Bongo NMAP document store.\n" +"\n" +"Usage: bongobackup [options] [command]\n" +"\n" +"Options:\n" +" -h, --host=[ip address] defaults to '127.0.0.1'\n" +" -p, --passwd=[password] password used to authenticate\n" +" -s, --store=[path] path to local backup store\n" +" -u, --user=[user] username used to authenticate\n" +" -v, --verbose verbose output\n" +"\n" +"Commands:\n" +" backup [user[:guid[,..]][ ..]] appends incremental backup to the store\n" +" restore [user[:guid[,..]][ ..]] restores documents from store to server\n" +" search [filter[,..]] searches the store for documents\n" +" rollback [MM/DD/YYYY] permanently deletes data store after date\n" +"\n" +"Search Filters:\n" +" after=[MM/DD/YYYY] only search documents after this date\n" +" before=[MM/DD/YYYY] only search documents before this date\n" +" string=[string[:..]] strings may be enclosed in single quotes " +"('')\n" +" type=[type[:..]] only search type(s) (mail, cal, ab)\n" +" user=[user[:..]] only search documents owned by user(s)\n" +msgstr "" +"bongobackup - arquiva e recupara um estoque NMAP do Bongo.\n" +"\n" +"Uso: bongobackup [opções] [comando]\n" +"\n" +"Opções:\n" +" -h, --host=[endereço IP] default é '127.0.0.1'\n" +" -p, --password=[senha] senha usada para autenticar\n" +" -s, --store=[caminho] caminho para o estoque de backup local\n" +" -u, --user=[usuário] nome de usuário usado para autenticar\n" +" -v, --verbose saída com mais informações\n" +"\n" +"Comandos:\n" +" backup [usuário[:guid[,..]][ ..]] anexa backup incremental ao estoque\n" +" restore [usuárior[:guid[,..]][ ..]] recupera documentos do estoque para o\n" +" servidor\n" +" search [filtro[,..]] busca no estoque por documentos\n" +" rollback [MM/DD/AAAA] apaga permanentemente dados apos a data\n" +"\n" +"Filtos de busca:\n" +" after=[MM/DD/AAAA] busca por documentos após esta data\n" +" before=[MM/DD/AAAA] busca por documentos antes desta data\n" +" string=[texto[:..]] texto pode estar entre aspas simples\n" +" ('')\n" +" type=[tipo[:..]] busca por tipo(s) (mail, cal, ab)\n" +" user=[usuário[:..]] busca por documentos de um usuário(s)\n" + +#: src/apps/backup/backup.c:1461 +msgid "Bongo Backup: " +msgstr "Bongo Backup: " + +#: src/apps/backup/backup.c:1472 +msgid "Failed to initialize memory manager\n" +msgstr "Falha em iniciar o gerenciador de memória\n" + +#: src/apps/backup/backup.c:1490 +#, c-format +msgid "Invalid store path: %s\n" +msgstr "Caminho para o estoque inválido: %s\n" + +#: src/apps/backup/backup.c:1496 src/apps/backup/backup.c:1501 +#, c-format +msgid "Unrecognized option: %s\n" +msgstr "Opção desconhecida: %s\n" + +#: src/apps/backup/backup.c:1515 +#, c-format +msgid "Unrecognized command: %s\n" +msgstr "Comando desconhecido: %s\n" + +#: src/apps/backup/backup.c:1518 +msgid "No command specified\n" +msgstr "Nenhum comando espeficicado\n" + +#: src/apps/backup/backup.c:1553 +msgid "Backing up data\n" +msgstr "Armazenando cópias de segurança\n" + +#: src/apps/backup/backup.c:1570 +#, c-format +msgid "Unrecognized NMAP response (ULIST): %s\n" +msgstr "Resposta NMAP desconhecida (ULIST): %s\n" + +#: src/apps/backup/backup.c:1597 +msgid "Backup complete\n" +msgstr "Armazenamento de segurança completo\n" + +#: src/apps/backup/backup.c:1599 +msgid "Backup failed\n" +msgstr "Armazenamento de cópias de segurança falhou\n" + +#: src/apps/backup/backup.c:1604 src/apps/backup/backup.c:1651 +msgid "Failed to initialize connection manager\n" +msgstr "Falhei em iniciar o gerenciador de conexões\n" + +#: src/apps/backup/backup.c:1608 +msgid "Restoring data\n" +msgstr "Recuperando dados\n" + +#: src/apps/backup/backup.c:1624 +#, c-format +msgid "Couldn't open store directory %s\n" +msgstr "Não pude abrir diretório do estoque%s\n" + +#: src/apps/backup/backup.c:1644 +msgid "Restore complete\n" +msgstr "Recuperação de segurança completa\n" + +#: src/apps/backup/backup.c:1646 +msgid "Restore failed\n" +msgstr "Recurepação de segurança falhou\n" + +#: src/apps/backup/backup.c:1655 +msgid "Search command not implemented\n" +msgstr "Comando de busca nao implementado\n" + +#: src/apps/manager/manager.c:137 +#, c-format +msgid "bongomanager: %s terminated with signal %d.\n" +msgstr "bongomanager: %s terminou com sinal %d.\n" + +#: src/apps/manager/manager.c:143 +#, c-format +msgid "bongo-manager: %s exited\n" +msgstr "bongo-manager: %s saiu\n" + +#: src/apps/manager/manager.c:204 +#, c-format +msgid "couldn't set rlimit: %s\n" +msgstr "não pude atribuir rlimit: %s\n" + +#: src/apps/manager/manager.c:223 +#, c-format +msgid "failed to exec %s (%s)\n" +msgstr "falhei em executar %s (%s)\n" + +#: src/apps/manager/manager.c:227 +#, c-format +msgid "bongo-manager: Could not drop to unprivileged user '%s', Exiting.\n" +msgstr "bongo-manager: Não pude me tornar o usuário desprivilegiado '%s', Saindo.\n" + +#: src/apps/manager/manager.c:275 +#, c-format +msgid "" +"bongo-manager: %s has crashed %d times within %d seconds of each other, not " +"restarting.\n" +msgstr "" +"bongo-manager: %s falhou %d vezes dentro de um periodo de %d segundos, não " +"irei iniciar.\n" + +#: src/apps/manager/manager.c:297 +#, c-format +msgid "bongo-manager: starting %s\n" +msgstr "bongo-manager: iniciando %s\n" + +#: src/apps/manager/manager.c:317 +#, c-format +msgid "bongo-manager: couldn't read config from store\n" +msgstr "bongo-manager: não pude ler configuração do estoque\n" + +#: src/apps/manager/manager.c:322 +#, c-format +msgid "bongo-manager: couldn't parse JSON config\n" +msgstr "bongo-manager: não pude interpretar a configuração JSON\n" + +#: src/apps/manager/manager.c:327 +#, c-format +msgid "manager: couldn't find agent list\n" +msgstr "manager: não pude achar a lista de agentes\n" + +#: src/apps/manager/manager.c:422 +#, c-format +msgid "bongo-manager: unlikely pid, Exiting\n" +msgstr "bongo-manager: PID improvável, Saindo\n" + +#: src/apps/manager/manager.c:454 +#, c-format +msgid "bongo-manager: couldn't unlink %s\n" +msgstr "bongo-manager: não pude remover %s\n" + +#: src/apps/manager/manager.c:495 +#, c-format +msgid "" +"Uso: bongo-manager [OPTIONS]\n" +"Starts and manages Bongo processes.\n" +"\n" +"Normal options:\n" +"\t-d: Run in background after starting agents.\n" +"\t-k: Keep agents alive, restarting them after crashes.\n" +"\t-f: Force start, replacing " +msgstr "" +"Usage: bongo-manager [OPÇÕES]\n" +"Inicia e gerencia os processos do Bongo.\n" +"\n" +"Opções normais:\n" +"\t-d: Roda em segundo plano após iniciar os agentes.\n" +"\t-k: Mantém os agentes rodando, reiniciando-os após falhas.\n" +"\t-f: Força início, substituindo" + +#: src/apps/manager/manager.c:554 +#, c-format +msgid "%s: -s cannot be supplied with other options.\n" +msgstr "%s: -s não pode ser usado com outras opções.\n" + +#: src/apps/manager/manager.c:559 +#, c-format +msgid "%s: -r cannot be supplied with other options.\n" +msgstr "%s: -r não pode ser usado com outras opções.\n" + +#: src/apps/manager/manager.c:564 +#, c-format +msgid "%s: -l cannot be supplied with other options.\n" +msgstr "%s: -l não pode ser usado com outras opções.\n" + +#: src/apps/manager/manager.c:597 +#, c-format +msgid "bongo-manager: killed existing managed-slapd process.\n" +msgstr "bongo-manager: matou o processo slapd-gerenciado existente.z\n" + +#: src/apps/manager/manager.c:599 +#, c-format +msgid "bongo-manager: could not kill existing managed-slapd process.\n" +msgstr "bongo-manager: nao pode matar o processo slapd-gerenciado existente.\n" + +#: src/apps/manager/manager.c:603 +#, c-format +msgid "bongo-manager: managed-slapd appears to be running as pid %ld\n" +msgstr "bongo-manager: slapd-gerenciado parece estar rodando com PID %ld\n" + +#: src/apps/manager/manager.c:604 +#, c-format +msgid "" +"bongo-manager: if this is definitely the bongo slapd, you can run with -e to " +"kill it\n" +msgstr "" +"bongo-manager: se isto é definitivamente o slapd do bongo, voce pode roda-lo " +"com -e para mata-lo\n" + +#: src/apps/manager/manager.c:614 +#, c-format +msgid "bongo-manager: error reading managed slapd port from config file.\n" +msgstr "" +"bongo-manager: erro lendo a porta do slapd-gerenciado do arquivo de\n" +"configuração\n" + +#: src/apps/manager/manager.c:622 +#, c-format +msgid "Error reading managed slapd path from config file.\n" +msgstr "Erro lendo o caminho do slapd-gerenciado do arquivo de configuração\n" + +#: src/apps/manager/manager.c:628 +#, c-format +msgid "bongo-manager: starting managed slapd...\n" +msgstr "bongo-manager: iniciando o slapd gerenciado...\n" + +#: src/apps/manager/manager.c:660 +#, c-format +msgid "Error creating socket: %s\n" +msgstr "Erro criando socket: %s\n" + +#: src/apps/manager/manager.c:680 +#, c-format +msgid "bongo-manager: error connecting to slapd: %s\n" +msgstr "bongo-manager: erro conectando-se ao slapd: %s\n" + +#: src/apps/manager/manager.c:686 +#, c-format +msgid "bongo-manager: slapd started\n" +msgstr "bongo-manager: slapd iniciado\n" + +#: src/apps/manager/manager.c:733 +#, c-format +msgid "bongo-manager: could not fork into background (%d): %s\n" +msgstr "bongo-manager: não pude duplicar para segundo plano (%d): %s\n" + +#: src/apps/manager/manager.c:746 +#, c-format +msgid "bongo-manager: running in background\n" +msgstr "bongo-manager: rodando em segundo plano\n" + +#: src/apps/manager/manager.c:791 +#, c-format +msgid "bongo-manager: could not drop to unprivileged user '%s'\n" +msgstr "bongo-manager: não pude me tornar o usuário desprivilegiado '%s'\n" + +#: src/apps/manager/manager.c:803 +#, c-format +msgid "bongo-manager: must be run by root\n" +msgstr "bongo-manager: deve ser executado pelo root\n" + +#: src/apps/manager/manager.c:811 src/apps/manager/manager.c:829 +#, c-format +msgid "bongo-manager: could not open pid file '%s'\n" +msgstr "bongo-manager: não pude abrir arquivo de PID '%s'\n" + +#: src/apps/manager/manager.c:817 src/apps/manager/manager.c:835 +#, c-format +msgid "bongo-manager: bongo-manager does not appear to be running.\n" +msgstr "bongo-manager: bongo-manager parece não estar rodando.\n" + +#: src/apps/manager/manager.c:819 +#, c-format +msgid "bongo-manager: unable to reload services: %s\n" +msgstr "bongo-manager: incapaz de reiniciar serviços: %s\n" + +#: src/apps/manager/manager.c:837 +#, c-format +msgid "bongo-manager: unable to shut down services: %s\n" +msgstr "bongo-manager: incapaz de deslugar serviços: %s\n" + +#: src/apps/manager/manager.c:857 +#, c-format +msgid "bongo-manager: another bongo-manager process appears to be running.\n" +msgstr "bongo-manager: outro procesos do bongo-manager parecer estar rodando.\n" + +#: src/apps/manager/manager.c:858 +#, c-format +msgid "" +"bongo-manager: run with -s to stop an existing process, or -f to ignore the " +"existing pidfile.\n" +msgstr "" +"bongo-manager: rode com -s pra parar um processo existente, ou -f para " +" ignorar o arquivo de PID existente.\n" + +#: src/apps/manager/manager.c:860 +#, c-format +msgid "bongo-manager: removing stale lock file in %s.\n" +msgstr "bongo-manager: removendo arquivo de travamento perdido em %s.\n" + +#: src/apps/manager/manager.c:864 +#, c-format +msgid "bongo-manager: could not remove stale lock file in %s.\n" +msgstr "" +"bongo-manager: não pude remover o arquivo de travamento perdido em %s.\n" + +#: src/apps/manager/manager.c:867 +#, c-format +msgid "" +"bongo-manager: %s user does not have permission to create a lock file in %s\n" +msgstr "" +"bongo-manager: usuário %s nao tem permissão para criar o arquivo de travamento " +"em %s\n" + +#: src/apps/manager/manager.c:870 +#, c-format +msgid "bongo-manager: could not create lock file in %s : %s\n" +msgstr "bongo-manager: não pude criar o arquivo de travamento em %s: %s\n" + +#: src/apps/manager/manager.c:878 +#, c-format +msgid "bongo-manager: failed to initialize memory manager. Exiting\n" +msgstr "bongo-manager: falhou em iniciar o gerenciador de memória. Saindo\n" + +#: src/apps/manager/manager.c:884 +#, c-format +msgid "bongo-manager: Couldn't read the server DN from bongo.conf.\n" +msgstr "bongo-manager: Não pude ler o DN do servido do bongo.conf.\n" + +#: src/apps/manager/manager.c:899 +#, c-format +msgid "bongo-manager: managed slapd process failed to start.\n" +msgstr "bongo-manager: processo do slapd gerenciado falhou em iniciar.\n" + +#: src/apps/manager/manager.c:903 +#, c-format +msgid "bongo-manager: -l only works with a managed-slapd database.\n" +msgstr "bongo-manager: -l só funciona com uma base de dados slapd-gerenciada.\n" + +#: src/apps/manager/manager.c:909 +#, c-format +msgid "bongo-manager: unable to intialize directory access.\n" +msgstr "bongo-manager: incapaz de iniciar o acesso ao diretório.\n" + +#: src/apps/manager/manager.c:915 +#, c-format +msgid "bongo-manager: unable to MsgInit()\n" +msgstr "bongo-manager: incapaz de MsgInit()\n" + +#: src/apps/manager/manager.c:922 +#, c-format +msgid "bongo-manager: unable to initialize messaging library.\n" +msgstr "bongo-manager: incapaz de iniciar a biblioteca de mensagens.\n" + +#: src/apps/manager/manager.c:937 +#, c-format +msgid "bongo-manager: Couldn't load configuration for agents\n" +msgstr "bongo-manager: Não pude ler configuração para os agentes\n" + +#: src/apps/manager/manager.c:962 +#, c-format +msgid "bongo-manager: Shutting down...\n" +msgstr "bongo-manager: Desligando...\n" + +#: src/apps/manager/manager.c:975 +#, c-format +msgid "' stubbornly refusing to die, insisting.\n" +msgstr "' teimosamente se recusa em morrer, insistindo.\n" + +#: src/apps/manager/manager.c:992 +#, c-format +msgid "bongo-manager: shutdown complete.\n" +msgstr "bongo-manager: Desligar concluído.\n" + diff --git a/src/agents/addressbook/Bongo.rules b/src/agents/addressbook/Bongo.rules deleted file mode 100644 index 2bca782..0000000 --- a/src/agents/addressbook/Bongo.rules +++ /dev/null @@ -1,28 +0,0 @@ -# -*- Makefile -*- -sbin_PROGRAMS += bongoaddressbook - -bongoaddressbook_SOURCES := \ - src/agents/addressbook/addressbook.c \ - src/agents/addressbook/addressbook.h \ - src/agents/addressbook/command.c - -bongoaddressbook_LDADD := \ - libbongonmap.la \ - libbongomanagement.la \ - libbongomsgapi.la \ - libbongomdb.la \ - libbongologger.la \ - libbongoconnio.la \ - libbongomemmgr.la \ - libbongoutil.la \ - libbongoxpl.la \ - libbongocal.la \ - libbongostreamio.la \ - $(top_builddir)/import/log4c/log4c/libbongolog4c.la \ - $(PTHREAD_LIBS) \ - $(ALL_LIBS) - -src/agents/addressbook/all: bongoaddressbook -src/agents/addressbook/clean: clean -src/agents/addressbook/install: - @cd $(top_builddir) && $(MAKE) $(MFLAGS) sbin_PROGRAMS=bongoaddressbook install-sbinPROGRAMS diff --git a/src/agents/addressbook/addressbook.c b/src/agents/addressbook/addressbook.c deleted file mode 100644 index 85dc629..0000000 --- a/src/agents/addressbook/addressbook.c +++ /dev/null @@ -1,333 +0,0 @@ -/**************************************************************************** - * * - * Copyright (c) 2005 Novell, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you - * may find current contact information at www.novell.com. - * - ****************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "addressbook.h" -#include "../store/messages.h" - -#define STACKSPACE (128 * 1024) - -#define MEMSTACKSIZE (4 * 1024) - -struct AddressbookGlobals AddressbookAgent; - -static void -AddressbookClientFree(void *clientp) -{ - AddressbookClient *client = clientp; - - MemPrivatePoolReturnEntry(client); -} - -static int -ProcessEntry(void *clientp, - Connection *conn) -{ - int ccode; - int count; - AddressbookClient *client; - - client = clientp; - client->conn = conn; - XplRWReadLockAcquire(&AddressbookAgent.configLock); { - for (count = 0; count < AddressbookAgent.trustedHosts.count; count++) { - if (client->conn->socketAddress.sin_addr.s_addr == - AddressbookAgent.trustedHosts.hosts[count]) - { - client->flags |= ADDRESSBOOK_CLIENT_FLAG_MANAGER; - break; - } - } - } XplRWReadLockRelease(&AddressbookAgent.configLock); - - if (!ConnNegotiate(client->conn, AddressbookAgent.server.ssl.context)) { - ccode = -1; - } else if (!IS_MANAGER(client)) { - /* issue nmap challenge */ - sprintf(client->authToken, "%x%s%x", - (unsigned int) XplGetThreadID(), - AddressbookAgent.server.host, - (unsigned int) time(NULL)); - ccode = ConnWriteF(client->conn, MSG4242AUTHREQUIRED, client->authToken); - } else { - ccode = ConnWriteF(client->conn, "1000 %s %s\r\n", - AddressbookAgent.server.host, MSG1000READY); - } - if (ccode != -1) { - ccode = ConnFlush(client->conn); - } - if (ccode != -1) { - ccode = AddressbookCommandLoop(client); - } - - /* Client connection will be freed by bongoagent's HandleConnection */ - - return 0; -} - - -static int -AddressbookSocketInit(void) -{ - MDBValueStruct *vs; - unsigned short port = 8672; - - vs = MDBCreateValueStruct(AddressbookAgent.handle.directory, AddressbookAgent.server.dn); - if (vs) { - if (MDBRead(AGENT_DN, MSGSRV_A_PORT, vs) > 0) { - port = atol(vs->Value[0]); - MDBFreeValues(vs); - } - MDBDestroyValueStruct(vs); - } - - AddressbookAgent.listenConn = ConnAlloc(FALSE); - if (!AddressbookAgent.listenConn) { - XplConsolePrintf(AGENT_NAME ": Could not allocate connection\n"); - return -1; - } - - AddressbookAgent.listenConn->socketAddress.sin_family = AF_INET; - AddressbookAgent.listenConn->socketAddress.sin_port = htons(port); - AddressbookAgent.listenConn->socketAddress.sin_addr.s_addr = MsgGetAgentBindIPAddress(); - - /* Get root privs back for the bind. It's ok if this fails - - * the user might not need to be root to bind to the port */ - XplSetEffectiveUserId(0); - - AddressbookAgent.listenConn->socket = ConnServerSocket(AddressbookAgent.listenConn, 2048); - - if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf(AGENT_NAME ": Could not drop to unprivileged user '%s'\n", - MsgGetUnprivilegedUser()); - return -1; - } - - if (AddressbookAgent.listenConn->socket == -1) { - int ret = AddressbookAgent.listenConn->socket; - XplConsolePrintf(AGENT_NAME ": Could not bind to port %d\n", port); - ConnFree(AddressbookAgent.listenConn); - return ret; - } - - return 0; -} - - -static void -AddressbookServer(void *ignored) -{ - XplRenameThread(XplGetThreadID(), AGENT_DN " Server"); - - /* Listen for incoming connections. Call ProcessEntry with a - * AddressbookAgentClient allocated for each incoming queue entry. */ - BongoAgentListenWithClientPool(&AddressbookAgent.agent, - AddressbookAgent.listenConn, - AddressbookAgent.threadPool, - sizeof(AddressbookClient), - AddressbookAgent.server.maxClients, - AddressbookClientFree, - ProcessEntry, - &AddressbookAgent.memPool); - - if (AddressbookAgent.listenConn) { - ConnClose(AddressbookAgent.listenConn, 1); - AddressbookAgent.listenConn = NULL; - } - - BongoThreadPoolShutdown(AddressbookAgent.threadPool); - CONN_TRACE_SHUTDOWN(); - BongoAgentShutdown(&AddressbookAgent.agent); -} - - -static BOOL -AddressbookAgentReadConfiguration(BOOL *recover) -{ - unsigned long used; - - BOOL result = TRUE; - MDBValueStruct *vs; - - tzset(); - - vs = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - if (vs && MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, vs)) { - gethostname(AddressbookAgent.server.host, sizeof(AddressbookAgent.server.host)); - - HashCredential(MsgGetServerDN(NULL), vs->Value[0], AddressbookAgent.server.hash); - - MDBFreeValues(vs); - } else { - return(FALSE); - } - - if (recover) { - if (MDBRead(AddressbookAgent.server.dn, MSGSRV_A_SERVER_STATUS, vs) > 0) { - if (XplStrCaseCmp(vs->Value[0], "Shutdown") != 0) { - *recover = TRUE; - } - } - - MDBFreeValues(vs); - } - - MDBSetValueStructContext(AddressbookAgent.server.dn, vs); - - /* trusted hosts */ - AddressbookAgent.trustedHosts.count = - MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_STORE_TRUSTED_HOSTS, vs); - - AddressbookAgent.trustedHosts.hosts = MemRealloc(AddressbookAgent.trustedHosts.hosts, - AddressbookAgent.trustedHosts.count + 2); - if (!AddressbookAgent.trustedHosts.hosts) { - AddressbookAgent.trustedHosts.count = 0; - } - if (AddressbookAgent.trustedHosts.count) { - int count = 0; - -#if defined(NETWARE) || defined(LIBC) - AddressbookAgent.trustedHosts.hosts[count++] = inet_addr("127.0.0.1"); - AddressbookAgent.trustedHosts.hosts[count++] = MsgGetHostIPAddress(); -#endif - for (used = 0; used < vs->Used; used++) { - AddressbookAgent.trustedHosts.hosts[count++] = inet_addr(vs->Value[used]); - } - } - MDBFreeValues(vs); - /* end trusted hosts */ - - - /** hacks **/ - - AddressbookAgent.server.maxClients = 1024; - - /** end hacks **/ - - - MDBDestroyValueStruct(vs); - - return(result); -} - - -static void -SignalHandler(int sigtype) -{ - BongoAgentHandleSignal(&AddressbookAgent.agent, sigtype); -} - -XplServiceCode(SignalHandler) - - -int -XplServiceMain(int argc, char *argv[]) -{ - int ccode; - int minThreads; - int maxThreads; - int minSleep; - int startupOpts = 0; -#ifdef WIN32 - XplThreadID id; -#endif - if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf(AGENT_NAME ": Could not drop to unprivileged user '%s'\n", - MsgGetUnprivilegedUser()); - return -1; - } - XplInit(); - - /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO; - ccode = BongoAgentInit(&AddressbookAgent.agent, AGENT_NAME, AGENT_DN, (30 * 60), startupOpts); - if (ccode == -1) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); - return -1; - } - - if (!BongoCalInit(MsgGetDBFDir(NULL))) { - XplConsolePrintf(AGENT_NAME ": Couldn't initialize calendaring library. Exiting.\r\n"); - return -1; - } - - MsgGetServerDN(AddressbookAgent.server.dn); - MsgGetConfigProperty(AddressbookAgent.defaultContext, MSGSRV_CONFIG_PROP_DEFAULT_CONTEXT); - - /* Create and bind the server connection */ - if (AddressbookSocketInit() < 0) { - XplConsolePrintf(AGENT_NAME ": Exiting.\n"); - return -1; - } - - /* Drop privs */ - if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf(AGENT_NAME ": Could not drop to unprivileged user '%s'\r\n" - AGENT_NAME ": exiting.\n", - MsgGetUnprivilegedUser()); - return -1; - } - - /* Create a thread pool for managing connections */ - - BongoQueueAgentGetThreadPoolParameters (&AddressbookAgent.agent, &minThreads, - &maxThreads, &minSleep); - - AddressbookAgent.threadPool = BongoThreadPoolNew(AGENT_DN " Clients", - STACKSPACE, - minThreads, maxThreads, minSleep); - - if (!AddressbookAgent.threadPool) { - BongoAgentShutdown(&AddressbookAgent.agent); - XplConsolePrintf(AGENT_NAME ": Unable to create thread pool.\r\n" - AGENT_NAME ": Exiting.\r\n"); - return -1; - } - - AddressbookAgentReadConfiguration(NULL); - - /* setup the guts: */ - if (AddressbookSetupCommands()) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); - return -1; - } - - XplSignalHandler(SignalHandler); - - /* Start the server thread */ - XplStartMainThread(AGENT_NAME, &id, AddressbookServer, 8192, NULL, ccode); - - XplUnloadApp(XplGetThreadID()); - - return 0; -} diff --git a/src/agents/addressbook/addressbook.h b/src/agents/addressbook/addressbook.h deleted file mode 100644 index 1529a76..0000000 --- a/src/agents/addressbook/addressbook.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2005, 2006 Novell, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you - * may find current contact information at www.novell.com. - * - ****************************************************************************/ - -#ifndef _ADDRESSBOOK_H -#define _ADDRESSBOOK_H - -#include - -XPL_BEGIN_C_LINKAGE - -#include -#include -#include -#include -#include -#include -#include -#include - -#define AGENT_NAME "bongoaddressbook" -#define AGENT_DN "Addressbook Agent" - -enum { - ADDRESSBOOK_CLIENT_FLAG_MANAGER = (1 << 0) -}; - -#define IS_MANAGER(client) (((client)->flags & ADDRESSBOOK_CLIENT_FLAG_MANAGER) == ADDRESSBOOK_CLIENT_FLAG_MANAGER) - -typedef struct _AddressbookClient AddressbookClient; - -struct _AddressbookClient { - Connection *conn; - - int flags; - - char authToken[64]; - - char user[64]; - char dn[MDB_MAX_OBJECT_CHARS + 1]; - - char parentObject[MDB_MAX_OBJECT_CHARS + 1]; - - char buffer[CONN_BUFSIZE + 1]; -}; - - -struct AddressbookGlobals { - BongoAgent agent; - - Connection *listenConn; /* this is the conn we're listening on */ - - void *memPool; - BongoThreadPool *threadPool; - - char defaultContext[MDB_MAX_OBJECT_CHARS + 1]; - - struct { - MDBHandle directory; - - void *logging; - } handle; - - XplRWLock configLock; - - struct { - struct { - BOOL enable; - ConnSSLConfiguration config; - bongo_ssl_context *context; - Connection *conn; - } ssl; - - BOOL bound; - - Connection *conn; /* NMAPServerSocket */ - - XplAtomic active; - - int maxClients; - unsigned long ipAddress; - unsigned long bytesPerBlock; - - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - unsigned char host[MAXEMAILNAMESIZE + 1]; - unsigned char hash[NMAP_HASH_SIZE]; - } server; - - struct { - int count; - unsigned long *hosts; - } trustedHosts; -}; - - -typedef enum { - ADDRESSBOOK_COMMAND_NULL = 0, - - ADDRESSBOOK_COMMAND_AUTH, /* COOKIE, USER or SYSTEM */ - - ADDRESSBOOK_COMMAND_SEARCH, - - ADDRESSBOOK_COMMAND_QUIT, -} AddressbookCommand; - -extern struct AddressbookGlobals AddressbookAgent; - - -int AddressbookSetupCommands(void); -CCode AddressbookCommandLoop(AddressbookClient *client); - -XPL_END_C_LINKAGE - - -#endif /* _ADDRESSBOOK_H */ diff --git a/src/agents/addressbook/command.c b/src/agents/addressbook/command.c deleted file mode 100644 index 6bb98e5..0000000 --- a/src/agents/addressbook/command.c +++ /dev/null @@ -1,526 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2005, 2006 Novell, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you - * may find current contact information at www.novell.com. - * - ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "addressbook.h" - -#include "../store/messages.h" - -#define MAX_PROPS 25 - -static uint32_t -CommandHash (const void *key) -{ - char *s = (char *) key; - uint32_t b = 1; - uint32_t h = 0; - - for (; *s && ' ' != *s; s++) { - h += b * tolower(*s); - b = (b << 5) - b; - } - return h; -} - -/* a strcmp() that ends on first space. (might be optimizable by word-compares) */ - -static int -CommandCmp(const void *cmda, const void *cmdb) -{ - char *a = (char *) cmda; - char *b = (char *) cmdb; - - while (*a) { - if (tolower(*a) != tolower(*b)) { - if (!*b && ' ' == *a) { - return 0; - } else { - return -1; - } - } - a++; - b++; - } - return 0; -} - - -static BongoHashtable *CommandTable; - - -/* returns 0 on success */ - -/* I probably should have used ProtocolCommandTree? The hashtable came - * about when I tried to do this with with lex yacc code */ - -int -AddressbookSetupCommands(void) -{ - CommandTable = BongoHashtableCreate(64, CommandHash, CommandCmp); - - if (!CommandTable || - - /* session commands */ - BongoHashtablePutNoReplace(CommandTable, "AUTH", (void *) ADDRESSBOOK_COMMAND_AUTH) || - BongoHashtablePutNoReplace(CommandTable, "QUIT", (void *) ADDRESSBOOK_COMMAND_QUIT) || - BongoHashtablePutNoReplace(CommandTable, "SEARCH", (void *) ADDRESSBOOK_COMMAND_SEARCH) || - 0) - { - XplConsolePrintf(AGENT_NAME ": Couldn't setup command table.\r\n"); - if (CommandTable) { - BongoHashtableDelete(CommandTable); - CommandTable = NULL; - } - return -1; - } - return 0; -} - - -#define TOKEN_OK 0xffff /* magic */ - -__inline static CCode -CheckTokC(AddressbookClient *client, int n, int min, int max) -{ - if (n < min || n > max) { - return ConnWriteStr(client->conn, MSG3010BADARGC); - } - - return TOKEN_OK; -} - -static CCode -ParseInt(AddressbookClient *client, char *token, int *out) -{ - long t; - char *endp; - - t = strtol(token, &endp, 10); - if (*endp) { - return ConnWriteStr(client->conn, MSG3017BADINTARG); - } - *out = t; - return TOKEN_OK; -} - -static int -ParseRange(AddressbookClient *client, char *token, int *startOut, int *endOut) -{ - long t; - char *endp; - - if (!strcmp(token, "all")) { - *startOut = *endOut = -1; - return TOKEN_OK; - } - - t = strtol(token, &endp, 10); - if (endp == token || *endp != '-' || t < 0) { - return ConnWriteStr(client->conn, MSG3020BADRANGEARG); - } - *startOut = t; - - t = strtol(endp + 1, &endp, 10); - if (*endp /* || t < *startOut */) { - return ConnWriteStr(client->conn, MSG3020BADRANGEARG); - } - *endOut = t; - - return TOKEN_OK; -} - -static CCode -RequireUser(AddressbookClient *client) -{ - return (IS_MANAGER(client) || client->user[0]) - ? TOKEN_OK - : ConnWriteStr(client->conn, MSG3241NOUSER); - - return TOKEN_OK; -} - -#define TOK_ARR_SZ 10 -#define PROP_ARR_SZ 10 -#define HDR_ARR_SZ 10 - -static BOOL -ReadParentObject(const char *dn, char *parentDn, MDBValueStruct *vs) -{ - char configDn[MDB_MAX_OBJECT_CHARS + 1]; - - if (MsgGetUserSettingsDN(dn, configDn, vs, FALSE)) { - if (MDBRead(configDn, MSGSRV_A_PARENT_OBJECT, vs)) { - BongoStrNCpy(parentDn, vs->Value[vs->Used - 1], MDB_MAX_OBJECT_CHARS + 1); - MDBFreeValues(vs); - return TRUE; - } - } - parentDn[0] = '\0'; - return FALSE; -} - -static void -UnselectUser(AddressbookClient *client) -{ - client->user[0] = '\0'; - client->dn[0] = '\0'; -} - -static CCode -SelectUser(AddressbookClient *client, char *user, char *password) -{ - MDBValueStruct *vs; - int ret = -1; - - vs = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - if (!vs) { - return ConnWriteStr(client->conn, MSG5001NOMEMORY); - } - - if (!MsgFindObject(user, client->dn, NULL, NULL, vs)) { - XplConsolePrintf("Couldn't find user object for %s\r\n", user); - if (IS_MANAGER(client)) { - ret = ConnWriteStr(client->conn, MSG4224NOUSER); - } else { - ret = ConnWriteStr(client->conn, MSG3242BADAUTH); - XplDelay(2000); - } - goto finish; - } - - ReadParentObject(client->dn, client->parentObject, vs); - - if (password && !MDBVerifyPassword(client->dn, password, vs)) { - ret = ConnWriteStr(client->conn, MSG3242BADAUTH); - XplDelay(2000); - goto finish; - } - - UnselectUser(client); - - BongoStrNCpy(client->user, user, sizeof(client->user)); - - ret = ConnWriteStr(client->conn, MSG1000OK); - -finish: - MDBDestroyValueStruct(vs); - return ret; -} - -static CCode -AddressbookCommandAUTHCOOKIE(AddressbookClient *client, char *user, char *token) -{ - Connection *conn; - CCode ccode; - char dn[MDB_MAX_OBJECT_CHARS + 1]; - char buffer[CONN_BUFSIZE]; - struct sockaddr_in serv; - - if (!MsgFindObject(user, dn, NULL, &serv, NULL)) { - ccode = ConnWriteStr(client->conn, MSG3242BADAUTH); - return -1; - } - - conn = NMAPConnect(NULL, &serv); - if (!conn) { - return ConnWriteStr(client->conn, MSG3242BADAUTH); - } - - ccode = NMAPAuthenticateWithCookie(conn, user, token, buffer, sizeof(buffer)); - switch (ccode) { - case 1000: - ccode = SelectUser(client, user, NULL); - break; - case -1: - break; - default: - if (ccode >= 1000 && ccode < 6000) { - ccode = ConnWriteF(client->conn, "%d %s\r\n", ccode, buffer); - } else { - XplConsolePrintf("Unexpected response from remote store: %s\r\n", - buffer); - ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); - } - break; - } - - NMAPQuit(conn); - ConnFree(conn); - - return ConnWriteStr(client->conn, "5000 Not Implemented"); -} - -static CCode -AddressbookCommandUSER(AddressbookClient *client, char *user, char *password) -{ - if (user) { - return SelectUser(client, user, password); - } else { - UnselectUser(client); - return ConnWriteStr(client->conn, MSG1000OK); - } -} - -static MDBValueStruct * -GetUserTypes(AddressbookClient *client) -{ - MDBValueStruct *types = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - - MDBAddValue(C_USER, types); - MDBAddValue(C_ORGANIZATIONAL_UNIT, types); - - return types; -} - -static MDBValueStruct * -GetSearchAttributes(AddressbookClient *client) -{ - MDBValueStruct *attributes = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - - MDBAddValue("cn", attributes); - MDBAddValue("ou", attributes); - MDBAddValue(A_FULL_NAME, attributes); - MDBAddValue(A_GIVEN_NAME, attributes); - MDBAddValue(A_SURNAME, attributes); - MDBAddValue(A_INTERNET_EMAIL_ADDRESS, attributes); - - return attributes; -} - -static CCode -WriteContactProperty(AddressbookClient *client, - const char *dn, - const char *prop, - MDBValueStruct *vs) -{ - CCode ccode = 1; - if (MDBRead(dn, prop, vs)) { - if (vs->Used > 0) { - char *value = vs->Value[vs->Used - 1]; - ccode = ConnWriteF(client->conn, "2001 \"%s\" %d\r\n%s\r\n", - prop, (int)strlen(value), value); - MDBFreeValues(vs); - if (ccode != -1) { - ccode = 0; - } - } - } - - return ccode; -} - -static CCode -WriteContact(AddressbookClient *client, const char *dn, char **props, int numProps, MDBValueStruct *vs) -{ - char buf[MDB_MAX_OBJECT_CHARS + 1]; - char *email; - int i; - - if (ConnWriteF(client->conn, "2000 %s\r\n", dn) == -1) { - return -1; - } - - for (i = 0; i < numProps; i++) { - char *prop = props[i]; - - if (!strcmp(prop, A_EMAIL_ADDRESS)) { - email = (char*)MsgGetUserEmailAddress(dn, vs, (unsigned char*)buf, sizeof(buf)); - if (email) { - if (ConnWriteF(client->conn, "2001 \"" A_EMAIL_ADDRESS "\" %d\r\n%s\r\n", (int)strlen(email), email) == -1) { - - return -1; - } - } - } else { - if (!WriteContactProperty(client, dn, prop, vs)) { - return -1; - } - } - } - - return 0; -} - -static CCode -AddressbookCommandSEARCH(AddressbookClient *client, const char *pattern, char **props, int numProps, int start, int end) -{ - CCode ccode; - MDBValueStruct *types; - MDBValueStruct *attributes; - MDBValueStruct *users; - MDBValueStruct *vs; - - types = GetUserTypes(client); - attributes = GetSearchAttributes(client); - users = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - - vs = MDBCreateValueStruct(AddressbookAgent.handle.directory, NULL); - - MDBFreeValues(vs); - - /* FIXME: is this the right context to search? */ - if (MDBFindObjects(AddressbookAgent.defaultContext, - types, - pattern, - attributes, - MDB_SCOPE_INFINITE, - 500, - users)) { - unsigned int i; - int num = 0; - for (i = 0; i < users->Used; i++) { - char *dn; - char theirParentObject[MDB_MAX_OBJECT_CHARS]; - - dn = users->Value[i]; - ReadParentObject(dn, theirParentObject, vs); - if (!strcmp(client->parentObject, theirParentObject)) { - if (num >= start) { - WriteContact(client, dn, props, numProps, vs); - } - num++; - if (end != -1 && num >= end) { - break; - } - } - } - ccode = ConnWriteStr(client->conn, MSG1000OK); - } else { - ccode = ConnWriteStr(client->conn, MSG1000OK); - } - - MDBDestroyValueStruct(vs); - MDBDestroyValueStruct(types); - MDBDestroyValueStruct(attributes); - MDBDestroyValueStruct(users); - - return ccode; -} - -static CCode -AddressbookCommandQUIT(AddressbookClient *client) -{ - if (-1 != ConnWriteStr(client->conn, MSG1000BYE)) { - ConnFlush(client->conn); - } - - return -1; -} - -CCode -AddressbookCommandLoop(AddressbookClient *client) -{ - int ccode = 0; - AddressbookCommand command; - - while (-1 != ccode && BONGO_AGENT_STATE_RUNNING == AddressbookAgent.agent.state) { - char *tokens[TOK_ARR_SZ]; - int n; - int numProps = 0; - char *props[MAX_PROPS]; - int start, end; - int i; - - start = end = -1; - - ccode = ConnReadAnswer(client->conn, client->buffer, CONN_BUFSIZE); - if (-1 == ccode || ccode >= CONN_BUFSIZE) { - break; - } - - memset(tokens, 0, sizeof(tokens)); - n = CommandSplit(client->buffer, tokens, TOK_ARR_SZ); - if (0 == n) { - command = ADDRESSBOOK_COMMAND_NULL; - } else { - command = (AddressbookCommand) BongoHashtableGet(CommandTable, tokens[0]); - } - - switch (command) { - case ADDRESSBOOK_COMMAND_NULL: - ccode = ConnWriteStr(client->conn, MSG3000UNKNOWN); - break; - - case ADDRESSBOOK_COMMAND_AUTH: - /* AUTH COOKIE */ - /* AUTH SYSTEM */ - /* AUTH USER */ - - if (TOKEN_OK != (ccode = CheckTokC(client, n, 3, 4))) { - break; - } - if (!XplStrCaseCmp(tokens[1], "COOKIE")) { - if (TOKEN_OK == (ccode = CheckTokC(client, n, 4, 4))) { - ccode = AddressbookCommandAUTHCOOKIE(client, tokens[2], tokens[3]); - } - } else if (0 == XplStrCaseCmp(tokens[1], "USER")) { - if (TOKEN_OK == (ccode = CheckTokC(client, n, 4, 4))) { - ccode = AddressbookCommandUSER(client, tokens[2], tokens[3]); - } - } else { - ccode = ConnWriteStr(client->conn, MSG3000UNKNOWN); - } - break; - case ADDRESSBOOK_COMMAND_SEARCH: - /* SEARCH pattern */ - if (TOKEN_OK != (ccode = RequireUser(client)) || - TOKEN_OK != (ccode = CheckTokC(client, n, 2, 3))) { - break; - } - - for (i = 2; i < n; i++) { - if ('R' == *tokens[i] && start == -1) { - ccode = ParseRange(client, tokens[i] + 1, &start, &end); - } else if ('P' == *tokens[i] && numProps == 0) { - numProps = BongoStringSplit(tokens[i] + 1, ',', props, MAX_PROPS); - } else { - ccode = ConnWriteStr(client->conn, MSG3022BADSYNTAX); - } - } - - ccode = AddressbookCommandSEARCH(client, tokens[1], props, numProps, start, end); - - break; - case ADDRESSBOOK_COMMAND_QUIT: - /* QUIT */ - - ccode = AddressbookCommandQUIT(client); - break; - - default: - break; - } - - if (ccode >= 0) { - ccode = ConnFlush(client->conn); - } - } - - return ccode; -} - diff --git a/src/agents/alarm/Bongo.rules b/src/agents/alarm/Bongo.rules index 3fce4bc..d8f38ef 100644 --- a/src/agents/alarm/Bongo.rules +++ b/src/agents/alarm/Bongo.rules @@ -1,16 +1,14 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoalarm -bongoalarm_SOURCES := \ +bongoalarm_SOURCES = \ src/agents/alarm/alarm.c \ src/agents/alarm/alarm.h -bongoalarm_LDADD := \ +bongoalarm_LDADD = \ libbongonmap.la \ libbongocal.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/alarm/alarm.c b/src/agents/alarm/alarm.c index 238bb37..12e8a55 100644 --- a/src/agents/alarm/alarm.c +++ b/src/agents/alarm/alarm.c @@ -30,11 +30,12 @@ #include #include #include +#include #include "alarm.h" #define TOK_ARR_SZ 10 -AlarmGlobals Alarm = {{0,}, 0, }; +AlarmGlobals Alarm; static void AlarmDestroy(AlarmInfo *alarm) @@ -84,7 +85,7 @@ ConnectToQueue(QueueClient *client, char *address) return -1; } - if (!NMAPAuthenticate(client->conn, buffer, sizeof(buffer))) { + if (!NMAPAuthenticateToQueue(client->conn, buffer, sizeof(buffer))) { NMAPQuit(client->conn); printf(AGENT_NAME ": authentication failed when connecting to queue %s.\r\n", address); @@ -147,7 +148,8 @@ GetAlarms(StoreClient *client, uint64_t start, uint64_t end) alarm = MemMalloc(sizeof(AlarmInfo)); memset(alarm, 0, sizeof(AlarmInfo)); - if (1 != sscanf(client->buffer, "%*llx %lld", &alarm->when)) { + // FIXME: sscanf == bad + if (1 != sscanf(client->buffer, "%*x %lld", &alarm->when)) { printf (AGENT_NAME ": couldn't parse store response '%s'.\n", client->buffer); return -1; @@ -240,8 +242,7 @@ SendAlarmEmail(QueueClient *qclient, AlarmInfo *alarm) static void AlarmLoop(void *ignored) { - //MDBValueStruct *vs; - int i; + unsigned int i; uint64_t start; uint64_t end; uint64_t now; @@ -374,8 +375,10 @@ XplServiceMain(int argc, char *argv[]) } XplInit(); + memset(&Alarm, 0, sizeof(AlarmGlobals)); + /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO; + startupOpts = BA_STARTUP_CONNIO; ccode = BongoAgentInit(&Alarm.agent, AGENT_NAME, AGENT_DN, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); diff --git a/src/agents/alarm/alarm.h b/src/agents/alarm/alarm.h index b24b40c..b4bd999 100644 --- a/src/agents/alarm/alarm.h +++ b/src/agents/alarm/alarm.h @@ -23,7 +23,6 @@ #define _ALARM_H #include -#include #include #include #include @@ -76,8 +75,4 @@ typedef enum { ALARM_COMMAND_NOOP, } AlarmCommand; -/* management.c */ -int AlarmManagementStart(void); -void AlarmManagementShutdown(void); - #endif /* _ALARM_H */ diff --git a/src/agents/antispam/Bongo.rules b/src/agents/antispam/Bongo.rules index 7c6dcef..1d2d735 100644 --- a/src/agents/antispam/Bongo.rules +++ b/src/agents/antispam/Bongo.rules @@ -1,15 +1,14 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoantispam -bongoantispam_SOURCES := \ +bongoantispam_SOURCES = \ src/agents/antispam/antispam.c \ src/agents/antispam/antispam.h \ src/agents/antispam/spamd.c -bongoantispam_LDADD := \ +bongoantispam_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/antispam/antispam.c b/src/agents/antispam/antispam.c index 250761f..006c9b1 100644 --- a/src/agents/antispam/antispam.c +++ b/src/agents/antispam/antispam.c @@ -27,10 +27,9 @@ #include #include -#include + #include #include -#include #include #include #include @@ -47,38 +46,6 @@ static void SignalHandler(int sigtype); -#define QUEUE_WORK_TO_DO(c, id, r) \ - { \ - XplWaitOnLocalSemaphore(ASpam.nmap.semaphore); \ - if (XplSafeRead(ASpam.nmap.worker.idle)) { \ - (c)->queue.previous = NULL; \ - if (((c)->queue.next = ASpam.nmap.worker.head) != NULL) { \ - (c)->queue.next->queue.previous = (c); \ - } else { \ - ASpam.nmap.worker.tail = (c); \ - } \ - ASpam.nmap.worker.head = (c); \ - (r) = 0; \ - } else { \ - XplSafeIncrement(ASpam.nmap.worker.active); \ - XplSignalBlock(); \ - XplBeginThread(&(id), HandleConnection, 24 * 1024, XPL_UINT_TO_PTR(XplSafeRead(ASpam.nmap.worker.active)), (r)); \ - XplSignalHandler(SignalHandler); \ - if (!(r)) { \ - (c)->queue.previous = NULL; \ - if (((c)->queue.next = ASpam.nmap.worker.head) != NULL) { \ - (c)->queue.next->queue.previous = (c); \ - } else { \ - ASpam.nmap.worker.tail = (c); \ - } \ - ASpam.nmap.worker.head = (c); \ - } else { \ - XplSafeDecrement(ASpam.nmap.worker.active); \ - (r) = -1; \ - } \ - } \ - XplSignalLocalSemaphore(ASpam.nmap.semaphore); \ - } ASpamGlobals ASpam; @@ -128,6 +95,8 @@ FreeClientData(ASpamClient *client) return; } +#if 0 +// FIXME: Deprecated? CmpAddr() and MatchAddr() are unused. static int CmpAddr(const void *c, const void *d) { @@ -215,40 +184,7 @@ MatchAddr(unsigned char *candidate, unsigned char *domain) return(0); } - -/** Searches for the passed ip address in the disallowed list. - */ -static unsigned char -*IsSpammer(unsigned char *from) -{ - int cmp; - int start; - int end; - int middle = 0; - BOOL matched = FALSE; - - start = 0; - end = ASpam.disallow.used - 1; - - while ((end >= start) && !matched) { - middle = (end - start) / 2 + start; - cmp = MatchAddr(from, ASpam.disallow.list->Value[middle]); - if (cmp == 0) { - matched = TRUE; - } else if (cmp < 0) { - end = middle - 1; - } else { - start = middle + 1; - } - } - - if(matched) { - return(ASpam.disallow.list->Value[middle]); - } - - return(NULL); -} - +#endif /** Callback function. Whenever a new message arrives in the queue that * this agent has registered itself on, NMAP calls back to this function @@ -268,7 +204,6 @@ ProcessConnection(ASpamClient *client) char *ptr2; unsigned char *cur; unsigned char *line; - unsigned char *blockedAddr = NULL; char *senderUserName = NULL; unsigned char qID[16]; BOOL copy; @@ -384,7 +319,8 @@ ProcessConnection(ASpamClient *client) } } - if (ASpam.allow.used || ASpam.disallow.used) { + //if (ASpam.allow.used || ASpam.disallow.used) + { unsigned char *tmpNull = NULL; unsigned char tmpChar; while (*cur) { @@ -411,10 +347,14 @@ ProcessConnection(ASpamClient *client) switch (cur[0]) { case QUEUE_FLAGS: { copy = FALSE; - ccode = NMAPSendCommandF(client->conn, "QMOD RAW "QUEUES_FLAGS"%ld\r\n", (msgFlags | MSG_FLAG_SPAM_CHECKED)); + /* this is handled by the QCREA done in spamd.c */ + /* ccode = NMAPSendCommandF(client->conn, "QMOD RAW "QUEUES_FLAGS"%ld\r\n", (msgFlags | MSG_FLAG_SPAM_CHECKED)); */ break; } case QUEUE_FROM: { + // code below used to check IPs for being spammy. Shouldn't + // be doing this in here IMHO - alex. +#if 0 ptr = strchr(cur + 1, ' '); if (ptr) { *ptr = '\0'; @@ -430,7 +370,7 @@ ProcessConnection(ASpamClient *client) *ptr = ' '; } } - +#endif break; } @@ -449,10 +389,12 @@ ProcessConnection(ASpamClient *client) break; } } - + /* this is handled by the QCREA in spamd.c */ + /* if (copy && (ccode != -1)) { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); } + */ cur = line; if (tmpNull) { /* Restore the local copy of the envelope. */ @@ -492,7 +434,7 @@ HandleConnection(void *param) ASpamClient *client; if ((client = ASpamClientAlloc()) == NULL) { - XplConsolePrintf("bongoantispam: New worker failed to startup; out of memory.\r\n"); + Log(LOG_ERROR, "New worker failed to start up; out of memory."); NMAPSendCommand(client->conn, "QDONE\r\n", 7); @@ -581,7 +523,35 @@ AntiSpamServer(void *ignored) if (ASpam.state < ASPAM_STATE_STOPPING) { conn->ssl.enable = FALSE; - QUEUE_WORK_TO_DO(conn, id, ccode); + XplWaitOnLocalSemaphore(ASpam.nmap.semaphore); + if (XplSafeRead(ASpam.nmap.worker.idle)) { + conn->queue.previous = NULL; + if ((conn->queue.next = ASpam.nmap.worker.head) != NULL) { + conn->queue.next->queue.previous = conn; + } else { + ASpam.nmap.worker.tail = conn; + } + ASpam.nmap.worker.head = conn; + ccode = 0; + } else { + XplSafeIncrement(ASpam.nmap.worker.active); + XplSignalBlock(); + XplBeginThread(&id, HandleConnection, 24 * 1024, XPL_UINT_TO_PTR(XplSafeRead(ASpam.nmap.worker.active)), ccode); + XplSignalHandler(SignalHandler); + if (!ccode) { + conn->queue.previous = NULL; + if ((conn->queue.next = ASpam.nmap.worker.head) != NULL) { + conn->queue.next->queue.previous = conn; + } else { + ASpam.nmap.worker.tail = conn; + } + ASpam.nmap.worker.head = conn; + } else { + XplSafeDecrement(ASpam.nmap.worker.active); + ccode = -1; + } + } + XplSignalLocalSemaphore(ASpam.nmap.semaphore); if (!ccode) { XplSignalLocalSemaphore(ASpam.nmap.worker.todo); @@ -613,7 +583,7 @@ AntiSpamServer(void *ignored) default: { if (ASpam.state < ASPAM_STATE_STOPPING) { - XplConsolePrintf("bongoantispam: Exiting after an accept() failure; error %d\r\n", errno); + Log(LOG_ERROR, "Exiting after an accept() failure; error %d", errno); LoggerEvent(ASpam.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); @@ -630,9 +600,7 @@ AntiSpamServer(void *ignored) /* Shutting down */ ASpam.state = ASPAM_STATE_UNLOADING; -#if VERBOSE - XplConsolePrintf("bongoantispam: Shutting down.\r\n"); -#endif + Log(LOG_DEBUG, "Shutting down"); id = XplSetThreadGroupID(ASpam.id.group); @@ -661,9 +629,7 @@ AntiSpamServer(void *ignored) XplDelay(1000); } -#if VERBOSE - XplConsolePrintf("bongoantispam: Shutting down %d queue threads\r\n", XplSafeRead(ASpam.nmap.worker.active)); -#endif + Log(LOG_DEBUG, "Shutting down %d queue threads", XplSafeRead(ASpam.nmap.worker.active)); XplWaitOnLocalSemaphore(ASpam.nmap.semaphore); @@ -679,11 +645,11 @@ AntiSpamServer(void *ignored) } if (XplSafeRead(ASpam.server.active) > 1) { - XplConsolePrintf("bongoantispam: %d server threads outstanding; attempting forceful unload.\r\n", XplSafeRead(ASpam.server.active) - 1); + Log(LOG_INFO, "%d server threads outstanding; attempting forceful unload.", XplSafeRead(ASpam.server.active)-1); } if (XplSafeRead(ASpam.nmap.worker.active)) { - XplConsolePrintf("bongoantispam: %d threads outstanding; attempting forceful unload.\r\n", XplSafeRead(ASpam.nmap.worker.active)); + Log(LOG_INFO, "%d threads outstanding; attempting forceful unload.", XplSafeRead(ASpam.nmap.worker.active)); } SpamdShutdown(&(ASpam.spamd)); @@ -695,18 +661,6 @@ AntiSpamServer(void *ignored) XplCloseLocalSemaphore(ASpam.nmap.worker.todo); XplCloseLocalSemaphore(ASpam.nmap.semaphore); - if (ASpam.allow.list) { - MDBDestroyValueStruct(ASpam.allow.list); - ASpam.allow.list = NULL; - ASpam.allow.used = 0; - } - - if (ASpam.disallow.list) { - MDBDestroyValueStruct(ASpam.disallow.list); - ASpam.disallow.list = NULL; - ASpam.disallow.used = 0; - } - MsgShutdown(); CONN_TRACE_SHUTDOWN(); @@ -716,9 +670,7 @@ AntiSpamServer(void *ignored) MemoryManagerClose(MSGSRV_AGENT_ANTISPAM); -#if VERBOSE - XplConsolePrintf("bongoantispam: Shutdown complete\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown complete."); XplSignalLocalSemaphore(ASpam.sem.main); XplWaitOnLocalSemaphore(ASpam.sem.shutdown); @@ -749,51 +701,10 @@ ReadConfiguration(void) { SpamdReadConfiguration(&ASpam.spamd, node); -#if 0 - ASpam.allow.list = MDBCreateValueStruct(ASpam.handle.directory, MsgGetServerDN(NULL)); - ASpam.disallow.list = MDBCreateValueStruct(ASpam.handle.directory, MsgGetServerDN(NULL)); - config = MDBCreateValueStruct(ASpam.handle.directory, MsgGetServerDN(NULL)); - if (ASpam.allow.list && ASpam.disallow.list && config) { - ASpam.allow.used = 0; - ASpam.disallow.used = 0; - } else { - if (config) { - MDBDestroyValueStruct(config); - } - - retcode = FALSE; - goto finish; - } -#endif - retcode = TRUE; finish: BongoJsonNodeFree(node); return retcode; -#if 0 - unsigned char *ptr; - - /* Find out which queue to register with. Otherwise remain Q_INCOMING */ - if (MDBRead(MSGSRV_AGENT_ANTISPAM, MSGSRV_A_REGISTER_QUEUE, config) > 0) { - ASpam.nmap.queue = atol(config->Value[0]); - } - MDBFreeValues(config); - - if ((ASpam.disallow.used = MDBRead(MSGSRV_AGENT_ANTISPAM, MSGSRV_A_EMAIL_ADDRESS, ASpam.disallow.list)) > 0) { - qsort(ASpam.disallow.list->Value, ASpam.disallow.used, sizeof(unsigned char*), CmpAddr); - - MDBFreeValues(config); - } - - MDBSetValueStructContext(NULL, config); - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, config)>0) { - HashCredential(MsgGetServerDN(NULL), config->Value[0], ASpam.nmap.hash); - } - - MDBDestroyValueStruct(config); - - return(TRUE); -#endif } #if defined(NETWARE) || defined(LIBC) || defined(WIN32) @@ -867,27 +778,27 @@ QueueSocketInit(void) ASpam.nmap.conn->socket = ConnServerSocket(ASpam.nmap.conn, 2048); if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongoantispam: Could not drop to unprivileged user '%s'\r\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); ConnFree(ASpam.nmap.conn); ASpam.nmap.conn = NULL; return(-1); } if (ASpam.nmap.conn->socket == -1) { - XplConsolePrintf("bongoantispam: Could not bind to dynamic port\r\n"); + Log(LOG_ERROR, "Could not bind to dynamic port."); ConnFree(ASpam.nmap.conn); ASpam.nmap.conn = NULL; return(-1); } - if (NMAPRegister(MSGSRV_AGENT_ANTISPAM, ASpam.nmap.queue, ASpam.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { - XplConsolePrintf("bongoantispam: Could not register with bongonmap\r\n"); + if (QueueRegister(MSGSRV_AGENT_ANTISPAM, ASpam.nmap.queue, ASpam.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { + Log(LOG_ERROR, "Could not register with bongoqueue"); ConnFree(ASpam.nmap.conn); ASpam.nmap.conn = NULL; return(-1); } } else { - XplConsolePrintf("bongoantispam: Could not allocate connection.\r\n"); + Log(LOG_ERROR, "Could not allocate connection."); return(-1); } @@ -902,7 +813,7 @@ XplServiceMain(int argc, char *argv[]) int ccode; if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongoantispam: Could not drop to unprivileged user '%s', exiting.\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); return(1); } XplInit(); @@ -924,7 +835,6 @@ XplServiceMain(int argc, char *argv[]) ASpam.nmap.ssl.context = NULL; ASpam.nmap.ssl.config.options = 0; - ASpam.handle.directory = NULL; ASpam.handle.logging = NULL; strcpy(ASpam.nmap.address, "127.0.0.1"); @@ -945,36 +855,25 @@ XplServiceMain(int argc, char *argv[]) } else { MemoryManagerClose(MSGSRV_AGENT_ANTISPAM); - XplConsolePrintf("bongoantispam: Unable to create connection pool; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to create connection pool"); return(-1); } } else { - XplConsolePrintf("bongoantispam: Unable to initialize memory manager; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to initialize memory manager"); return(-1); } ConnStartup(CONNECTION_TIMEOUT, TRUE); - MDBInit(); - ASpam.handle.directory = (MDBHandle)MsgInit(); - if (ASpam.handle.directory == NULL) { - XplBell(); - XplConsolePrintf("bongoantispam: Invalid directory credentials; exiting!\r\n"); - XplBell(); - - MemoryManagerClose(MSGSRV_AGENT_ANTISPAM); - - return(-1); - } - - NMAPInitialize(ASpam.handle.directory); + MsgInit(); + NMAPInitialize(); SetCurrentNameSpace(NWOS2_NAME_SPACE); SetTargetNameSpace(NWOS2_NAME_SPACE); ASpam.handle.logging = LoggerOpen("bongoantispam"); if (!ASpam.handle.logging) { - XplConsolePrintf("bongoantispam: Unable to initialize logging; disabled.\r\n"); + Log(LOG_ERROR, "Unable to initialze logging"); } ReadConfiguration(); @@ -987,7 +886,7 @@ XplServiceMain(int argc, char *argv[]) // the right place, really... // if (ASpam.allow.used || ASpam.disallow.used) { if (QueueSocketInit() < 0) { - XplConsolePrintf("bongoantispam: Exiting.\r\n"); + Log(LOG_ERROR, "Init failed"); MemoryManagerClose(MSGSRV_AGENT_ANTISPAM); @@ -997,7 +896,7 @@ XplServiceMain(int argc, char *argv[]) /* initialize scanning engine here */ if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongoantispam: Could not drop to unprivileged user '%s', exiting.\r\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); MemoryManagerClose(MSGSRV_AGENT_ANTISPAM); @@ -1005,9 +904,11 @@ XplServiceMain(int argc, char *argv[]) } ASpam.nmap.ssl.enable = FALSE; - ASpam.nmap.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); + + ASpam.nmap.ssl.config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + ASpam.nmap.ssl.config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); + ASpam.nmap.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - ASpam.nmap.ssl.config.key.file = MsgGetTLSKeyPath(NULL); ASpam.nmap.ssl.context = ConnSSLContextAlloc(&(ASpam.nmap.ssl.config)); if (ASpam.nmap.ssl.context) { diff --git a/src/agents/antispam/antispam.h b/src/agents/antispam/antispam.h index 6c6936c..bcabc59 100644 --- a/src/agents/antispam/antispam.h +++ b/src/agents/antispam/antispam.h @@ -22,8 +22,10 @@ #ifndef _ANTISPAM_H #define _ANTISPAM_H +#define LOGGERNAME "antispam" +#include + #include -#include #include #include #include @@ -64,7 +66,6 @@ typedef struct { unsigned char *envelope; unsigned char line[CONN_BUFSIZE + 1]; unsigned char command[CONN_BUFSIZE + 1]; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; } ASpamClient; typedef struct { @@ -81,16 +82,6 @@ typedef struct _ASpamGlobals { unsigned char officialName[MAXEMAILNAMESIZE + 1]; - struct { - unsigned long used; - MDBValueStruct *list; - } allow; - - struct { - unsigned long used; - MDBValueStruct *list; - } disallow; - struct { XplSemaphore semaphore; @@ -124,12 +115,9 @@ typedef struct _ASpamGlobals { unsigned long queue; unsigned char address[80]; - unsigned char hash[NMAP_HASH_SIZE]; } nmap; struct { - MDBHandle directory; - void *logging; } handle; diff --git a/src/agents/antispam/spamd.c b/src/agents/antispam/spamd.c index 4dfc471..5b52087 100644 --- a/src/agents/antispam/spamd.c +++ b/src/agents/antispam/spamd.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -69,9 +68,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha double score = 0; Connection *conn; /* Holds the current connection to spamd. */ -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) Checking with SpamAssassin spamd\n", queueID); -#endif + Log(LOG_DEBUG, "(%s) Checking with spamd", queueID); infected = FALSE; conn = ConnAddressPoolConnect(&(spamd->hosts), spamd->connectionTimeout); @@ -105,11 +102,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha /* Write the message body to the connection. */ && ((ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE) ) != -1)) { /* Read response from spamd. */ -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) Answer from socket: \"%s\"\n", queueID, client->line); -#else - ; -#endif + Log(LOG_DEBUG, "(%s) Answer from socket: '%s'", queueID, client->line); } else { goto ErrConnFree; } @@ -165,7 +158,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha */ ptr = strchr(client->line, ';'); score = atof(++ptr); - XplConsolePrintf("AntiSpam: (%s) Current message received a spam score of %f\n", queueID, score); + Log(LOG_INFO, "(%s) spam score of %f", queueID, score); } } infected = TRUE; @@ -180,9 +173,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha ) { ; } else { -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) error while creating new queue entry.\n", queueID); -#endif + Log(LOG_DEBUG, "(%s) Error creating new queue entry."); NMAPSendCommand(client->conn, "QABRT\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); goto ErrConnFree; @@ -244,11 +235,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha /* Copy out the message data from spamd. * Tell nmap to process the new message. */ -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) Created new queue entry with spam headers.\n", queueID); -#else - ; -#endif + Log(LOG_DEBUG, "(%s) Created new queue entry with spam headers.", queueID); } else { NMAPSendCommand(client->conn, "QABRT\r\n", 7); goto ErrConnFree; @@ -256,9 +243,7 @@ SpamdCheck(SpamdConfig *spamd, ASpamClient *client, const char *queueID, BOOL ha /* Drop original message. */ -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) Dropped original spam message from the queue.\n", queueID); -#endif + Log(LOG_DEBUG, "(%s) Dropped original spam message from the queue", queueID); ccode = NMAPSendCommandF(client->conn, "QDELE %s\r\n", queueID); /* expect ccode != -1*/ ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE); /* expect ccode == 1000 */ #if 0 @@ -280,10 +265,7 @@ this is commented out until we determine how we'd want to do this sort of thing, #endif } else { /* Pass message */ - -#ifdef VERBOSE_SPAMD - XplConsolePrintf("AntiSpam: (%s) Recieved a non-zero status code from spamd: %d", queueID, ccode); -#endif + Log(LOG_DEBUG, "(%s) Received a non-zero status code from spamd: %d", queueID, ccode); } ErrConnFree: @@ -291,7 +273,7 @@ this is commented out until we determine how we'd want to do this sort of thing, return infected; } - XplConsolePrintf("BONGOANTISPAM: failed to connecto to spamd server!\n"); + Log(LOG_ERROR, "(%s) Failed to connect to the spamd server"); return(FALSE); } @@ -349,6 +331,9 @@ ParseHost(char *buffer, char **host, unsigned short *port, unsigned long *weight static BongoConfigItem SpamdHostList = { BONGO_JSON_STRING, NULL, &ASpam.spamd.hostlist }; +// TODO: other items we might want to configure. +// ASpam.nmap.queue - defaults to Q_INCOMING + static BongoConfigItem SpamdConfigSchema[] = { { BONGO_JSON_INT, "o:timeout/i", &ASpam.spamd.connectionTimeout }, { BONGO_JSON_ARRAY, "o:hosts/a", &SpamdHostList}, diff --git a/src/agents/avirus/Bongo.rules b/src/agents/avirus/Bongo.rules index a2f8b8f..ac0578c 100644 --- a/src/agents/avirus/Bongo.rules +++ b/src/agents/avirus/Bongo.rules @@ -1,17 +1,16 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoavirus -bongoavirus_SOURCES := \ +bongoavirus_SOURCES = \ src/agents/avirus/avirus.c \ src/agents/avirus/avirus.h \ src/agents/avirus/mime.c \ src/agents/avirus/stream.c -bongoavirus_LDADD := \ +bongoavirus_LDADD = \ libbongonmap.la \ libbongostreamio.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/avirus/avirus.c b/src/agents/avirus/avirus.c index a129f0b..bced1fd 100755 --- a/src/agents/avirus/avirus.c +++ b/src/agents/avirus/avirus.c @@ -25,10 +25,12 @@ #include #include + +#define LOGGERNAME "antivirus" #include + #include #include -#include #include #include #include @@ -45,40 +47,6 @@ static void SignalHandler(int sigtype); -#define QUEUE_WORK_TO_DO(c, id, r) \ - { \ - XplWaitOnLocalSemaphore(AVirus.nmap.semaphore); \ - if (XplSafeRead(AVirus.nmap.worker.idle)) { \ - (c)->queue.previous = NULL; \ - if (((c)->queue.next = AVirus.nmap.worker.head) != NULL) { \ - (c)->queue.next->queue.previous = (c); \ - } else { \ - AVirus.nmap.worker.tail = (c); \ - } \ - AVirus.nmap.worker.head = (c); \ - (r) = 0; \ - } else { \ - XplSafeIncrement(AVirus.nmap.worker.active); \ - XplSignalBlock(); \ - XplBeginThread(&(id), HandleConnection, 24 * 1024, XPL_INT_TO_PTR(XplSafeRead(AVirus.nmap.worker.active)), (r)); \ - XplSignalHandler(SignalHandler); \ - if (!(r)) { \ - (c)->queue.previous = NULL; \ - if (((c)->queue.next = AVirus.nmap.worker.head) != NULL) { \ - (c)->queue.next->queue.previous = (c); \ - } else { \ - AVirus.nmap.worker.tail = (c); \ - } \ - AVirus.nmap.worker.head = (c); \ - } else { \ - XplSafeDecrement(AVirus.nmap.worker.active); \ - (r) = -1; \ - } \ - } \ - XplSignalLocalSemaphore(AVirus.nmap.semaphore); \ - } - - AVirusGlobals AVirus; static BOOL @@ -102,10 +70,6 @@ AVClientFree(AVClient *client) c->conn = NULL; } - if (c->uservs) { - MDBDestroyValueStruct(c->uservs); - } - MemPrivatePoolReturnEntry(c); return; @@ -125,12 +89,6 @@ FreeClientData(AVClient *client) client->conn = NULL; } - if (client->uservs) { - MDBFreeValues(client->uservs); - - MDBSetValueStructContext(NULL, client->uservs); - } - if (client->envelope) { MemFree(client->envelope); } @@ -264,10 +222,8 @@ ScanMessageClam(AVClient *client, char *queueID) infected = 0; - conn = ConnAlloc(TRUE); + conn = ConnAddressPoolConnect(&(AVirus.clam.hosts), AVirus.clam.timeout); if (conn) { - memcpy(&conn->socketAddress, &AVirus.clam.addr, sizeof(struct sockaddr_in)); - if (ConnConnectEx(conn, NULL, 0, NULL, client->conn->trace.destination) >= 0) { Connection *data; unsigned short port; @@ -286,7 +242,7 @@ ScanMessageClam(AVClient *client, char *queueID) return -1; } - memcpy(&data->socketAddress, &AVirus.clam.addr, sizeof(struct sockaddr_in)); + memcpy(&data->socketAddress, &conn->socketAddress, sizeof(struct sockaddr_in)); data->socketAddress.sin_port = htons(port); if (ConnConnectEx(data, NULL, 0, NULL, client->conn->trace.destination) < 0) { ConnFree(conn); @@ -319,30 +275,29 @@ ScanMessageClam(AVClient *client, char *queueID) ConnFree(data); if ((ccode == -1) || ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != 1000)) { - XplConsolePrintf("DEBUG: result %d\n", ccode); + Log(LOG_DEBUG, "result: %d", ccode); ConnFree(conn); return -1; } while ((ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE)) != -1) { - char *ptr; + char *ptr; - ptr = strrchr(client->line, ' '); - if (XplStrCaseCmp(ptr + 1, "FOUND") == 0) { - *ptr = '\0'; - ptr = client->line + strlen("stream: "); + ptr = strrchr(client->line, ' '); + if (XplStrCaseCmp(ptr + 1, "FOUND") == 0) { + *ptr = '\0'; + ptr = client->line + strlen("stream: "); - if(client->foundViruses.used == client->foundViruses.allocated) { - client->foundViruses.names = MemRealloc(client->foundViruses.names, sizeof(char*) * (client->foundViruses.allocated + MIME_REALLOC_SIZE)); - } - client->foundViruses.names[client->foundViruses.used++] = MemStrdup(ptr); - - XplSafeIncrement(AVirus.stats.viruses); - infected = 1; - } + if(client->foundViruses.used == client->foundViruses.allocated) { + client->foundViruses.names = MemRealloc(client->foundViruses.names, sizeof(char*) * (client->foundViruses.allocated + MIME_REALLOC_SIZE)); + } + client->foundViruses.names[client->foundViruses.used++] = MemStrdup(ptr); + + XplSafeIncrement(AVirus.stats.viruses); + infected = 1; + } } - } - ConnFree(conn); + ConnFree(conn); } return infected; @@ -364,7 +319,7 @@ ScanMessage(AVClient *client, char *qID) } static __inline int -SendNotification(AVClient *client, unsigned char *from, unsigned char *qID, MDBValueStruct *nUsers) +SendNotification(AVClient *client, unsigned char *from, unsigned char *qID, BongoSList *users) { int ccode; unsigned long used; @@ -418,11 +373,16 @@ SendNotification(AVClient *client, unsigned char *from, unsigned char *qID, MDBV if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1) && (ccode == 1000)) { - for (used = 0; (used < nUsers->Used) && (ccode != -1); used += 2) { - if (strchr(nUsers->Value[used], '@')) { - ccode = NMAPSendCommandF(client->conn, "QSTOR TO %s %s %lu\r\n", nUsers->Value[used], nUsers->Value[used + 1], (long unsigned int)0); + BongoSList *userlist; + for (userlist = users; userlist != NULL; userlist = userlist->next) { + AVRecipient *recip; + recip = (AVRecipient *)userlist->data; + if (strchr(recip->name, '@')) { + ccode = NMAPSendCommandF(client->conn, "QSTOR TO %s %s %lu\r\n", + recip->name, recip->address, (long unsigned int)0); } else { - ccode = NMAPSendCommandF(client->conn, "QSTOR LOCAL %s %s %lu\r\n", nUsers->Value[used], nUsers->Value[used+1], (long unsigned int)0); + ccode = NMAPSendCommandF(client->conn, "QSTOR LOCAL %s %s %lu\r\n", + recip->name, recip->address, (long unsigned int)0); } if (ccode != -1) { @@ -520,7 +480,7 @@ ProcessConnection(AVClient *client) unsigned char qID[16]; BOOL copy; BOOL infected = FALSE; - MDBValueStruct *nUsers; + BongoSList *users; if (((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1) && (ccode == 6020) @@ -560,35 +520,38 @@ ProcessConnection(AVClient *client) return(-1); } + /* if (AVirus.flags & AV_FLAG_NOTIFY_USER) { - nUsers = MDBShareContext(client->uservs); - if (!nUsers) { - MemFree(client->envelope); - client->envelope = NULL; - - NMAPSendCommand(client->conn, "QDONE\r\n", 7); - NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); - return(-1); - } + users = MemMalloc0(sizeof(BongoSList)); + if (!users) { + MemFree(client->envelope); + client->envelope = NULL; + + NMAPSendCommand(client->conn, "QDONE\r\n", 7); + NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); + return(-1); + } } else { - nUsers = NULL; + users = NULL; } + */ + users = NULL; preserve = '\0'; if (AVirus.flags & AV_FLAG_SCAN_INCOMING) { XplSafeIncrement(AVirus.stats.messages.scanned); - ccode = ScanMessage(client, qID); - - if (ccode == -1) { - MemFree(client->envelope); - client->envelope = NULL; - - NMAPSendCommand(client->conn, "QDONE\r\n", 7); - NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); - return(-1); - } + ccode = ScanMessage(client, qID); + + if (ccode == -1) { + MemFree(client->envelope); + client->envelope = NULL; + + NMAPSendCommand(client->conn, "QDONE\r\n", 7); + NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); + return(-1); + } infected = (ccode > 0); @@ -681,8 +644,7 @@ ProcessConnection(AVClient *client) } } - LoggerEvent(AVirus.handle.logging, LOGGER_SUBSYSTEM_QUEUE, LOGGER_EVENT_VIRUS_BLOCKED, LOG_INFO, 0, cur + 1, client->foundViruses.used > 0 ? client->foundViruses.names[0] : "", source, 0, from, from? strlen(from) + 1: 0); - + Log(LOG_INFO, "(%s) Blocked %d viruses including '%s' sent from '%s' to '%s'", qID, client->foundViruses.used, client->foundViruses.names[0], from, email); if (email > cur + 1) { email[-1] = ' '; @@ -693,8 +655,11 @@ ProcessConnection(AVClient *client) copy = FALSE; if (AVirus.flags & AV_FLAG_NOTIFY_USER) { - MDBAddValue(cur + 1, nUsers); - MDBAddValue(email, nUsers); + AVRecipient *recip; + recip = MemMalloc0(sizeof(AVRecipient)); + recip->name = MemStrdup(cur + 1); + recip->address = MemStrdup(email); + users = BongoSListAppend(users, (void *)recip); } break; @@ -718,7 +683,7 @@ ProcessConnection(AVClient *client) } if (AVirus.flags & AV_FLAG_NOTIFY_USER) { - SendNotification(client, from, qID, nUsers); + SendNotification(client, from, qID, users); } } } else { @@ -800,6 +765,9 @@ ProcessConnection(AVClient *client) ptr = NULL; } +#if 0 +// REMOVE-MDB +// FIXME! What is this code actually doing? if (!MsgFindObject(cur + 1, client->dn, NULL, NULL, client->uservs)) { MDBFreeValues(client->uservs); @@ -815,24 +783,28 @@ ProcessConnection(AVClient *client) } MDBFreeValues(client->uservs); +#endif } else { break; } - if (MsgGetUserFeature(client->dn, FEATURE_ANTIVIRUS, NULL, NULL)) { + //if (MsgGetUserFeature(client->dn, FEATURE_ANTIVIRUS, NULL, NULL)) { XplSafeIncrement(AVirus.stats.messages.scanned); ccode = ScanMessage(client, qID); infected = (ccode == 1); if (infected) { - BOOL bounce = TRUE; - /* Message is infected, do not copy this recipient on it, since he has virus protection */ if (AVirus.flags & AV_FLAG_NOTIFY_USER) { - MDBAddValue(cur + 1, nUsers); - MDBAddValue(email, nUsers); + AVRecipient *recip; + recip = MemMalloc0(sizeof(AVRecipient)); + recip->name = MemStrdup(cur + 1); + recip->address = MemStrdup(email); + users = BongoSListAppend(users, (void *)recip); } +#if 0 +// we bounce virus messages back to the sender over my dead body if ((AVirus.flags & AV_FLAG_NOTIFY_SENDER) && ((ccode = NMAPSendCommandF(client->conn, "QGREP %s Precedence:\r\n", qID)) != -1) @@ -866,11 +838,12 @@ ProcessConnection(AVClient *client) break; } } +#endif XplSafeIncrement(AVirus.stats.attachments.blocked); copy = FALSE; } - } + // } if ((email - 1) > cur + 1) { *(email - 1) = ' '; @@ -901,7 +874,7 @@ ProcessConnection(AVClient *client) } if (infected && (AVirus.flags & AV_FLAG_NOTIFY_USER)) { - SendNotification(client, from, qID, nUsers); + SendNotification(client, from, qID, users); } } @@ -914,8 +887,19 @@ ProcessConnection(AVClient *client) ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } - if (AVirus.flags & AV_FLAG_NOTIFY_USER) { - MDBDestroyValueStruct(nUsers); + if ((AVirus.flags & AV_FLAG_NOTIFY_USER) && users) { + BongoSList *userlist; + for (userlist = users; userlist != NULL; userlist = userlist->next) { + AVRecipient *recip; + recip = (AVRecipient *)userlist->data; + if (recip){ + MemFree(recip->name); + MemFree(recip->address); + MemFree(recip); + } + userlist->data = NULL; + } + BongoSListFree(users); } MemFree(client->envelope); @@ -933,13 +917,12 @@ HandleConnection(void *param) time_t wokeup; AVClient *client; - if (((client = AVClientAlloc()) == NULL) - || ((client->uservs = MDBCreateValueStruct(AVirus.handle.directory, NULL)) == NULL)) { + if ((client = AVClientAlloc()) == NULL) { if (client) { AVClientFree(client); } - XplConsolePrintf("antivirus: New worker failed to startup; out of memory.\r\n"); + Log(LOG_ERROR, "New worker failed startup; out of memory."); NMAPSendCommand(client->conn, "QDONE\r\n", 7); @@ -949,8 +932,6 @@ HandleConnection(void *param) } do { - MDBValueStruct *tempv; - XplRenameThread(XplGetThreadID(), "AVirus Worker"); XplSafeIncrement(AVirus.nmap.worker.idle); @@ -999,10 +980,7 @@ HandleConnection(void *param) sleep = time(NULL); - tempv = client->uservs; AVClientAllocCB(client, NULL); - client->uservs = tempv; - } while (AVirus.state == AV_STATE_RUNNING); FreeClientData(client); @@ -1035,7 +1013,36 @@ AntiVirusServer(void *ignored) if (AVirus.state < AV_STATE_STOPPING) { conn->ssl.enable = FALSE; - QUEUE_WORK_TO_DO(conn, id, ccode); + XplWaitOnLocalSemaphore(AVirus.nmap.semaphore); + if (XplSafeRead(AVirus.nmap.worker.idle)) { + conn->queue.previous = NULL; + if ((conn->queue.next = AVirus.nmap.worker.head) != NULL) { + conn->queue.next->queue.previous = conn; + } else { + AVirus.nmap.worker.tail = conn; + } + AVirus.nmap.worker.head = conn; + ccode = 0; + } else { + XplSafeIncrement(AVirus.nmap.worker.active); + XplSignalBlock(); + XplBeginThread(&(id), HandleConnection, 24 * 1024, XPL_INT_TO_PTR(XplSafeRead(AVirus.nmap.worker.active)), ccode); + XplSignalHandler(SignalHandler); + if (!ccode) { + conn->queue.previous = NULL; + if ((conn->queue.next = AVirus.nmap.worker.head) != NULL) { + conn->queue.next->queue.previous = conn; + } else { + AVirus.nmap.worker.tail = conn; + } + AVirus.nmap.worker.head = conn; + } else { + XplSafeDecrement(AVirus.nmap.worker.active); + ccode = -1; + } + } + XplSignalLocalSemaphore(AVirus.nmap.semaphore); + if (!ccode) { XplSignalLocalSemaphore(AVirus.nmap.worker.todo); @@ -1059,7 +1066,7 @@ AntiVirusServer(void *ignored) #endif case EINTR: { if (AVirus.state < AV_STATE_STOPPING) { - LoggerEvent(AVirus.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); + Log(LOG_ERROR, "accept() failed; errno: %d", errno); } continue; @@ -1067,10 +1074,7 @@ AntiVirusServer(void *ignored) default: { if (AVirus.state < AV_STATE_STOPPING) { - XplConsolePrintf("antivirus: Exiting after an accept() failure; error %d\r\n", errno); - - LoggerEvent(AVirus.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); - + Log(LOG_ERROR, "Exiting after an accept() failure; error %d.", errno); AVirus.state = AV_STATE_STOPPING; } @@ -1084,9 +1088,7 @@ AntiVirusServer(void *ignored) /* Shutting down */ AVirus.state = AV_STATE_UNLOADING; -#if VERBOSE - XplConsolePrintf("antivirus: Shutting down.\r\n"); -#endif + Log(LOG_DEBUG, "Shutting down"); id = XplSetThreadGroupID(AVirus.id.group); @@ -1115,9 +1117,7 @@ AntiVirusServer(void *ignored) XplDelay(1000); } -#if VERBOSE - XplConsolePrintf("antivirus: Shutting down %d queue threads\r\n", XplSafeRead(AVirus.nmap.worker.active)); -#endif + Log(LOG_DEBUG, "Shutting down %d queue threads.", XplSafeRead(AVirus.nmap.worker.active)); XplWaitOnLocalSemaphore(AVirus.nmap.semaphore); @@ -1133,16 +1133,13 @@ AntiVirusServer(void *ignored) } if (XplSafeRead(AVirus.server.active) > 1) { - XplConsolePrintf("antivirus: %d server threads outstanding; attempting forceful unload.\r\n", XplSafeRead(AVirus.server.active) - 1); + Log(LOG_DEBUG, "%d server threads outstanding; attempting forceful unload.", XplSafeRead(AVirus.server.active) -1); } if (XplSafeRead(AVirus.nmap.worker.active)) { - XplConsolePrintf("antivirus: %d threads outstanding; attempting forceful unload.\r\n", XplSafeRead(AVirus.nmap.worker.active)); + Log(LOG_DEBUG, "%d threads outstanding; attempting forceful unload.", XplSafeRead(AVirus.nmap.worker.active)); } - LoggerClose(AVirus.handle.logging); - AVirus.handle.logging = NULL; - /* shutdown the scanning engine */ XplCloseLocalSemaphore(AVirus.nmap.worker.todo); @@ -1161,9 +1158,7 @@ AntiVirusServer(void *ignored) MemoryManagerClose(MSGSRV_AGENT_ANTIVIRUS); -#if VERBOSE - XplConsolePrintf("antivirus: Shutdown complete\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown complete"); XplSignalLocalSemaphore(AVirus.sem.main); XplWaitOnLocalSemaphore(AVirus.sem.shutdown); @@ -1176,12 +1171,54 @@ AntiVirusServer(void *ignored) return; } +static void +ParseHost(char *buffer, char **host, unsigned short *port, unsigned long *weight) +{ + char *portPtr; + char *weightPtr; + + portPtr = NULL; + weightPtr = NULL; + + if (*buffer == '\0') { + return; + } + + if (*buffer == ':') { + portPtr = buffer; + } else { + *host = buffer; + portPtr = strchr(buffer + 1, ':'); + } + + if (portPtr) { + *portPtr = '\0'; + portPtr++; + if (*portPtr == ':') { + weightPtr = portPtr; + } else if (*portPtr != '\0') { + *port = (unsigned short)atol(portPtr); + weightPtr = strchr(portPtr + 1, ':'); + } + + if (weightPtr) { + weightPtr++; + if ( *weightPtr != '\0' ) { + *weight = (unsigned long)atol(weightPtr); + } /*else, retain preset default weight */ + } + } +} + + +static BongoConfigItem AVirusHostList = { BONGO_JSON_STRING, NULL, &AVirus.clam.hostlist }; + static BongoConfigItem AVirusConfig[] = { { BONGO_JSON_INT, "o:flags/i", &AVirus.flags }, { BONGO_JSON_STRING, "o:patterns/s", &AVirus.path.patterns }, { BONGO_JSON_INT, "o:queue/i", &AVirus.nmap.queue }, - { BONGO_JSON_STRING, "o:host/s", &AVirus.clam.host }, - { BONGO_JSON_INT, "o:port/i", &AVirus.clam.addr.sin_port }, + { BONGO_JSON_ARRAY, "o:hosts/a", &AVirusHostList }, + { BONGO_JSON_INT, "o:timeout/i", &AVirus.clam.timeout }, { BONGO_JSON_NULL, NULL, NULL } }; @@ -1191,22 +1228,30 @@ ReadConfiguration(void) unsigned char path[XPL_MAX_PATH + 1]; XplDir *dir; XplDir *dirEntry; - struct hostent *he; + unsigned int i; - if (! ReadBongoConfiguration(AVirusConfig, "antivirus")) - return FALSE; - - AVirus.clam.addr.sin_family = AF_INET; - - he = gethostbyname(AVirus.clam.host); - if (he) { - memcpy(&AVirus.clam.addr.sin_addr.s_addr, he->h_addr_list[0], - sizeof(AVirus.clam.addr.sin_addr.s_addr)); + if (! ReadBongoConfiguration(AVirusConfig, "antivirus")) { + return FALSE; } - MsgGetWorkDir(AVirus.path.work); + if (! ReadBongoConfiguration(GlobalConfig, "global")) { + return FALSE; + } + + + ConnAddressPoolStartup(&AVirus.clam.hosts, 0, 0); + for (i=0; isocket = ConnServerSocket(AVirus.nmap.conn, 2048); if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("antivirus: Could not drop to unprivileged user '%s'\r\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); ConnFree(AVirus.nmap.conn); AVirus.nmap.conn = NULL; return(-1); } if (AVirus.nmap.conn->socket == -1) { - XplConsolePrintf("antivirus: Could not bind to dynamic port\r\n"); + Log(LOG_ERROR, "Could not bind to dynamic port."); ConnFree(AVirus.nmap.conn); AVirus.nmap.conn = NULL; return(-1); } - if (NMAPRegister(MSGSRV_AGENT_ANTIVIRUS, AVirus.nmap.queue, AVirus.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { - XplConsolePrintf("antivirus: Could not register with bongonmap\r\n"); + if (QueueRegister(MSGSRV_AGENT_ANTIVIRUS, AVirus.nmap.queue, AVirus.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { + Log(LOG_ERROR, "Could not register with bongoqueue"); ConnFree(AVirus.nmap.conn); AVirus.nmap.conn = NULL; return(-1); } } else { - XplConsolePrintf("antivirus: Could not allocate connection.\r\n"); + Log(LOG_ERROR, "Could not allocate connection."); return(-1); } @@ -1328,7 +1373,7 @@ XplServiceMain(int argc, char *argv[]) int ccode; if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("antivirus: Could not drop to unprivileged user '%s', exiting.\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); return(1); } XplInit(); @@ -1351,9 +1396,6 @@ XplServiceMain(int argc, char *argv[]) AVirus.nmap.ssl.context = NULL; AVirus.nmap.ssl.config.options = 0; - AVirus.handle.directory = NULL; - AVirus.handle.logging = NULL; - strcpy(AVirus.nmap.address, "127.0.0.1"); XplSafeWrite(AVirus.server.active, 0); @@ -1378,47 +1420,31 @@ XplServiceMain(int argc, char *argv[]) } else { MemoryManagerClose(MSGSRV_AGENT_ANTIVIRUS); - XplConsolePrintf("antivirus: Unable to create connection pool; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to create connection pool; shutting down."); return(-1); } } else { - XplConsolePrintf("antivirus: Unable to initialize memory manager; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to initialize memory manager; shutting down."); return(-1); } ConnStartup(CONNECTION_TIMEOUT, TRUE); - MDBInit(); - AVirus.handle.directory = (MDBHandle)MsgInit(); - if (AVirus.handle.directory == NULL) { - XplBell(); - XplConsolePrintf("antivirus: Invalid directory credentials; exiting!\r\n"); - XplBell(); - - MemoryManagerClose(MSGSRV_AGENT_ANTIVIRUS); - - return(-1); - } - + MsgInit(); StreamioInit(); - NMAPInitialize(AVirus.handle.directory); + NMAPInitialize(); XplRWLockInit(&AVirus.lock.pattern); SetCurrentNameSpace(NWOS2_NAME_SPACE); SetTargetNameSpace(NWOS2_NAME_SPACE); - AVirus.handle.logging = LoggerOpen("bongoavirus"); - if (!AVirus.handle.logging) { - XplConsolePrintf("antivirus: Unable to initialize logging; disabled.\r\n"); - } - ReadConfiguration(); CONN_TRACE_INIT((char *)MsgGetWorkDir(NULL), "avirus"); // CONN_TRACE_SET_FLAGS(CONN_TRACE_ALL); /* uncomment this line and pass '--enable-conntrace' to autogen to get the agent to trace all connections */ if (QueueSocketInit() < 0) { - XplConsolePrintf("antivirus: Exiting.\r\n"); + Log(LOG_ERROR, "Initialization failed."); MemoryManagerClose(MSGSRV_AGENT_ANTIVIRUS); @@ -1429,7 +1455,7 @@ XplServiceMain(int argc, char *argv[]) if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("antivirus: Could not drop to unprivileged user '%s', exiting.\r\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); MemoryManagerClose(MSGSRV_AGENT_ANTIVIRUS); @@ -1437,9 +1463,9 @@ XplServiceMain(int argc, char *argv[]) } AVirus.nmap.ssl.enable = FALSE; - AVirus.nmap.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); AVirus.nmap.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - AVirus.nmap.ssl.config.key.file = MsgGetTLSKeyPath(NULL); + AVirus.nmap.ssl.config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + AVirus.nmap.ssl.config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); AVirus.nmap.ssl.context = ConnSSLContextAlloc(&(AVirus.nmap.ssl.config)); if (AVirus.nmap.ssl.context) { diff --git a/src/agents/avirus/avirus.h b/src/agents/avirus/avirus.h index ab6f4ad..9c01725 100755 --- a/src/agents/avirus/avirus.h +++ b/src/agents/avirus/avirus.h @@ -24,7 +24,6 @@ #define _AVIRUS_H #include -#include #include #include #include @@ -90,11 +89,11 @@ typedef struct _AVMIME { unsigned char *virusName; } AVMIME; -typedef struct _AVRecipients { - struct _AVRecipients *next; - +typedef struct _AVRecipient { unsigned char *name; -} AVRecipients; + unsigned char *address; + unsigned char *next; +} AVRecipient; typedef struct { AVirusClientFlags flags; @@ -102,13 +101,11 @@ typedef struct { Connection *conn; void *handle; - MDBValueStruct *uservs; - unsigned char *envelope; unsigned char work[XPL_MAX_PATH + 1]; unsigned char line[CONN_BUFSIZE + 1]; unsigned char command[CONN_BUFSIZE + 1]; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; + unsigned char dn[101]; struct { unsigned long used; @@ -166,12 +163,6 @@ typedef struct _AVirusGlobals { unsigned char hash[NMAP_HASH_SIZE]; } nmap; - struct { - MDBHandle directory; - - void *logging; - } handle; - struct { XplThreadID main; /* Tid */ XplThreadID group; /* TGid */ @@ -214,8 +205,9 @@ typedef struct _AVirusGlobals { } stats; struct { - char *host; - struct sockaddr_in addr; + BongoArray *hostlist; + AddressPool hosts; + int timeout; } clam; } AVirusGlobals; diff --git a/src/agents/calcmd/Bongo.rules b/src/agents/calcmd/Bongo.rules index 9905ef0..84e1ffa 100644 --- a/src/agents/calcmd/Bongo.rules +++ b/src/agents/calcmd/Bongo.rules @@ -1,15 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongocalcmd -bongocalcmd_SOURCES := \ +bongocalcmd_SOURCES = \ src/agents/calcmd/calcmdd.c \ src/agents/calcmd/calcmdd.h -bongocalcmd_LDADD := \ +bongocalcmd_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/calcmd/calcmdd.c b/src/agents/calcmd/calcmdd.c index b89bc7c..a371a61 100644 --- a/src/agents/calcmd/calcmdd.c +++ b/src/agents/calcmd/calcmdd.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -482,18 +481,6 @@ CalCmdAgentServer(void *ignored) static BOOL ReadConfiguration(void) { - MDBValueStruct *config; - - config = MDBCreateValueStruct(CalCmdAgent.agent.directoryHandle, - MsgGetServerDN(NULL)); - if (config) { - /* Read your agent's configuration here */ - } else { - return FALSE; - } - - MDBDestroyValueStruct(config); - return TRUE; } @@ -523,14 +510,14 @@ XplServiceMain(int argc, char *argv[]) strcpy(CalCmdAgent.nmapAddress, "127.0.0.1"); /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO | BA_STARTUP_NMAP; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_NMAP; ccode = BongoAgentInit(&CalCmdAgent.agent, AGENT_NAME, AGENT_DN, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); return -1; } - BongoCalInit(MsgGetDBFDir(NULL)); + BongoCalInit(MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); /* Set up socket for listening on an incoming queue */ CalCmdAgent.queueNumber = Q_FIVE; diff --git a/src/agents/calcmd/calcmdd.h b/src/agents/calcmd/calcmdd.h index c807bfa..32d5832 100644 --- a/src/agents/calcmd/calcmdd.h +++ b/src/agents/calcmd/calcmdd.h @@ -23,8 +23,6 @@ #define _CALCMDD_H #include -#include -#include #include #include #include @@ -63,8 +61,4 @@ typedef struct _CalCmdAgentGlobals { extern CalCmdAgentGlobals CalCmdAgent; -/* management.c */ -int CalCmdAgentManagementStart(void); -void CalCmdAgentManagementShutdown(void); - #endif /* _GENERIC_H */ diff --git a/src/agents/collector/Bongo.rules b/src/agents/collector/Bongo.rules index a8ffa1f..a3f529a 100644 --- a/src/agents/collector/Bongo.rules +++ b/src/agents/collector/Bongo.rules @@ -1,19 +1,17 @@ # -*- Makefile -*- sbin_PROGRAMS += bongocollector -bongocollector_SOURCES := \ +bongocollector_SOURCES = \ src/agents/collector/collector.c \ src/agents/collector/collector.h -bongocollector_CPPFLAGS := $(AM_CPPFLAGS) \ +bongocollector_CPPFLAGS = $(AM_CPPFLAGS) \ $(LIBCURL_CPPFLAGS) -bongocollector_LDADD := \ +bongocollector_LDADD = \ libbongonmap.la \ libbongocal.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/collector/collector.c b/src/agents/collector/collector.c index 8945b40..2256e4f 100644 --- a/src/agents/collector/collector.c +++ b/src/agents/collector/collector.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -66,18 +65,6 @@ CollectorLoop(void *ignored) static BOOL ReadConfiguration(void) { - MDBValueStruct *config; - - config = MDBCreateValueStruct(Collector.agent.directoryHandle, - MsgGetServerDN(NULL)); - if (config) { - /* Read your agent's configuration here */ - } else { - return FALSE; - } - - MDBDestroyValueStruct(config); - return TRUE; } @@ -102,7 +89,7 @@ XplServiceMain(int argc, char *argv[]) XplInit(); /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO | BA_STARTUP_NMAP; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_NMAP; ccode = BongoAgentInit(&Collector.agent, AGENT_NAME, AGENT_DN, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); diff --git a/src/agents/collector/collector.h b/src/agents/collector/collector.h index 50c5596..e3e0615 100644 --- a/src/agents/collector/collector.h +++ b/src/agents/collector/collector.h @@ -23,8 +23,6 @@ #define _COLLECTOR_H #include -#include -#include #include #include #include @@ -62,10 +60,6 @@ typedef enum { COLLECTOR_COMMAND_NOOP, } CollectorCommand; -/* management.c */ -int CollectorManagementStart(void); -void CollectorManagementShutdown(void); - CCode CollectorCommandPUT(CollectorClient *client, char *user, char *name, char *url); CCode CollectorCommandQUIT(CollectorClient *client); diff --git a/src/agents/generic/Bongo.rules b/src/agents/generic/Bongo.rules index f0e44d8..9660fd1 100644 --- a/src/agents/generic/Bongo.rules +++ b/src/agents/generic/Bongo.rules @@ -1,15 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongogeneric -bongogeneric_SOURCES := \ +bongogeneric_SOURCES = \ src/agents/generic/generic.c \ src/agents/generic/generic.h -bongogeneric_LDADD := \ +bongogeneric_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/generic/generic.c b/src/agents/generic/generic.c index 0e66cd4..f7dfccb 100755 --- a/src/agents/generic/generic.c +++ b/src/agents/generic/generic.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -156,18 +155,6 @@ GenericAgentServer(void *ignored) static BOOL ReadConfiguration(void) { - MDBValueStruct *config; - - config = MDBCreateValueStruct(GAgent.agent.directoryHandle, - MsgGetServerDN(NULL)); - if (config) { - /* Read your agent's configuration here */ - } else { - return FALSE; - } - - MDBDestroyValueStruct(config); - return TRUE; } @@ -197,7 +184,7 @@ XplServiceMain(int argc, char *argv[]) strcpy(GAgent.nmapAddress, "127.0.0.1"); /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO | BA_STARTUP_NMAP; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_NMAP; ccode = BongoAgentInit(&GAgent.agent, AGENT_NAME, AGENT_DN, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); diff --git a/src/agents/generic/generic.h b/src/agents/generic/generic.h index 3f73a24..a147656 100644 --- a/src/agents/generic/generic.h +++ b/src/agents/generic/generic.h @@ -23,8 +23,6 @@ #define _GENERIC_H #include -#include -#include #include #include #include @@ -56,8 +54,4 @@ typedef struct _GAgentGlobals { extern GAgentGlobals GAgent; -/* management.c */ -int GenericAgentManagementStart(void); -void GenericAgentManagementShutdown(void); - #endif /* _GENERIC_H */ diff --git a/src/agents/imap/Bongo.rules b/src/agents/imap/Bongo.rules index a4df5a4..dc4c6b2 100644 --- a/src/agents/imap/Bongo.rules +++ b/src/agents/imap/Bongo.rules @@ -1,7 +1,7 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoimap -bongoimap_SOURCES := \ +bongoimap_SOURCES = \ src/agents/imap/imapd.c \ src/agents/imap/imapd.h \ src/agents/imap/copy.c \ @@ -18,12 +18,9 @@ bongoimap_SOURCES := \ src/agents/imap/uid.c \ src/agents/imap/inline.h -bongoimap_LDADD := \ +bongoimap_LDADD = \ libbongonmap.la \ - libbongoconnmgr.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/imap/event.c b/src/agents/imap/event.c index e3d7a60..06a0b8a 100644 --- a/src/agents/imap/event.c +++ b/src/agents/imap/event.c @@ -25,11 +25,8 @@ #include -#include #include -/* Management Client Header Include */ -#include #include "imapd.h" __inline static BOOL @@ -299,7 +296,7 @@ MessageListAddNewMessages(Connection *storeConn, OpenedFolder *folder, NewEvent do { result = STATUS_CONTINUE; - if (NMAPSendCommandF(storeConn, "INFO %llx Pnmap.mail.headersize\r\n", newEvent->guid) != -1) { + if (NMAPSendCommandF(storeConn, "INFO %lx Pnmap.mail.headersize\r\n", newEvent->guid) != -1) { ccode = NMAPReadResponse(storeConn, reply, sizeof(reply), TRUE); if (ccode == 2001) { ccode = NMAPReadDecimalPropertyResponse(storeConn, "nmap.mail.headersize", &headerSize); diff --git a/src/agents/imap/fetch.c b/src/agents/imap/fetch.c index f91e052..d1199fc 100644 --- a/src/agents/imap/fetch.c +++ b/src/agents/imap/fetch.c @@ -25,11 +25,8 @@ #include -#include #include -/* Management Client Header Include */ -#include #include "imapd.h" @@ -111,7 +108,7 @@ FindRFC822Header(unsigned char *Header, unsigned char *SearchFor, unsigned char static long SendRFC822Address(ImapSession *session, unsigned char *Address, unsigned char *Answer) { - long ccode; + long ccode = 0; RFC822AddressStruct *Current; RFC822AddressStruct *Rfc822AddressList = NULL; unsigned long Len; @@ -434,7 +431,7 @@ MessageDetailsFree(MessageDetail *messageDetail) } if (messageDetail->mimeInfo) { - MDBDestroyValueStruct(messageDetail->mimeInfo); + BongoArrayFree(messageDetail->mimeInfo, TRUE); messageDetail->mimeInfo = NULL; } } @@ -502,7 +499,7 @@ FreeFetchResourcesFailure(FetchStruct *FetchRequest) __inline static long ReadBodyPart(ImapSession *session, unsigned char **Part, unsigned long ID, unsigned long Start, unsigned long Size) { - long count; + size_t count; long ccode; *Part = MemMalloc(Size + 1); @@ -511,7 +508,7 @@ ReadBodyPart(ImapSession *session, unsigned char **Part, unsigned long ID, unsig /* Request the body part*/ if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", session->folder.selected.message[ID].guid, Start, Size) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (NMAPReadCount(session->store.conn, *Part, count) == count) { + if (NMAPReadCount(session->store.conn, *Part, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -788,7 +785,7 @@ FetchFlagResponderUid(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; - if (ConnWriteF(session->client.conn, "UID %lu", FetchRequest->message->uid) != -1) { + if (ConnWriteF(session->client.conn, "UID %lu", (long)FetchRequest->message->uid) != -1) { return(STATUS_CONTINUE); } return(STATUS_ABORT); @@ -873,10 +870,11 @@ FetchFlagResponderXSender(void *param1, void *param2, void *param3) authLen = strlen(session->store.response); if (!strchr(session->store.response, '@')) { - if ((ConnWriteF(session->client.conn, "XSENDER {%lu}\r\n", authLen + 1 + Imap.server.hostnameLen) != -1) && + size_t hostlen = strlen(BongoGlobals.hostname); + if ((ConnWriteF(session->client.conn, "XSENDER {%lu}\r\n", authLen + 1 + hostlen) != -1) && (ConnWrite(session->client.conn, session->store.response, authLen) != -1) && (ConnWrite(session->client.conn, "@", 1) != -1) && - (ConnWrite(session->client.conn, Imap.server.hostname, Imap.server.hostnameLen) != -1)) { + (ConnWrite(session->client.conn, BongoGlobals.hostname, hostlen) != -1)) { return(STATUS_CONTINUE); } return(STATUS_ABORT); @@ -948,9 +946,11 @@ FetchFlagResponderBodyStructure(void *param1, void *param2, void *param3) if (ccode != -1) { do { - switch(atol(FetchRequest->messageDetail.mimeInfo->Value[mimeResponseLine])) { + char *mime_string = BongoArrayIndex(FetchRequest->messageDetail.mimeInfo, + char *, mimeResponseLine); + switch(atol(mime_string)) { case 2002: { - ParseMIMEDLine(FetchRequest->messageDetail.mimeInfo->Value[mimeResponseLine] + 5, + ParseMIMEDLine(mime_string + 5, Type, MIME_TYPE_LEN, Subtype, MIME_SUBTYPE_LEN, Charset, MIME_CHARSET_LEN, @@ -1280,7 +1280,7 @@ FetchFlagResponderBodyStructure(void *param1, void *param2, void *param3) } mimeResponseLine++; - if (mimeResponseLine < FetchRequest->messageDetail.mimeInfo->Used) { + if (mimeResponseLine < BongoArrayCount(FetchRequest->messageDetail.mimeInfo)) { continue; } @@ -1307,12 +1307,12 @@ FetchFlagResponderRfc822Text(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; long ccode; - long count; + size_t count; if (NMAPSendCommandF(session->store.conn, "READ %llx %lu\r\n", FetchRequest->message->guid, FetchRequest->message->headerSize) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "RFC822.TEXT {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "RFC822.TEXT {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1359,13 +1359,13 @@ FetchFlagResponderRfc822(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; long ccode; - long count; + size_t count; if (NMAPSendCommandF(session->store.conn, "READ %llx %lu\r\n", FetchRequest->message->guid, FetchRequest->message->headerSize) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { if (ConnWriteF(session->client.conn, "RFC822 {%lu}\r\n", count + FetchRequest->message->headerSize) != -1) { if (ConnWrite(session->client.conn, FetchRequest->messageDetail.header, FetchRequest->message->headerSize) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1439,13 +1439,12 @@ FetchFlagResponderBodyText(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; long ccode; - - long count; + size_t count; if (NMAPSendCommandF(session->store.conn, "READ %llx %lu\r\n", FetchRequest->message->guid, FetchRequest->message->headerSize) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "BODY[TEXT] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "BODY[TEXT] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1467,7 +1466,7 @@ FetchFlagResponderBodyTextPartial(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; - long count; + size_t count; long ccode; if (flag->partial.start < FetchRequest->message->bodySize) { @@ -1479,8 +1478,8 @@ FetchFlagResponderBodyTextPartial(void *param1, void *param2, void *param3) if (ccode != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "BODY[TEXT]<%lu> {%lu}\r\n", flag->partial.start, count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "BODY[TEXT]<%lu> {%lu}\r\n", flag->partial.start, (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1508,12 +1507,12 @@ FetchFlagResponderBodyBoth(void *param1, void *param2, void *param3) ImapSession *session = (ImapSession *)param1; FetchStruct *FetchRequest = (FetchStruct *)param2; long ccode; - long count; + size_t count; if (NMAPSendCommandF(session->store.conn, "READ %llx\r\n", FetchRequest->message->guid) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "BODY[] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "BODY[] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1536,13 +1535,13 @@ FetchFlagResponderBodyBothPartial(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; if (flag->partial.start < FetchRequest->message->size) { - if (NMAPSendCommandF(session->store.conn, "READ %llx %d %lu\r\n", FetchRequest->message->guid, flag->partial.start, flag->partial.len) != -1) { + if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->partial.start, flag->partial.len) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "BODY[]<%lu> {%lu}\r\n", flag->partial.start, count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "BODY[]<%lu> {%lu}\r\n", flag->partial.start, (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1705,13 +1704,13 @@ FetchFlagResponderBodyHeaderFields(void *param1, void *param2, void *param3) } __inline static BOOL -HasPart(MDBValueStruct *mimeInfo, BodyPartRequestStruct *request) +HasPart(BongoArray *mimeInfo, BodyPartRequestStruct *request) { unsigned char type[MIME_TYPE_LEN+1]; unsigned char dummy[MIME_NAME_LEN+1]; unsigned long dummyLong; - long depthChange; + long depthChange = 0; BOOL haveRfc822 = TRUE; unsigned long mimeResponseLine = 0; @@ -1721,9 +1720,10 @@ HasPart(MDBValueStruct *mimeInfo, BodyPartRequestStruct *request) unsigned long matchDepthPart = 0; do { - switch (atol(mimeInfo->Value[mimeResponseLine])) { + char *mime_string = BongoArrayIndex(mimeInfo, char *, mimeResponseLine); + switch (atol(mime_string)) { case 2002: { - ParseMIMEDLine(mimeInfo->Value[mimeResponseLine] + 5, + ParseMIMEDLine(mime_string + 5, type, MIME_TYPE_LEN, dummy, MIME_NAME_LEN, dummy, MIME_NAME_LEN, @@ -1808,7 +1808,7 @@ HasPart(MDBValueStruct *mimeInfo, BodyPartRequestStruct *request) } mimeResponseLine++; - if (mimeResponseLine < mimeInfo->Used) { + if (mimeResponseLine < BongoArrayCount(mimeInfo)) { if (depthChange == 0) { continue; } @@ -1840,7 +1840,7 @@ FetchFlagResponderBodyPartNumber(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; if (ConnWriteF(session->client.conn, "BODY[%lu", flag->bodyPart.part[0]) != -1) { @@ -1854,8 +1854,8 @@ FetchFlagResponderBodyPartNumber(void *param1, void *param2, void *param3) if (HasPart(FetchRequest->messageDetail.mimeInfo, &(flag->bodyPart))) { if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.partOffset, flag->bodyPart.partLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1885,7 +1885,7 @@ FetchFlagResponderBodyPartNumberPartial(void *param1, void *param2, void *param3 FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; long resultLen; @@ -1909,8 +1909,8 @@ FetchFlagResponderBodyPartNumberPartial(void *param1, void *param2, void *param3 if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.partOffset + flag->partial.start, resultLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, "]<%lu> {%lu}\r\n", flag->partial.start, count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, "]<%lu> {%lu}\r\n", flag->partial.start, (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1944,7 +1944,7 @@ FetchFlagResponderBodyPartText(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; if (ConnWriteF(session->client.conn, "BODY[%lu", flag->bodyPart.part[0]) != -1) { @@ -1958,8 +1958,8 @@ FetchFlagResponderBodyPartText(void *param1, void *param2, void *param3) if (HasPart(FetchRequest->messageDetail.mimeInfo, &(flag->bodyPart)) && flag->bodyPart.isMessage) { if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.partOffset + flag->bodyPart.messageHeaderLen, flag->bodyPart.partLen - flag->bodyPart.messageHeaderLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".TEXT] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".TEXT] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -1989,7 +1989,7 @@ FetchFlagResponderBodyPartTextPartial(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; long resultLen; unsigned long textStart; @@ -2017,8 +2017,8 @@ FetchFlagResponderBodyPartTextPartial(void *param1, void *param2, void *param3) } if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, textStart + flag->partial.start, resultLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".TEXT]<%lu> {%lu}\r\n", flag->partial.start, count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".TEXT]<%lu> {%lu}\r\n", flag->partial.start, (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -2051,7 +2051,7 @@ FetchFlagResponderBodyPartHeader(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; if (ConnWriteF(session->client.conn, "BODY[%lu", flag->bodyPart.part[0]) != -1) { @@ -2065,8 +2065,8 @@ FetchFlagResponderBodyPartHeader(void *param1, void *param2, void *param3) if (HasPart(FetchRequest->messageDetail.mimeInfo, &(flag->bodyPart)) && flag->bodyPart.isMessage ) { if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.partOffset, flag->bodyPart.messageHeaderLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".HEADER] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".HEADER] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -2095,7 +2095,7 @@ FetchFlagResponderBodyPartHeaderPartial(void *param1, void *param2, void *param3 FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; long resultLen; @@ -2117,8 +2117,8 @@ FetchFlagResponderBodyPartHeaderPartial(void *param1, void *param2, void *param3 } if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.partOffset + flag->partial.start, resultLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".HEADER]<%lu> {%lu}\r\n", flag->partial.start, count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".HEADER]<%lu> {%lu}\r\n", flag->partial.start, (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -2212,7 +2212,7 @@ FetchFlagResponderBodyPartHeaderFields(void *param1, void *param2, void *param3) return(STATUS_ABORT); } - if (ConnWriteF(session->client.conn, " {0}\r\n", sizeof(" {0}\r\n") - 1) != -1) { + if (ConnWrite(session->client.conn, " {0}\r\n", sizeof(" {0}\r\n") - 1) != -1) { MemFree(resultHeader); return(STATUS_CONTINUE); } @@ -2287,7 +2287,7 @@ FetchFlagResponderBodyPartMime(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; if (ConnWriteF(session->client.conn, "BODY[%lu", flag->bodyPart.part[0]) != -1) { @@ -2300,8 +2300,8 @@ FetchFlagResponderBodyPartMime(void *param1, void *param2, void *param3) if (HasPart(FetchRequest->messageDetail.mimeInfo, &(flag->bodyPart))) { if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.mimeOffset, flag->bodyPart.mimeLen) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".MIME] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".MIME] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -2329,7 +2329,7 @@ FetchFlagResponderBodyPartMimePartial(void *param1, void *param2, void *param3) FetchStruct *FetchRequest = (FetchStruct *)param2; FetchFlagStruct *flag = (FetchFlagStruct *)param3; long ccode; - long count; + size_t count; unsigned long i; if (ConnWriteF(session->client.conn, "BODY[%lu", flag->bodyPart.part[0]) != -1) { @@ -2345,10 +2345,10 @@ FetchFlagResponderBodyPartMimePartial(void *param1, void *param2, void *param3) } else { count = flag->bodyPart.mimeLen - flag->partial.start; } - if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.mimeOffset + flag->partial.start, count) != -1) { + if (NMAPSendCommandF(session->store.conn, "READ %llx %lu %lu\r\n", FetchRequest->message->guid, flag->bodyPart.mimeOffset + flag->partial.start, (long)count) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - if (ConnWriteF(session->client.conn, ".MIME] {%lu}\r\n", count) != -1) { - if (ConnReadToConn(session->store.conn, session->client.conn, count) == count) { + if (ConnWriteF(session->client.conn, ".MIME] {%lu}\r\n", (long)count) != -1) { + if (ConnReadToConn(session->store.conn, session->client.conn, count) == (int)count) { if (NMAPReadCrLf(session->store.conn) == 2) { return(STATUS_CONTINUE); } @@ -2850,7 +2850,7 @@ ParseFetchArguments(ImapSession *session, unsigned char *ptr, FetchStruct *Fetch if (ccode == STATUS_CONTINUE) { if (FetchRequest->messageSet) { if (*ptr == ' ') { - *ptr++; + ptr++; if (*ptr != '\0') { /* parse the fetch flags */ if (*ptr == '(') { @@ -2982,12 +2982,12 @@ __inline static long GetMessageHeader(ImapSession *session, FetchStruct *FetchRequest) { int ccode; - long count; + size_t count; /* Request the header */ if (NMAPSendCommandF(session->store.conn, "READ %llx 0 %lu\r\n", FetchRequest->message->guid, FetchRequest->message->headerSize) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &count)) == 2001) { - FetchRequest->message->headerSize = count; + FetchRequest->message->headerSize = (long)count; FetchRequest->messageDetail.header = MemMalloc(FetchRequest->message->headerSize + 1); if (FetchRequest->messageDetail.header) { if ((ccode = NMAPReadCount(session->store.conn, FetchRequest->messageDetail.header, FetchRequest->message->headerSize)) > 0) { @@ -3015,21 +3015,25 @@ GetMimeInfo(ImapSession *session, FetchStruct *FetchRequest) long ccode; if (FetchRequest->messageDetail.mimeInfo == NULL) { - FetchRequest->messageDetail.mimeInfo = MDBCreateValueStruct(Imap.directory.handle, NULL); - if (FetchRequest->messageDetail.mimeInfo) { - ; - } else { + FetchRequest->messageDetail.mimeInfo = BongoArrayNew(sizeof(char *), 0); + if (! FetchRequest->messageDetail.mimeInfo) { return(STATUS_MEMORY_ERROR); } } else { - MDBFreeValues(FetchRequest->messageDetail.mimeInfo); + BongoArrayFree(FetchRequest->messageDetail.mimeInfo, TRUE); } if (NMAPSendCommandF(session->store.conn, "MIME %llx\r\n", FetchRequest->message->guid) != -1) { ccode = NMAPReadResponse(session->store.conn, session->store.response, sizeof(session->store.response), FALSE); while(ccode != 1000) { if ((ccode > 2001) && (ccode < 2005)) { - MDBAddValue(session->store.response, FetchRequest->messageDetail.mimeInfo); + char *entry; + size_t len = sizeof(char) * (strlen(session->store.response) + 1); + + entry = MemMalloc(len); + memcpy(entry, session->store.response, len); + + BongoArrayAppendValue(FetchRequest->messageDetail.mimeInfo, entry); ccode = NMAPReadResponse(session->store.conn, session->store.response, sizeof(session->store.response), FALSE); continue; } diff --git a/src/agents/imap/fetch.h b/src/agents/imap/fetch.h index 811c26a..d511fcd 100644 --- a/src/agents/imap/fetch.h +++ b/src/agents/imap/fetch.h @@ -92,7 +92,7 @@ typedef struct { typedef struct { unsigned long sequenceNumber; unsigned char *header; - MDBValueStruct *mimeInfo; + BongoArray *mimeInfo; } MessageDetail; typedef struct { diff --git a/src/agents/imap/imapd.c b/src/agents/imap/imapd.c index 1982235..a101a9c 100644 --- a/src/agents/imap/imapd.c +++ b/src/agents/imap/imapd.c @@ -1,4 +1,3 @@ - /**************************************************************************** * * Copyright (c) 2001 Novell, Inc. All Rights Reserved. @@ -40,13 +39,8 @@ #include -#include #include -/* Management Client Header Include */ -#include - -#include #include "imapd.h" ImapGlobal Imap; @@ -89,15 +83,6 @@ static ProtocolCommand ImapProtocolCommands[] = { { IMAP_COMMAND_GETQUOTA, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_GETQUOTA) - 1, ImapCommandGetQuota, NULL, NULL }, { IMAP_COMMAND_GETQUOTAROOT, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_GETQUOTAROOT) - 1, ImapCommandGetQuotaRoot, NULL, NULL }, { IMAP_COMMAND_NAMESPACE, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_NAMESPACE) - 1, ImapCommandNameSpace, NULL, NULL }, - { IMAP_COMMAND_PROXYAUTH, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_PROXYAUTH) - 1, ImapCommandProxyAuth, NULL, NULL }, -#if MDB_DEBUG - { IMAP_COMMAND_USER_LOOKUP, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_LOOKUP) - 1, ImapCommandUserLookup, NULL, NULL }, - { IMAP_COMMAND_USER_VERIFY, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_VERIFY) - 1, ImapCommandUserVerify, NULL, NULL }, - { IMAP_COMMAND_USER_READ, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_READ) - 1, ImapCommandUserRead, NULL, NULL }, - { IMAP_COMMAND_USER_WRITE_LOCAL, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_READ) - 1, ImapCommandUserWriteLocal, NULL, NULL }, - { IMAP_COMMAND_USER_WRITE_SUPER, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_READ) - 1, ImapCommandUserWriteSuper, NULL, NULL }, - { IMAP_COMMAND_USER_ENUM, IMAP_HELP_NOT_DEFINED, sizeof(IMAP_COMMAND_USER_READ) - 1, ImapCommandUserEnum, NULL, NULL }, -#endif { NULL, NULL, 0, NULL, NULL, NULL } }; @@ -156,6 +141,8 @@ CreateReturnValueIndex() return(NULL); } +#if 0 +// FIXME: Shutdown not needed atm static BOOL IMAPShutdown(unsigned char *Arguments, unsigned char **Response, BOOL *CloseConnection) { @@ -202,6 +189,7 @@ IMAPShutdown(unsigned char *Arguments, unsigned char **Response, BOOL *CloseConn return(FALSE); } +#endif static BOOL IMAPSessionAllocCB(void *Buffer, void *ClientData) @@ -370,7 +358,7 @@ __inline static long FolderGetHighestUid(Connection *storeConn, FolderInformation *folder, uint32_t *highestUid) { long ccode; - size_t propertyValue; + unsigned long propertyValue; /* Get the highest UID for the collection */ ccode = NMAPGetHexadecimalProperty(storeConn, folder->guid, "nmap.mail.imapuid", &propertyValue); @@ -386,7 +374,7 @@ __inline static long FolderGetRecentUid(Connection *storeConn, FolderInformation *folder, uint32_t *recentUid) { long ccode; - size_t propertyValue; + unsigned long propertyValue; /* Get the recent UID for the collection */ ccode = NMAPGetHexadecimalProperty(storeConn, folder->guid, "imap.recentuid", &propertyValue); @@ -436,13 +424,13 @@ FolderSendStatus(Connection *conn, OpenedFolder *folder) firstUnseen + 1, firstUnseen + 1, (unsigned long)(folder->info->guid & 0x00000000FFFFFFFF), - folder->info->uidNext); + (unsigned long)folder->info->uidNext); } else { ccode = ConnWriteF(conn, "* %lu EXISTS\r\n* %lu RECENT\r\n* OK [UIDVALIDITY %lu] UIDs valid\r\n* OK [UIDNEXT %lu] Predicted next UID\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n", folder->messageCount, folder->recentCount, (unsigned long)(folder->info->guid & 0x00000000FFFFFFFF), - folder->info->uidNext); + (unsigned long)folder->info->uidNext); } if (ccode != -1) { return(STATUS_CONTINUE); @@ -454,7 +442,7 @@ long FolderOpen(Connection *storeConn, OpenedFolder *openFolder, FolderInformation *folder, BOOL readOnly) { long ccode; - uint32_t highestUid; + uint32_t highestUid = 0; ccode = FolderGetRecentUid(storeConn, folder, &folder->uidRecent); if (ccode == STATUS_CONTINUE) { @@ -617,7 +605,7 @@ long FolderListLoad(ImapSession *session) { char buffer[CONN_BUFSIZE]; - uint64_t selectedGuid; + uint64_t selectedGuid = 0; FolderInformation *folderList; FolderInformation *newList; FolderInformation *currentFolder; @@ -858,13 +846,6 @@ ImapCommandCapability(void *param) ImapSession *session = (ImapSession *)param; if ((ccode = EventsSend(session, STORE_EVENT_ALL)) == STATUS_CONTINUE) { - if (!Imap.server.ssl.enable || session->client.conn->ssl.enable) { - if (ConnWrite(session->client.conn, Imap.command.capability.message, Imap.command.capability.len) != -1) { - return(SendOk(session, "CAPABILITY")); - } - return(STATUS_ABORT); - } - if (ConnWrite(session->client.conn, Imap.command.capability.ssl.message, Imap.command.capability.ssl.len) != -1) { return(SendOk(session, "CAPABILITY")); } @@ -1054,7 +1035,7 @@ FolderHierarchyCreate(ImapSession *session, char *folderPathUtf8) if (NMAPSendCommandF(session->store.conn, "CREATE /mail/%s\r\n", folderPathUtf8) != -1) { ccode = NMAPReadResponse(session->store.conn, NULL, 0, 0); if (ccode == 1000) { - if (NMAPSendCommandF(session->store.conn, "FLAG /mail/%s +%lu\r\n", folderPathUtf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) != -1) { + if (NMAPSendCommandF(session->store.conn, "FLAG /mail/%s +%u\r\n", folderPathUtf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) != -1) { ccode = NMAPReadResponse(session->store.conn, NULL, 0, 0); if (ccode == 1000) { *ptr = '/'; @@ -1145,7 +1126,7 @@ ImapCommandCreate(void *param) } /* this folder is just hierarchy. Make it a real folder */ - if (NMAPSendCommandF(session->store.conn, "FLAG /mail/%s -%lu\r\n", pathUtf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) == -1) { + if (NMAPSendCommandF(session->store.conn, "FLAG /mail/%s -%u\r\n", pathUtf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) == -1) { MemFree(pathUtf8); return(STATUS_NMAP_COMM_ERROR); } @@ -1167,7 +1148,7 @@ ImapCommandCreate(void *param) return(SendError(session->client.conn, session->command.tag, "CREATE", ccode)); } - if (NMAPSendCommandF(session->store.conn, "CREATE /mail/%s\r\n", pathUtf8) == -1) { + if (NMAPSendCommandF(session->store.conn, "CREATE \"/mail/%s\"\r\n", pathUtf8) == -1) { MemFree(pathUtf8); return(SendError(session->client.conn, session->command.tag, "CREATE", STATUS_NMAP_COMM_ERROR)); } @@ -1280,10 +1261,10 @@ FolderConvertToHierarchyOnly(ImapSession *session, FolderInformation *folder) { long ccode; uint64_t *guid; - uint64_t *guidList; + uint64_t *guidList = NULL; long guidCount; - if (NMAPSendCommandF(session->store.conn, "FLAG %s +%lu\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) == -1) { + if (NMAPSendCommandF(session->store.conn, "FLAG %s +%u\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_HIERARCHY_ONLY) == -1) { return(STATUS_NMAP_COMM_ERROR); } @@ -1382,7 +1363,7 @@ ImapCommandDelete(void *param) FolderDeselect(session); } - if (NMAPSendCommandF(session->store.conn, "REMOVE %s\r\n", folder->name.utf8) == -1) { + if (NMAPSendCommandF(session->store.conn, "REMOVE \"%s\"\r\n", folder->name.utf8) == -1) { return(SendError(session->client.conn, session->command.tag, "DELETE", STATUS_NMAP_COMM_ERROR)); } @@ -1398,7 +1379,7 @@ __inline static long FolderMoveMessages(ImapSession *session, char *sourcePathUtf8, char *destinationPathUtf8) { long ccode; - uint64_t *guidList; + uint64_t *guidList = NULL; uint64_t *guid; long guidCount; @@ -1540,7 +1521,7 @@ ImapCommandRename(void *param) FolderDeselect(session); } - if (NMAPSendCommandF(session->store.conn, "RENAME %s /mail/%s\r\n", sourceFolder->name.utf8, destinationPathUtf8) == -1) { + if (NMAPSendCommandF(session->store.conn, "RENAME \"%s\" \"/mail/%s\"\r\n", sourceFolder->name.utf8, destinationPathUtf8) == -1) { MemFree(destinationPathUtf8); return(SendError(session->client.conn, session->command.tag, "RENAME", STATUS_NMAP_COMM_ERROR)); } @@ -1620,7 +1601,7 @@ ImapCommandSubscribe(void *param) return(SendError(session->client.conn, session->command.tag, "SUBSCRIBE", STATUS_NO_SUCH_FOLDER)); } - if (NMAPSendCommandF(session->store.conn, "FLAG %s -%lu\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_NON_SUBSCRIBED) != -1) { + if (NMAPSendCommandF(session->store.conn, "FLAG \"%s\" -%u\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_NON_SUBSCRIBED) != -1) { FreePathArgument(&path); ccode = NMAPReadResponse(session->store.conn, NULL, 0, 0); if (ccode == 1000) { @@ -1664,7 +1645,7 @@ ImapCommandUnsubscribe(void *param) return(SendError(session->client.conn, session->command.tag, "UNSUBSCRIBE", STATUS_NO_SUCH_FOLDER)); } - if (NMAPSendCommandF(session->store.conn, "FLAG %s +%lu\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_NON_SUBSCRIBED) != -1) { + if (NMAPSendCommandF(session->store.conn, "FLAG \"%s\" +%u\r\n", folder->name.utf8, STORE_COLLECTION_FLAG_NON_SUBSCRIBED) != -1) { FreePathArgument(&path); ccode = NMAPReadResponse(session->store.conn, NULL, 0, 0); if (ccode == 1000) { @@ -1847,7 +1828,7 @@ ImapCommandList(void *param) long ccode; char pattern[STORE_MAX_COLLECTION * 2]; - unsigned long patternLen; + unsigned long patternLen = 0; if ((ccode = CheckState(session, STATE_AUTH)) == STATUS_CONTINUE) { if ((ccode = EventsSend(session, STORE_EVENT_ALL)) == STATUS_CONTINUE) { @@ -1870,7 +1851,7 @@ ImapCommandLsub(void *param) long ccode; char pattern[STORE_MAX_COLLECTION * 2]; - unsigned long patternLen; + unsigned long patternLen = 0; if ((ccode = CheckState(session, STATE_AUTH)) == STATUS_CONTINUE) { if ((ccode = EventsSend(session, STORE_EVENT_ALL)) == STATUS_CONTINUE) { @@ -2274,7 +2255,7 @@ WriteMessageInMailbox(Connection *clientConn, Connection *storeConn, uint64_t fo char buffer[100]; ccode = STATUS_NMAP_COMM_ERROR; - if (NMAPSendCommandF(storeConn, "WRITE %llx %lu %lu T%lu\r\n", folderGuid, STORE_DOCTYPE_MAIL, size, (unsigned long)creationTime) != -1) { + if (NMAPSendCommandF(storeConn, "WRITE %llx %u %lu T%lu\r\n", folderGuid, STORE_DOCTYPE_MAIL, size, (unsigned long)creationTime) != -1) { if ((ccode = CheckForNMAPCommError(NMAPReadResponse(storeConn, NULL, 0, 0))) == 2002) { ccode = STATUS_ABORT; if (ConnWrite(clientConn, "+ Ready for more data\r\n", sizeof("+ Ready for more data\r\n") - 1) != -1) { @@ -2320,7 +2301,7 @@ ImapCommandAppend(void *param) unsigned long messageSize; unsigned long flags; time_t date; - uint64_t messageGuid; + uint64_t messageGuid = 0; if ((ccode = CheckState(session, STATE_AUTH)) == STATUS_CONTINUE) { if ((ccode = EventsSend(session, STORE_EVENT_ALL)) == STATUS_CONTINUE) { @@ -2370,7 +2351,7 @@ ImapCommandCheck(void *param) __inline static long PurgeDeletedMessages(Connection *storeConn, Connection *clientConn, MessageInformation *message, unsigned long messageCount) { - long ccode; + long ccode = 0; long count; count = messageCount; @@ -3159,104 +3140,18 @@ ImapCommandGetQuotaRoot(void *param) int ImapCommandNameSpace(void *param) { -#if defined(HAVE_SHARED_FOLDERS) ImapSession *session = (ImapSession *)param; - long ccode; - if (session->client.state == STATE_SELECTED) { - if (((ccode = PurgeMessageNotify(session)) == STATUS_CONTINUE) && ((ccode = NewMessageNotify(session)) == STATUS_CONTINUE)) { - ; - } else { - return(SendError(session->client.conn, session->command.tag, "NAMESPACE", ccode)); - } - } else if (session->client.state < STATE_AUTH) { + if (session->client.state < STATE_AUTH) { return(SendError(session->client.conn, session->command.tag, "NAMESPACE", STATUS_INVALID_STATE)); } if (ConnWrite(session->client.conn, - "* NAMESPACE ((\"\" \"/\")) ((\"Shares/\" \"/\")) ((\"Public Shares\" \"/\"))\r\n", - strlen("* NAMESPACE ((\"\" \"/\")) ((\"Shares/\" \"/\")) ((\"Public Shares\" \"/\"))\r\n")) != -1) { + "* NAMESPACE ((\"\" \"/\")) NIL NIL\r\n", + strlen("* NAMESPACE ((\"\" \"/\")) NIL NIL\r\n")) != -1) { return(SendOk(session, "NAMESPACE")); } return(STATUS_ABORT); -#else - return(SendError(((ImapSession *)param)->client.conn, ((ImapSession *)param)->command.tag, "SETACL", STATUS_UNKNOWN_COMMAND)); -#endif -} - -/********** non-standard commands **********/ - -int -ImapCommandProxyAuth(void *param) -{ -#if defined(HAVE_SHARED_FOLDERS) - ImapSession *session = (ImapSession *)param; - long ccode; - unsigned char *ptr; - unsigned char *user = NULL; - MDBValueStruct *User; - - if (session->client.state == STATE_SELECTED) { - if (((ccode = PurgeMessageNotify(session)) == STATUS_CONTINUE) && ((ccode = NewMessageNotify(session)) == STATUS_CONTINUE)) { - ; - } else { - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", ccode)); - } - } else if (session->client.state < STATE_AUTH) { - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", STATUS_INVALID_STATE)); - } - - /* One of the consequences of switching users the way we do is that proxyauth - * will only succeed the first time. After that, the user has changed and can - * no longer proxyauth. This is the way Netscape does it, so supposedly its - * correct, although inefficient for the session. */ - if(session->client.state < STATE_AUTH || XplStrCaseCmp(session->user.name, Imap.server.postmaster)) { - LoggerEvent(Imap.logHandle, LOGGER_SUBSYSTEM_UNHANDLED, LOGGER_EVENT_UNHANDLED_REQUEST, LOG_INFO, 0, session->user.name, session->command.buffer, XplHostToLittle(session->client.conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); - return(SendError(session->client.conn, session->command.tag, "", STATUS_UNKNOWN_COMMAND)); - } - ptr = session->command.buffer + 10; - while(IsWhiteSpace(*ptr)) { - ++ptr; - } - - if(!*ptr) { - return(SendError(session->client.conn, session->command.tag, "", STATUS_INVALID_ARGUMENT)); - } - - ccode = GrabArgument(session, &ptr, &user); - if (ccode == STATUS_CONTINUE) { - /* Fixme - this doesn't connect the user to *his/her* nmap server */ - - User = MDBCreateValueStruct(Imap.directory.handle, NULL); - if (MsgFindObject(user, NULL, NULL, NULL, User)) { - if(XplStrCaseCmp(session->user.name, User->Value[0]) != 0) { - if (strlen(User->Value[0]) < sizeof(session->user.name)) { - strcpy(session->user.name, User->Value[0]); - } - } - MemFree(user); - MDBDestroyValueStruct(User); - - session->client.state = STATE_AUTH; - if (NMAPSendCommandF(session->store.conn, "USER %s\r\n", session->user.name) != -1) { - ccode = NMAPReadResponse(session->store.conn, NULL, 0, 0); - if (ccode == 1000) { - return(SendOk(session, "PROXYAUTH")); - } - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", CheckForNMAPCommError(ccode))); - } - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", STATUS_NMAP_COMM_ERROR)); - } - - MDBDestroyValueStruct(User); - MemFree(user); - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", STATUS_USERNAME_NOT_FOUND)); - } - - return(SendError(session->client.conn, session->command.tag, "PROXYAUTH", ccode)); -#else - return(SendError(((ImapSession *)param)->client.conn, ((ImapSession *)param)->command.tag, "SETACL", STATUS_UNKNOWN_COMMAND)); -#endif } static BOOL @@ -3275,7 +3170,7 @@ HandleConnection(void *param) LoggerEvent(Imap.logHandle, LOGGER_SUBSYSTEM_AUTH, LOGGER_EVENT_SSL_CONNECTION, LOG_INFO, 0, NULL, NULL, XplHostToLittle(session->client.conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); } - if ((ConnWriteF(session->client.conn, "* OK %s %s server ready <%ud.%lu@%s>\r\n",Imap.server.hostname, PRODUCT_NAME, XplGetThreadID(),time(NULL),Imap.server.hostname) != -1) && (ConnFlush(session->client.conn) != -1)) { + if ((ConnWriteF(session->client.conn, "* OK %s %s server ready <%ud.%lu@%s>\r\n",BongoGlobals.hostname, PRODUCT_NAME, (unsigned int)XplGetThreadID(),time(NULL),BongoGlobals.hostname) != -1) && (ConnFlush(session->client.conn) != -1)) { while (TRUE) { ccode = ReadCommandLine(session->client.conn, &(session->command.buffer), &(session->command.bufferLen)); if (ccode == STATUS_CONTINUE) { @@ -3472,22 +3367,17 @@ InitializeImapGlobals() Imap.server.disabled = FALSE; Imap.server.port = 143; Imap.server.ssl.port = 993; - Imap.server.ssl.enable = FALSE; + Imap.server.ssl.config.options = 0; + Imap.server.ssl.config.options |= SSL_ALLOW_CHAIN; + Imap.server.ssl.config.options |= SSL_ALLOW_SSL3; Imap.server.threadGroupId = XplGetThreadGroupID(); - Imap.server.hostname[0] = '\0'; - Imap.server.hostnameLen = 0; strcpy(Imap.server.postmaster, "admin"); /* Imap.command. */ Imap.command.capability.acl.enabled = TRUE; -#if defined(HAVE_SHARED_FOLDERS) - Imap.command.capability.len = sprintf(Imap.command.capability.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 ACL AUTH=LOGIN NAMESPACE XSENDER"); - Imap.command.capability.ssl.len = sprintf(Imap.command.capability.ssl.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 ACL AUTH=LOGIN NAMESPACE STARTTLS XSENDER LOGINDISABLED");` -#else - Imap.command.capability.len = sprintf(Imap.command.capability.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN XSENDER"); - Imap.command.capability.ssl.len = sprintf(Imap.command.capability.ssl.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN STARTTLS XSENDER LOGINDISABLED"); - -#endif + /* FIXME: ACL ?? */ + Imap.command.capability.len = sprintf(Imap.command.capability.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN NAMESPACE XSENDER"); + Imap.command.capability.ssl.len = sprintf(Imap.command.capability.ssl.message, "%s\r\n", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN NAMESPACE STARTTLS XSENDER LOGINDISABLED"); Imap.command.months[0] = "Jan"; Imap.command.months[1] = "Feb"; @@ -3505,7 +3395,6 @@ InitializeImapGlobals() /* Imap.(misc). */ Imap.exiting = FALSE; Imap.logHandle = NULL; - Imap.directory.handle = NULL; /* Global allocations */ BongoKeywordIndexCreateFromTable(Imap.command.index, ImapProtocolCommands, .name, TRUE); @@ -3637,12 +3526,6 @@ IMAPServer(void *unused) ConnClose(Imap.server.ssl.conn, 1); } - /* Management Client Shutdown */ - ManagementShutdown(); - for (j = 0; (ManagementState() != MANAGEMENT_STOPPED) && (j < 60); j++) { - XplDelay(1000); - } - /* Wake up the children and set them free! */ /* fixme - SocketShutdown; */ @@ -3672,13 +3555,11 @@ IMAPServer(void *unused) if (Imap.server.ssl.context) { ConnSSLContextFree(Imap.server.ssl.context); } - XPLCryptoLockDestroy(); LoggerClose(Imap.logHandle); Imap.logHandle = NULL; MsgShutdown(); -// MDBShutdown(); CONN_TRACE_SHUTDOWN(); ConnShutdown(); @@ -3812,12 +3693,16 @@ IMAPSSLServer(void *unused) return; } +static BongoConfigItem IMAPConfig[] = { + { BONGO_JSON_INT, "o:port/i", &Imap.server.port }, + { BONGO_JSON_INT, "o:port_ssl/i", &Imap.server.ssl.port }, + { BONGO_JSON_INT, "o:threads_max/i", &Imap.session.threads.max }, + { BONGO_JSON_NULL, NULL, NULL } +}; static BOOL ReadConfiguration(void) { - MDBValueStruct *Config; - unsigned char *ptr; time_t gm_time_of_day, time_of_day; struct tm gm, ltm; @@ -3828,78 +3713,14 @@ ReadConfiguration(void) localtime_r(&time_of_day, <m); gm_time_of_day=mktime(&gm); - Config = MDBCreateValueStruct(Imap.directory.handle, MsgGetServerDN(NULL)); + // Imap.server.postmaster needs to be set to something? + if (! ReadBongoConfiguration(IMAPConfig, "imap")) { + return FALSE; + } - if (MDBRead(MSGSRV_AGENT_IMAP, MSGSRV_A_PORT, Config)>0) { - Imap.server.port = (unsigned short)atol(Config->Value[0]); + if (! ReadBongoConfiguration(GlobalConfig, "global")) { + return FALSE; } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_IMAP, MSGSRV_A_SSL_PORT, Config)>0) { - Imap.server.ssl.port = (unsigned short)atol(Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_IMAP, MSGSRV_A_MAX_LOAD, Config)>0) { - Imap.session.threads.max=atol(Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_IMAP, MSGSRV_A_ACL_ENABLED, Config)>0) { - if (atol(Config->Value[0])) { - Imap.command.capability.acl.enabled = TRUE; - } else { - Imap.command.capability.acl.enabled = FALSE; - Imap.command.capability.len = - sprintf(Imap.command.capability.message, - "%s\r\n", - "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN NAMESPACE XSENDER"); - Imap.command.capability.ssl.len = - sprintf(Imap.command.capability.ssl.message, - "%s\r\n", - "* CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN NAMESPACE STARTTLS XSENDER LOGINDISABLED"); - } - } - MDBFreeValues(Config); - - Imap.server.ssl.config.options = 0; - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_SSL_ALLOW_CHAINED, Config)) { - if (atol(Config->Value[0])) { - Imap.server.ssl.config.options |= SSL_ALLOW_CHAIN; - } - } - MDBFreeValues(Config); - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_SSL_TLS, Config)) { - if (atol(Config->Value[0])) { - Imap.server.ssl.config.options |= SSL_ALLOW_SSL3; - Imap.server.ssl.enable = TRUE; - } - } - MDBFreeValues(Config); - - if (MDBRead(MSGSRV_SELECTED_CONTEXT, MSGSRV_A_OFFICIAL_NAME, Config)) { - if ((Config->Value[0]) && (strlen(Config->Value[0]) < sizeof(Imap.server.hostname))) { - - strcpy(Imap.server.hostname, Config->Value[0]); - } else { - gethostname(Imap.server.hostname, sizeof(Imap.server.hostname)); - } - - } else { - gethostname(Imap.server.hostname, sizeof(Imap.server.hostname)); - } - Imap.server.hostnameLen = strlen(Imap.server.hostname); - MDBFreeValues(Config); - - if (MDBRead(MSGSRV_SELECTED_CONTEXT, MSGSRV_A_POSTMASTER, Config)) { - ptr=strchr(Config->Value[0], '.'); - if (ptr) { - *ptr='\0'; - } - if (strlen(Config->Value[0]) < sizeof(Imap.server.postmaster)) { - strcpy(Imap.server.postmaster, Config->Value[0]); - } - } - MDBFreeValues(Config); - - MDBDestroyValueStruct(Config); return(TRUE); } @@ -3941,20 +3762,9 @@ XplServiceMain(int argc, char *argv[]) ConnStartup(IMAP_CONNECTION_TIMEOUT, TRUE); - MDBInit(); - Imap.directory.handle = (MDBHandle)MsgInit(); - if (Imap.directory.handle == NULL) { - XplBell(); - XplConsolePrintf("\rIMAPD: Invalid directory credentials; exiting!\n"); - XplBell(); - - MemoryManagerClose(MSGSRV_AGENT_IMAP); - - return(-1); - } - - NMAPInitialize(Imap.directory.handle); - CMInitialize(Imap.directory.handle, "IMAP"); + MsgInit(); + MsgAuthInit(); + NMAPInitialize(); Imap.logHandle = LoggerOpen("bongoimap"); if (Imap.logHandle != NULL) { @@ -3972,21 +3782,15 @@ XplServiceMain(int argc, char *argv[]) return -1; } - if (Imap.server.ssl.enable) { - if (!ServerSocketSSLInit()) { + if (!ServerSocketSSLInit()) { + Imap.server.ssl.config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + Imap.server.ssl.config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); + + Imap.server.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - Imap.server.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); - Imap.server.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - Imap.server.ssl.config.key.file = MsgGetTLSKeyPath(NULL); - - Imap.server.ssl.context = ConnSSLContextAlloc(&(Imap.server.ssl.config)); - if (Imap.server.ssl.context) { - XplBeginCountedThread(&id, IMAPSSLServer, IMAP_STACK_SIZE, NULL, ccode, Imap.server.active); - } else { - Imap.server.ssl.enable = FALSE; - } - } else { - Imap.server.ssl.enable = FALSE; + Imap.server.ssl.context = ConnSSLContextAlloc(&(Imap.server.ssl.config)); + if (Imap.server.ssl.context) { + XplBeginCountedThread(&id, IMAPSSLServer, IMAP_STACK_SIZE, NULL, ccode, Imap.server.active); } } diff --git a/src/agents/imap/imapd.h b/src/agents/imap/imapd.h index ca6d311..9168d12 100755 --- a/src/agents/imap/imapd.h +++ b/src/agents/imap/imapd.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -195,16 +196,6 @@ static ImapErrorString ImapErrorStrings[] = { #define IMAP_COMMAND_PROXYAUTH "PROXYAUTH" /* depricated - should use SASL */ #define IMAP_HELP_NOT_DEFINED "%s - HELP not defined.\r\n" -#if MDB_DEBUG -/* directory test commands */ -#define IMAP_COMMAND_USER_LOOKUP "USER LOOKUP" -#define IMAP_COMMAND_USER_VERIFY "USER VERIFY" -#define IMAP_COMMAND_USER_READ "USER READ" -#define IMAP_COMMAND_USER_WRITE_LOCAL "USER WRITE LOCAL" -#define IMAP_COMMAND_USER_WRITE_SUPER "USER WRITE SUPER" -#define IMAP_COMMAND_USER_ENUM "USER ENUM" -#endif - /* Internal stuff */ #define CR 0x0d #define LF 0x0a @@ -313,7 +304,6 @@ typedef struct { struct { char *name; /* login name */ - char dn[MDB_MAX_OBJECT_CHARS + 1]; /* distinguished name */ } user; FolderListInformation folder; @@ -350,10 +340,6 @@ typedef struct { } store; } command; - struct { - MDBHandle handle; - } directory; - struct { struct { XplAtomic inUse; @@ -367,8 +353,6 @@ typedef struct { struct { struct { - BOOL enable; - ConnSSLConfiguration config; bongo_ssl_context *context; @@ -384,8 +368,6 @@ typedef struct { struct sockaddr_in addr; - char hostname[256]; - unsigned long hostnameLen; unsigned short port; int threadGroupId; BOOL disabled; @@ -465,13 +447,5 @@ int ImapCommandSetQuota(void *param); int ImapCommandGetQuota(void *param); int ImapCommandGetQuotaRoot(void *param); int ImapCommandNameSpace(void *param); -int ImapCommandProxyAuth(void *param); -#if MDB_DEBUG -int ImapCommandUserLookup(void *param); -int ImapCommandUserVerify(void *param); -int ImapCommandUserRead(void *param); -int ImapCommandUserWriteLocal(void *param); -int ImapCommandUserWriteSuper(void *param); -int ImapCommandUserEnum(void *param); -#endif + #include "inline.h" diff --git a/src/agents/imap/search.c b/src/agents/imap/search.c index 2b6b106..5793ce3 100644 --- a/src/agents/imap/search.c +++ b/src/agents/imap/search.c @@ -251,7 +251,6 @@ ImapDateArgToUtc(char *dateText, unsigned long *dateUtc) char *monthPtr; char *yearPtr; unsigned long month; - long year; dayPtr = dateText; monthPtr = strchr(dateText, '-'); @@ -289,12 +288,12 @@ __inline static long GetMessageSentDate(ImapSession *session, uint64_t guid, unsigned long headerLen, time_t *dateUtc) { long ccode; - unsigned long len; + size_t len; char *dateString; if ((ccode = NMAPSendCommandF(session->store.conn, "READ %llx 0 %lu\r\n", guid, headerLen)) != -1) { if ((ccode = NMAPReadPropertyValueLength(session->store.conn, "nmap.document", &len)) == 2001) { - if ((dateString = BongoStreamGrabRfc822Header(ReadSourceConn, session->store.conn, len, "Date")) != NULL) { + if ((dateString = BongoStreamGrabRfc822Header(ReadSourceConn, session->store.conn, (unsigned long)len, "Date")) != NULL) { if (NMAPReadCrLf(session->store.conn) == 2) { *dateUtc = MsgParseRFC822Date(dateString); MemFree(dateString); @@ -481,7 +480,7 @@ SearchRemainingMatchSentBefore(ImapSession *session, MessageInformation *message { long ccode; time_t date = *(unsigned long *)arg2; - time_t messageDateUtc; + time_t messageDateUtc = 0; if ((ccode = GetMessageSentDate(session, message->guid, message->headerSize, &messageDateUtc)) == STATUS_CONTINUE) { *found = (messageDateUtc < date); @@ -495,7 +494,7 @@ SearchRemainingMatchSentOn(ImapSession *session, MessageInformation *message, ch { long ccode; time_t date = *(unsigned long *)arg2; - time_t messageDateUtc; + time_t messageDateUtc = 0; if ((ccode = GetMessageSentDate(session, message->guid, message->headerSize, &messageDateUtc)) == STATUS_CONTINUE) { *found = ((messageDateUtc >= date) && (messageDateUtc < date + (60 * 60 * 24))); @@ -509,7 +508,7 @@ SearchRemainingMatchSentSince(ImapSession *session, MessageInformation *message, { long ccode; time_t date = *(unsigned long *)arg2; - time_t messageDateUtc; + time_t messageDateUtc = 0; if ((ccode = GetMessageSentDate(session, message->guid, message->headerSize, &messageDateUtc)) == STATUS_CONTINUE) { *found = (messageDateUtc >= date); @@ -1083,11 +1082,11 @@ SearchHandleTopKey(ImapSession *session, char **keyString, SearchKey *key) __inline static long SearchSendResults(ImapSession *session, long *matches, BOOL byUid) { - MessageInformation *message; + MessageInformation *message = NULL; if (byUid) { message = &session->folder.selected.message[0]; } else { - + // FIXME - What should we do here? } if (ConnWrite(session->client.conn, "* SEARCH", strlen("* SEARCH")) != -1) { @@ -1096,7 +1095,7 @@ SearchSendResults(ImapSession *session, long *matches, BOOL byUid) for (;;) { if (matches[i] != -1) { if (byUid) { - if (ConnWriteF(session->client.conn, " %lu", message[matches[i]].uid) != -1) { + if (ConnWriteF(session->client.conn, " %lu", (unsigned long)message[matches[i]].uid) != -1) { i++; continue; } diff --git a/src/agents/imap/session.c b/src/agents/imap/session.c index 689646d..d9685a7 100644 --- a/src/agents/imap/session.c +++ b/src/agents/imap/session.c @@ -25,61 +25,22 @@ #include -#include #include -/* Management Client Header Include */ -#include - -#include #include "imapd.h" static long UserAuthenticate(ImapSession *session, unsigned char **userName, unsigned char *password, struct sockaddr_in *storeAddress) { - MDBValueStruct *user; - char *tmpName; - - user = MDBCreateValueStruct(Imap.directory.handle, NULL); - if (user) { - if (MsgFindObject(*userName, session->user.dn, NULL, storeAddress, user)) { - if (MsgGetUserFeature(session->user.dn, FEATURE_IMAP, NULL, NULL)) { - if (!password || MDBVerifyPassword(session->user.dn, password, user)) { - - if (strcmp(*userName, user->Value[0]) == 0) { - MDBDestroyValueStruct(user); - return(STATUS_CONTINUE); - } - - tmpName = MemStrdup(user->Value[0]); - MDBDestroyValueStruct(user); - if (tmpName) { - MemFree(*userName); - *userName = tmpName; - return(STATUS_CONTINUE); - } - return(STATUS_MEMORY_ERROR); - } - - LoggerEvent(Imap.logHandle, LOGGER_SUBSYSTEM_AUTH, LOGGER_EVENT_WRONG_PASSWORD, LOG_NOTICE, - 0, *userName, password, XplHostToLittle(session->client.conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); - MDBDestroyValueStruct(user); - return(STATUS_WRONG_PASSWORD); - } - - LoggerEvent(Imap.logHandle, LOGGER_SUBSYSTEM_AUTH, LOGGER_EVENT_DISABLED_FEATURE, LOG_NOTICE, - 0, *userName, NULL, XplHostToLittle(session->client.conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); - MDBDestroyValueStruct(user); - return(STATUS_FEATURE_DISABLED); - } - - LoggerEvent(Imap.logHandle, LOGGER_SUBSYSTEM_AUTH, LOGGER_EVENT_UNKNOWN_USER, LOG_NOTICE, - 0, *userName, password, XplHostToLittle(session->client.conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); - MDBDestroyValueStruct(user); + if (MsgAuthFindUser(*userName) != 0) return(STATUS_USERNAME_NOT_FOUND); - } - return(STATUS_IDENTITY_STORE_FAILURE); + + if (MsgAuthVerifyPassword(*userName, password) != 0) + return(STATUS_WRONG_PASSWORD); + + MsgAuthGetUserStore(*userName, storeAddress); + return(STATUS_CONTINUE); } __inline static long @@ -240,8 +201,8 @@ ImapCommandAuthenticate(void *param) { ImapSession *session = (ImapSession *)param; long ccode; - unsigned char *username; - unsigned char *password; + unsigned char *username = NULL; + unsigned char *password = NULL; if (session->client.state == STATE_FRESH) { if (XplStrNCaseCmp(session->command.buffer + 13, "LOGIN", 5) == 0) { @@ -258,7 +219,6 @@ ImapCommandAuthenticate(void *param) /* We are flushing here so that we can update the connection manager */ /* while the client is working on the response and sending the next command */ if (ConnFlush(session->client.conn) != -1) { -// Reenable me CMAuthenticated((unsigned long)session->client.conn->socketAddress.sin_addr.s_addr, session->user.name); return(STATUS_CONTINUE); } } @@ -296,7 +256,6 @@ ImapCommandLogin(void *param) /* We are flushing here so that we can update the connection manager */ /* while the client is working on the response and sending the next command */ if (ConnFlush(session->client.conn) != -1) { -// Reenable me CMAuthenticated((unsigned long)session->client.conn->socketAddress.sin_addr.s_addr, session->user.name); return(STATUS_CONTINUE); } else { ccode = STATUS_ABORT; @@ -340,144 +299,3 @@ ImapCommandStartTls(void *param) } - -#if MDB_DEBUG -/********** Mdb test commands - any state (User Lookup, User Verify, UserRead) **********/ -int -ImapCommandUserLookup(void *param) -{ - MDBValueStruct *user; - ImapSession *session = (ImapSession *)param; - char *username; - struct sockaddr_in storeAddress; - - if ((user = MDBCreateValueStruct(Imap.directory.handle, NULL)) != NULL) { - username = session->command.buffer + strlen("USER LOOKUP"); - if (*username == ' ') { - username++; - if (MsgFindObject(username, session->user.dn, NULL, &storeAddress, user)) { - if (ConnWriteF(session->client.conn, "* %s\r\n", session->user.dn) == -1) { - MDBDestroyValueStruct(user); - return(STATUS_ABORT); - } - } - MDBDestroyValueStruct(user); - return(SendOk(session, "USER LOOKUP")); - } - MDBDestroyValueStruct(user); - return(SendError(session->client.conn, session->command.tag, "USER LOOKUP", STATUS_INVALID_ARGUMENT)); - } - return(SendError(session->client.conn, session->command.tag, "USER LOOKUP", STATUS_IDENTITY_STORE_FAILURE)); -} - -int -ImapCommandUserVerify(void *param) -{ - MDBValueStruct *user; - ImapSession *session = (ImapSession *)param; - unsigned char *userDn; - unsigned char *password; - char *spacePtr; - - userDn = session->command.buffer + strlen("USER VERIFY"); - if (*userDn == ' ') { - userDn++; - spacePtr = strchr(userDn, ' '); - if (spacePtr) { - password = spacePtr + 1; - if ((user = MDBCreateValueStruct(Imap.directory.handle, NULL)) != NULL) { - *spacePtr = '\0'; - if (MDBVerifyPassword(userDn, password, user)) { - *spacePtr = ' '; - MDBDestroyValueStruct(user); - return(SendOk(session, "USER VERIFY")); - } - *spacePtr = ' '; - MDBDestroyValueStruct(user); - return(SendError(session->client.conn, session->command.tag, "USER VERIFY", STATUS_USERNAME_NOT_FOUND)); - } - return(SendError(session->client.conn, session->command.tag, "USER VERIFY", STATUS_IDENTITY_STORE_FAILURE)); - } - } - return(SendError(session->client.conn, session->command.tag, "USER VERIFY", STATUS_INVALID_ARGUMENT)); -} - -int -ImapCommandUserRead(void *param) -{ - MDBValueStruct *user; - ImapSession *session = (ImapSession *)param; - unsigned char *userDn; - unsigned char *attribute; - char *spacePtr; - unsigned long i; - - userDn = session->command.buffer + strlen("USER READ"); - if (*userDn == ' ') { - userDn++; - spacePtr = strchr(userDn, ' '); - if (spacePtr) { - attribute = spacePtr + 1; - if ((user = MDBCreateValueStruct(Imap.directory.handle, NULL)) != NULL) { - *spacePtr = '\0'; - MsgGetUserSetting(userDn, attribute, user); - for(i = 0; i < user->Used; i++) { - if (ConnWriteF(session->client.conn, "* %s\r\n", user->Value[i]) == -1) { - *spacePtr = ' '; - MDBDestroyValueStruct(user); - return(STATUS_ABORT); - } - } - *spacePtr = ' '; - MDBDestroyValueStruct(user); - return(SendOk(session, "USER READ")); - } - return(SendError(session->client.conn, session->command.tag, "USER READ", STATUS_IDENTITY_STORE_FAILURE)); - } - } - return(SendError(session->client.conn, session->command.tag, "USER READ", STATUS_INVALID_ARGUMENT)); -} - -int -ImapCommandUserWriteLocal(void *param) -{ - long ccode; - ImapSession *session = (ImapSession *)param; - unsigned char *userDn; - unsigned char *attribute; - unsigned long count; - unsigned long i; - unsigned char *ptr; - - ptr = session->command.buffer + strlen("USER WRITE LOCAL"); - if ((ccode = GrabArgument(session, &ptr, &userDn)) == STATUS_CONTINUE) { - if ((ccode = GrabArgument(session, &ptr, &attribute)) == STATUS_CONTINUE) { - if (*ptr == ' ') { - count = atol(ptr + 1); - ccode = STATUS_IDENTITY_STORE_FAILURE; - - - - - } - MemFree(attribute); - } - MemFree(userDn); - } - return(SendError(session->client.conn, session->command.tag, "USER WRITE LOCAL", ccode)); -} - -int -ImapCommandUserWriteSuper(void *param) -{ - return(STATUS_UNKNOWN_COMMAND); -} - -int -ImapCommandUserEnum(void *param) -{ - return(STATUS_UNKNOWN_COMMAND); -} - -#endif - diff --git a/src/agents/imap/uid.c b/src/agents/imap/uid.c index b97953d..e10f034 100644 --- a/src/agents/imap/uid.c +++ b/src/agents/imap/uid.c @@ -1,4 +1,3 @@ - /**************************************************************************** * * Copyright (c) 2001 Novell, Inc. All Rights Reserved. @@ -26,11 +25,8 @@ #include -#include #include -/* Management Client Header Include */ -#include #include "imapd.h" #define GREATER_THAN_OR_EQUAL_TO 1 diff --git a/src/agents/itip/Bongo.rules b/src/agents/itip/Bongo.rules index a9acd93..ca0e625 100644 --- a/src/agents/itip/Bongo.rules +++ b/src/agents/itip/Bongo.rules @@ -1,15 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoitip -bongoitip_SOURCES := \ +bongoitip_SOURCES = \ src/agents/itip/itip.c \ src/agents/itip/itip.h -bongoitip_LDADD := \ +bongoitip_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/itip/itip.c b/src/agents/itip/itip.c index f22605f..bff28ef 100644 --- a/src/agents/itip/itip.c +++ b/src/agents/itip/itip.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -394,18 +393,6 @@ ItipAgentServer(void *ignored) static BOOL ReadConfiguration(void) { - MDBValueStruct *config; - - config = MDBCreateValueStruct(ItipAgent.agent.directoryHandle, - MsgGetServerDN(NULL)); - if (config) { - /* Read your agent's configuration here */ - } else { - return FALSE; - } - - MDBDestroyValueStruct(config); - return TRUE; } @@ -435,14 +422,14 @@ XplServiceMain(int argc, char *argv[]) strcpy(ItipAgent.nmapAddress, "127.0.0.1"); /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO | BA_STARTUP_NMAP; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_NMAP; ccode = BongoAgentInit(&ItipAgent.agent, AGENT_NAME, AGENT_DN, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); return -1; } - BongoCalInit(MsgGetDBFDir(NULL)); + BongoCalInit(MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); /* Set up socket for listening on an incoming queue */ ItipAgent.queueNumber = Q_FIVE; diff --git a/src/agents/itip/itip.h b/src/agents/itip/itip.h index e151883..6a8141e 100644 --- a/src/agents/itip/itip.h +++ b/src/agents/itip/itip.h @@ -23,8 +23,6 @@ #define _ITIP_H #include -#include -#include #include #include #include @@ -56,8 +54,4 @@ typedef struct _ItipAgentGlobals { extern ItipAgentGlobals ItipAgent; -/* management.c */ -int ItipAgentManagementStart(void); -void ItipAgentManagementShutdown(void); - #endif /* _ITIP_H */ diff --git a/src/agents/mailprox/Bongo.rules b/src/agents/mailprox/Bongo.rules index caf2100..f721615 100644 --- a/src/agents/mailprox/Bongo.rules +++ b/src/agents/mailprox/Bongo.rules @@ -1,17 +1,15 @@ # -*- Makefile -*- sbin_PROGRAMS += bongomailprox -bongomailprox_SOURCES := \ +bongomailprox_SOURCES = \ src/agents/mailprox/imap.c \ src/agents/mailprox/mailprox.c \ src/agents/mailprox/mailprox.h \ src/agents/mailprox/pop.c -bongomailprox_LDADD := \ +bongomailprox_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/mailprox/imap.c b/src/agents/mailprox/imap.c index bea6bda..1adf2b4 100644 --- a/src/agents/mailprox/imap.c +++ b/src/agents/mailprox/imap.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "mailprox.h" diff --git a/src/agents/mailprox/mailprox.c b/src/agents/mailprox/mailprox.c index d7ba53c..c8f134c 100644 --- a/src/agents/mailprox/mailprox.c +++ b/src/agents/mailprox/mailprox.c @@ -21,11 +21,14 @@ #include +#define LOGGERNAME "mailprox" + #include #include #include #include #include +#include #include "mailprox.h" @@ -526,7 +529,8 @@ ProxyUser(MailProxyClient *client) } if (update) { - MsgSetUserSetting(client->q->user, MSGSRV_A_PROXY_LIST, accounts); + // FIXME + // MsgSetUserSetting(client->q->user, MSGSRV_A_PROXY_LIST, accounts); } MDBDestroyValueStruct(accounts); @@ -663,10 +667,13 @@ ProxyServer(void *ignored) accounts = MDBShareContext(MailProxy.contexts); } - if ((MsgGetUserSetting(user, MSGSRV_A_MESSAGING_DISABLED, accounts) == 0) || (accounts->Value[accounts->Used - 1][0] != '1')) { + // FIXME + // if ((MsgGetUserSetting(user, MSGSRV_A_MESSAGING_DISABLED, accounts) == 0) || (accounts->Value[accounts->Used - 1][0] != '1')) { + if (accounts->Value[accounts->Used - 1][0] != '1') { MDBFreeValues(accounts); - if (MsgGetUserFeature(user, FEATURE_PROXY, MSGSRV_A_PROXY_LIST, accounts)) { + // FIXME + // if (MsgGetUserFeature(user, FEATURE_PROXY, MSGSRV_A_PROXY_LIST, accounts)) { ptr = strrchr(user, '\\'); if (ptr) { strcpy(queue->user, ptr + 1); @@ -694,7 +701,7 @@ ProxyServer(void *ignored) } LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, queue->user, sizeof(MailProxyClient), __LINE__, NULL, 0); - } + // } if (accounts) { MDBFreeValues(accounts); @@ -733,18 +740,10 @@ ProxyServer(void *ignored) ConnCloseAll(1); - if (ManagementState() == MANAGEMENT_RUNNING) { - ManagementShutdown(); - } - for (i = 0; (XplSafeRead(MailProxy.server.active) > 1) && (i < 60); i++) { XplDelay(1000); } - for (i = 0; (ManagementState() != MANAGEMENT_STOPPED) && (i < 60); i++) { - XplDelay(1000); - } - XplWaitOnLocalSemaphore(MailProxy.client.semaphore); ccode = XplSafeRead(MailProxy.client.worker.idle); @@ -818,162 +817,26 @@ ProxyServer(void *ignored) return(0); } -static void -ProxyConfigMonitor(void) -{ - int i; - MDBValueStruct *Config; - long PrevConfigNumber; - - XplRenameThread(XplGetThreadID(), "Proxy Config Monitor"); - - Config = MDBCreateValueStruct(MailProxy.handle.directory, MsgGetServerDN(NULL)); - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_CONFIG_CHANGED, Config)>0) { - PrevConfigNumber = atol(Config->Value[0]); - } else { - PrevConfigNumber = 0; - } - MDBDestroyValueStruct(Config); - - while (MailProxy.state == MAILPROXY_STATE_RUNNING) { - LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_PROXY_HEARTBEAT, LOG_INFO, 0, NULL, NULL, 0, 0, NULL, 0); - - for (i = 0; (i < 300) && (MailProxy.state == MAILPROXY_STATE_RUNNING); i++) { - XplDelay(1000); - } - - if (MailProxy.state == MAILPROXY_STATE_RUNNING) { - Config = MDBCreateValueStruct(MailProxy.handle.directory, MsgGetServerDN(NULL)); - if ((MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_CONFIG_CHANGED, Config)>0) && (atol(Config->Value[0]) != PrevConfigNumber)) { - /* Clear what we just read */ - PrevConfigNumber=atol(Config->Value[0]); - MDBFreeValues(Config); - - /* Acquire Write Lock */ - XplRWWriteLockAcquire(&MailProxy.lock); - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_TIME_INTERVAL, Config) > 0) { - MailProxy.runInterval = atol(Config->Value[0]) * 3600; /* Convert hours to seconds */ - if ((MailProxy.runInterval == 0) && (toupper(Config->Value[0][0])=='S')) { - MailProxy.runInterval = atol(Config->Value[0]+1); - } - } - if (MailProxy.runInterval == 0) { - MailProxy.runInterval = 3600 * 3; - } - MDBFreeValues(Config); - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_THREAD_LIMIT, Config) > 0) { - MailProxy.max.threadsParallel = atol(Config->Value[0]); - } - MDBFreeValues(Config); - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_MAXIMUM_ITEMS, Config) > 0) { - MailProxy.max.accounts = atol(Config->Value[0]); - } - MDBFreeValues(Config); - - /* Release Write Lock */ - XplRWWriteLockRelease(&MailProxy.lock); - } - - MDBDestroyValueStruct(Config); - } - } - -#if VERBOSE - XplConsolePrintf("\rMAILPROX: Config monitor thread done.\r\n"); -#endif - - XplSafeDecrement(MailProxy.server.active); - - XplExitThread(TSR_THREAD, 0); -} +// MailProxy.contexts +static BongoConfigItem ProxyConfig[] = { + { BONGO_JSON_STRING, "o:postmaster/s", &MailProxy.postmaster }, + { BONGO_JSON_INT, "o:interval/i", &MailProxy.runInterval }, // in seconds + { BONGO_JSON_INT, "o:max_threads/i", &MailProxy.max.threadsParallel }, + { BONGO_JSON_INT, "o:max_accounts/i", &MailProxy.max.accounts }, + { BONGO_JSON_STRING, "o:queue/s", &MailProxy.nmap.address }, + { BONGO_JSON_NULL, NULL, NULL } +}; static BOOL ReadConfiguration(void) { - unsigned long used; - unsigned char *ptr; - MDBValueStruct *vs; + if (! MsgGetServerCredential(MailProxy.nmap.hash)) + return FALSE; - vs = MDBCreateValueStruct(MailProxy.handle.directory, MsgGetServerDN(NULL)); - if (vs) { - if (MDBRead(MSGSRV_SELECTED_CONTEXT, MSGSRV_A_POSTMASTER, vs) > 0) { - ptr = strrchr(vs->Value[0], '\\'); - if (ptr) { - strcpy(MailProxy.postmaster, ptr + 1); - } else { - strcpy(MailProxy.postmaster, vs->Value[0]); - } + if (! ReadBongoConfiguration(ProxyConfig, "mailproxy")) + return FALSE; - MDBFreeValues(vs); - } else { - strcpy(MailProxy.postmaster, "admin"); - } - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_TIME_INTERVAL, vs) > 0) { - /* Convert hours to seconds */ - MailProxy.runInterval = atol(vs->Value[0]) * 3600; - if (!MailProxy.runInterval && (toupper(vs->Value[0][0]) == 'S')) { - MailProxy.runInterval = atol(vs->Value[0] + 1); - } - - MDBFreeValues(vs); - } - - if (!MailProxy.runInterval) { - MailProxy.runInterval = 3600 * 3; - } - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_THREAD_LIMIT, vs) > 0) { - MailProxy.max.threadsParallel = atol(vs->Value[0]); - - MDBFreeValues(vs); - } - - if (MDBRead(MSGSRV_AGENT_PROXY, MSGSRV_A_MAXIMUM_ITEMS, vs) > 0) { - MailProxy.max.accounts = atol(vs->Value[0]); - - MDBFreeValues(vs); - } - - if (MDBReadDN(MSGSRV_AGENT_PROXY, MSGSRV_A_STORE_SERVER, vs) > 0) { - MailProxy.contexts = MDBCreateValueStruct(MailProxy.handle.directory, NULL); - for (used = 0; used < vs->Used; used++) { - ptr = strrchr(vs->Value[used], '\\'); - if (ptr) { - *ptr = '\0'; - } - - MDBReadDN(vs->Value[used], MSGSRV_A_CONTEXT, MailProxy.contexts); - } - - MDBFreeValues(vs); - } else { - MDBDestroyValueStruct(vs); - return(FALSE); - } - - if (MsgReadIP(MSGSRV_AGENT_PROXY, MSGSRV_A_QUEUE_SERVER, vs)) { - strcpy(MailProxy.nmap.address, vs->Value[0]); - - LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_QUEUE_SERVER", vs->Value[0], 0, 0, NULL, 0); - } - - MDBFreeValues(vs); - - MDBSetValueStructContext(NULL, vs); - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, vs)>0) { - HashCredential(MsgGetServerDN(NULL), vs->Value[0], MailProxy.nmap.hash); - } - - MDBDestroyValueStruct(vs); - - return(TRUE); - } - - return(FALSE); + return(TRUE); } XplServiceCode(SignalHandler) @@ -1035,7 +898,7 @@ XplServiceMain(int argc, char *argv[]) return(-1); } - NMAPInitialize(MailProxy.handle.directory); + NMAPInitialize(); MailProxy.handle.logging = LoggerOpen("bongomailprox"); if (MailProxy.handle.logging == NULL) { @@ -1044,6 +907,7 @@ XplServiceMain(int argc, char *argv[]) XplRWLockInit(&MailProxy.lock); + MailProxy.state = MAILPROXY_STATE_STOPPING; if (ReadConfiguration()) { CONN_TRACE_INIT((char *)MsgGetWorkDir(NULL), "mailprox"); // CONN_TRACE_SET_FLAGS(CONN_TRACE_ALL); /* uncomment this line and pass '--enable-conntrace' to autogen to get the agent to trace all connections */ @@ -1059,19 +923,12 @@ XplServiceMain(int argc, char *argv[]) NMAPSetEncryption(MailProxy.client.ssl.context); - if (XplSetRealUser(MsgGetUnprivilegedUser()) >= 0) { - XplBeginCountedThread(&id, ProxyConfigMonitor, 128 * 1024, NULL, ccode, MailProxy.server.active); - - MailProxy.state = MAILPROXY_STATE_RUNNING; - } else { + if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { XplConsolePrintf("bongocalendar: Could not drop to unprivileged user '%s', exiting.\r\n", MsgGetUnprivilegedUser()); - - MailProxy.state = MAILPROXY_STATE_STOPPING; + } else { + MailProxy.state = MAILPROXY_STATE_RUNNING; } - } else { - MailProxy.state = MAILPROXY_STATE_STOPPING; - LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NOT_CONFIGURED, LOG_ERROR, 0, "Proxy NMAP Servers", NULL, 0, 0, NULL, 0); } diff --git a/src/agents/mailprox/mailprox.h b/src/agents/mailprox/mailprox.h index e01b4f4..5b12786 100644 --- a/src/agents/mailprox/mailprox.h +++ b/src/agents/mailprox/mailprox.h @@ -23,10 +23,8 @@ #define _MAILPROX_H #include -#include #include #include -#include #define PRODUCT_SHORT_NAME "mailprox.nlm" @@ -251,12 +249,6 @@ void FreeFolderList(IMAPFolderPath *folder); ProxyUID *GetProxyUID(ProxyAccount *proxy, const unsigned char *folderPath); unsigned long ProxyIMAPAccount(MailProxyClient *client, ProxyAccount *account); -/* management.c */ -ManagementVariables *GetMailProxyManagementVariables(void); -int GetMailProxyManagementVariablesCount(void); -ManagementCommands *GetMailProxyManagementCommands(void); -int GetMailProxyManagementCommandsCount(void); - /* pop.c */ unsigned long ProxyPOP3Account(MailProxyClient *client, ProxyAccount *account); diff --git a/src/agents/mailprox/pop.c b/src/agents/mailprox/pop.c index 6d34ebb..7354109 100644 --- a/src/agents/mailprox/pop.c +++ b/src/agents/mailprox/pop.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "mailprox.h" diff --git a/src/agents/pluspack/Bongo.rules b/src/agents/pluspack/Bongo.rules index 62fcbdf..37d37b6 100644 --- a/src/agents/pluspack/Bongo.rules +++ b/src/agents/pluspack/Bongo.rules @@ -1,15 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongopluspack -bongopluspack_SOURCES := \ +bongopluspack_SOURCES = \ src/agents/pluspack/pluspack.c \ src/agents/pluspack/pluspack.h -bongopluspack_LDADD := \ +bongopluspack_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/pluspack/pluspack.c b/src/agents/pluspack/pluspack.c index 2a6274c..6aa5388 100644 --- a/src/agents/pluspack/pluspack.c +++ b/src/agents/pluspack/pluspack.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1306,18 +1305,10 @@ PlusPackQueueServer6(void *ignored) ConnCloseAll(1); - if (ManagementState() == MANAGEMENT_RUNNING) { - ManagementShutdown(); - } - for (i = 0; (XplSafeRead(PlusPack.server.active) > 1) && (i < 60); i++) { XplDelay(1000); } - for (i = 0; (ManagementState() != MANAGEMENT_STOPPED) && (i < 60); i++) { - XplDelay(1000); - } - XplConsolePrintf("bongopluspack: Shutting down %d queue threads\r\n", XplSafeRead(PlusPack.nmap.queue.active)); XplWaitOnLocalSemaphore(PlusPack.nmap.semaphore); @@ -1592,8 +1583,8 @@ QueueSocketInit(void) return(-1); } - if ((NMAPRegister(PLUSPACK_AGENT, Q_FIVE, PlusPack.nmap.conn.queue5->socketAddress.sin_port) != REGISTRATION_COMPLETED) - || (NMAPRegister(PLUSPACK_AGENT, Q_DELIVER, PlusPack.nmap.conn.queue6->socketAddress.sin_port) != REGISTRATION_COMPLETED)) { + if ((QueueRegister(PLUSPACK_AGENT, Q_FIVE, PlusPack.nmap.conn.queue5->socketAddress.sin_port) != REGISTRATION_COMPLETED) + || (QueueRegister(PLUSPACK_AGENT, Q_DELIVER, PlusPack.nmap.conn.queue6->socketAddress.sin_port) != REGISTRATION_COMPLETED)) { XplConsolePrintf("bongopluspack: Could not register with bongonmap\r\n"); if (PlusPack.nmap.conn.queue5) { ConnFree(PlusPack.nmap.conn.queue5); @@ -1700,7 +1691,7 @@ XplServiceMain(int argc, char *argv[]) XplDelay(20 * 1000); #endif - NMAPInitialize(PlusPack.handle.directory); + NMAPInitialize(); SetCurrentNameSpace(NWOS2_NAME_SPACE); SetTargetNameSpace(NWOS2_NAME_SPACE); diff --git a/src/agents/pluspack/pluspack.h b/src/agents/pluspack/pluspack.h index 38ce56c..afd21f7 100644 --- a/src/agents/pluspack/pluspack.h +++ b/src/agents/pluspack/pluspack.h @@ -23,8 +23,6 @@ #define _BONGOPLUSPACK_H #include -#include -#include #include #include #include @@ -219,11 +217,4 @@ typedef struct _PlusPackGlobals { extern PlusPackGlobals PlusPack; -/* management.c */ -ManagementVariables *GetPlusPackManagementVariables(void); -int GetPlusPackManagementVariablesCount(void); -ManagementCommands *GetPlusPackManagementCommands(void); -int GetPlusPackManagementCommandsCount(void); -unsigned char *GetPlusPackVersion(void); - #endif /* _BONGOPLUSPACK_H */ diff --git a/src/agents/pop/Bongo.rules b/src/agents/pop/Bongo.rules index ec1e01a..9f4b4ed 100644 --- a/src/agents/pop/Bongo.rules +++ b/src/agents/pop/Bongo.rules @@ -1,16 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongopop3 -bongopop3_SOURCES := \ +bongopop3_SOURCES = \ src/agents/pop/pop3.c \ src/agents/pop/pop3.h -bongopop3_LDADD := \ +bongopop3_LDADD = \ libbongonmap.la \ - libbongoconnmgr.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/pop/pop3.c b/src/agents/pop/pop3.c index 9aaccf1..7643298 100644 --- a/src/agents/pop/pop3.c +++ b/src/agents/pop/pop3.c @@ -31,15 +31,14 @@ #include #include #include -#include #include #include #include -#include #include -#include #include +#include + #include "pop3.h" #undef NO_READONLY_MBOX @@ -172,7 +171,6 @@ typedef struct _POP3Client { ProtocolCommand *handler; unsigned char user[MAXEMAILNAMESIZE + 1]; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; unsigned char command[CONN_BUFSIZE + 1]; unsigned char buffer[CONN_BUFSIZE + 1]; @@ -263,11 +261,8 @@ struct { XplAtomic badPasswords; } stats; - unsigned char hostName[MAXEMAILNAMESIZE]; unsigned char managementURL[256]; - MDBHandle directoryHandle; - void *loggingHandle; ProtocolCommandTree commands; @@ -380,6 +375,8 @@ SignalHandler(int sigtype) return; } +#if 0 +// FIXME: Function deprecated, or just waiting for a new signal framework static BOOL POP3Shutdown(unsigned char *arguments, unsigned char **response, BOOL *closeConnection) { @@ -428,6 +425,7 @@ POP3Shutdown(unsigned char *arguments, unsigned char **response, BOOL *closeConn return(FALSE); } +#endif static BOOL POP3ClientAllocCB(void *buffer, void *clientData) @@ -460,45 +458,21 @@ ConnectUserToNMAPServer(POP3Client *client, unsigned char *username, unsigned ch { BOOL result; struct sockaddr_in nmap; - MDBValueStruct *user; - user = MDBCreateValueStruct(POP3.directoryHandle, NULL); - if (user) { - result = MsgFindObject(username, client->dn, NULL, &nmap, user); - } else { - return(-1); - } - - if (result) { - result = MDBVerifyPassword(client->dn, password, user); - } else { + if (MsgAuthFindUser(username) != 0) { Log(LOG_NOTICE, "Unknown user %s from host %s", username, LOGIP(client->conn->socketAddress)); - MDBDestroyValueStruct(user); return(POP3_NMAP_USER_UNKNOWN); } - if (result) { - result = MsgGetUserFeature(client->dn, FEATURE_POP, NULL, NULL); - } else { + if (MsgAuthVerifyPassword(username, password) != 0) { XplSafeIncrement(POP3.stats.badPasswords); Log(LOG_NOTICE, "Incorrect password for user %s from host %s", username, LOGIP(client->conn->socketAddress)); - MDBDestroyValueStruct(user); - return(POP3_NMAP_PASSWORD_INVALID); } - if (result) { - strcpy(client->user, user->Value[0]); - } else { - Log(LOG_NOTICE, "POP3 feature disabled on user %s account", username); - MDBDestroyValueStruct(user); - return(POP3_NMAP_FEATURE_DISABLED); - } - - MDBDestroyValueStruct(user); - - if ((client->store = NMAPConnectEx(NULL, &nmap, client->conn->trace.destination)) != NULL) { - result = NMAPAuthenticate(client->store, client->buffer, CONN_BUFSIZE); + MsgAuthGetUserStore(username, &nmap); + if ((client->store = NMAPConnectEx("127.0.0.1", NULL, client->conn->trace.destination)) != NULL) { + result = NMAPAuthenticateToStore(client->store, client->buffer, CONN_BUFSIZE); } else { Log(LOG_ERROR, "Cannot connect to Store Agent on host %s", LOGIP(nmap)); return(POP3_NMAP_SERVER_DOWN); @@ -680,7 +654,6 @@ POP3CommandAuth(void *param) if (!ccode) { LoggerEvent(POP3.loggingHandle, LOGGER_SUBSYSTEM_AUTH, LOGGER_EVENT_LOGIN, LOG_INFO, 0, client->user, NULL, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); - CMAuthenticated((unsigned long)client->conn->socketAddress.sin_addr.s_addr, client->user); } else { if (ccode == POP3_NMAP_SERVER_DOWN) { ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", POP3.hostName, MSGERRNONMAP); @@ -939,10 +912,9 @@ POP3CommandPass(void *param) ccode = ConnectUserToNMAPServer(client, client->user, ptr); if (!ccode) { Log(LOG_INFO, "User %s logged in from host %s", client->user, LOGIP(client->conn->socketAddress)); - CMAuthenticated((unsigned long)client->conn->socketAddress.sin_addr.s_addr, client->user); } else { if (ccode == POP3_NMAP_SERVER_DOWN) { - ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", POP3.hostName, MSGERRNONMAP); + ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", BongoGlobals.hostname, MSGERRNONMAP); } else if (ccode != POP3_NMAP_FEATURE_DISABLED) { XplDelay(2000); client->loginCount++; @@ -985,7 +957,7 @@ POP3CommandPass(void *param) } default: { - ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", POP3.hostName, MSGERRNONMAP); + ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", BongoGlobals.hostname, MSGERRNONMAP); break; } } @@ -1012,7 +984,7 @@ POP3CommandPass(void *param) } default: { - ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", POP3.hostName, MSGERRNONMAP); + ConnWriteF(client->conn, "-ERR [SYS/PERM] %s %s\r\n", BongoGlobals.hostname, MSGERRNONMAP); break; } } @@ -1046,7 +1018,7 @@ static int POP3CommandQuit(void *param) { unsigned long id; - int ccode; + int ccode = 0; int lastccode = 0; POP3Client *client = (POP3Client *)param; @@ -1072,7 +1044,7 @@ POP3CommandQuit(void *param) } if(lastccode == 0) - ConnWriteF(client->conn, "+OK %s %s\r\n", POP3.hostName,MSGOKBYE); + ConnWriteF(client->conn, "+OK %s %s\r\n", BongoGlobals.hostname,MSGOKBYE); else ConnWriteF(client->conn, "-ERR %s %d, %s\r\n", MSGERRINTERNAL, lastccode, MSGOKBYE); @@ -1553,7 +1525,7 @@ HandleConnection(void *param) LOGIP(client->conn->socketAddress)); } - ccode = ConnWriteF(client->conn, "+OK %s %s %s\r\n", POP3.hostName, PRODUCT_NAME, PRODUCT_VERSION); + ccode = ConnWriteF(client->conn, "+OK %s %s %s\r\n", BongoGlobals.hostname, PRODUCT_NAME, PRODUCT_VERSION); if (ccode != -1) { ccode = ConnFlush(client->conn); @@ -1663,7 +1635,6 @@ ServerSocketInit (void) if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { Log(LOG_ERROR, "Couldn't drop to unprivileged user %s", MsgGetUnprivilegedUser()); - XplConsolePrintf("bongopop3: Could not drop to unprivileged user '%s'\n", MsgGetUnprivilegedUser()); return -1; } @@ -1671,13 +1642,11 @@ ServerSocketInit (void) if (POP3.server.conn->socket == -1) { int ret = POP3.server.conn->socket; Log(LOG_ERROR, "Unable to bind to port %ld", POP3ServerPort); - XplConsolePrintf("bongopop3: Could not bind to port %ld\n", POP3ServerPort); ConnFree(POP3.server.conn); return ret; } } else { Log(LOG_ERROR, "Unable to allocate create server socket"); - XplConsolePrintf("bongopop3: Could not allocate connection.\n"); return -1; } @@ -1701,14 +1670,12 @@ ServerSocketSSLInit (void) if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { Log(LOG_ERROR, "Could not drop to unprivileged user %s", MsgGetUnprivilegedUser()); - XplConsolePrintf("bongopop3: Could not drop to unprivileged user '%s'\n", MsgGetUnprivilegedUser()); return -1; } if (POP3.server.ssl.conn->socket == -1) { int ret = POP3.server.ssl.conn->socket; Log(LOG_ERROR, "Could not bind to secure port %ld", POP3ServerPortSSL); - XplConsolePrintf("bongopop3: Could not bind to SSL port %ld\n", POP3ServerPortSSL); ConnFree(POP3.server.conn); ConnFree(POP3.server.ssl.conn); @@ -1716,7 +1683,6 @@ ServerSocketSSLInit (void) } } else { Log(LOG_ERROR, "Could not allocate secure socket"); - XplConsolePrintf("bongopop3: Could not allocate connection.\n"); ConnFree(POP3.server.conn); return -1; } @@ -1806,7 +1772,6 @@ POP3Server(void *ignored) default: { if (POP3.state < POP3_STOPPING) { Log(LOG_ERROR, "Exiting after an accept() failure (%d)", errno); - XplConsolePrintf("POP3D: Exiting after an accept() failure; error %d\n", errno); } POP3.state = POP3_STOPPING; @@ -1818,10 +1783,7 @@ POP3Server(void *ignored) break; } -#if VERBOSE - /* Shutting down */ - XplConsolePrintf("POP3D: Shutdown started.\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown started"); POP3.state = POP3_STOPPING; @@ -1833,21 +1795,10 @@ POP3Server(void *ignored) POP3.server.conn = NULL; } -#if VERBOSE - XplConsolePrintf("POP3D: Standard listener down\r\n"); -#endif + Log(LOG_DEBUG, "Standard listener down."); /* fixme - we need connection management flags for ConnClose to force the shutdown */ ConnCloseAll(1); - /* Management Client Shutdown */ - if (ManagementState() != MANAGEMENT_STOPPED) { - ManagementShutdown(); - - for (ccode = 0; (ManagementState() != MANAGEMENT_STOPPED) && (ccode < 60); ccode++) { - XplDelay(1000); - } - } - XplWaitOnLocalSemaphore(POP3.client.semaphore); ccode = XplSafeRead(POP3.client.worker.idle); @@ -1862,12 +1813,10 @@ POP3Server(void *ignored) } if (XplSafeRead(POP3.server.active) > 1) { - XplConsolePrintf("POP3D: %d server threads outstanding; attempting forceful unload.\r\n", XplSafeRead(POP3.server.active) - 1); + Log(LOG_INFO, "%d server threads outstanding; attempting forceful unload.", XplSafeRead(POP3.server.active)-1); } -#if VERBOSE - XplConsolePrintf("\rPOP3D: Shutting down %d client threads\r\n", XplSafeRead(POP3.client.worker.active)); -#endif + Log(LOG_DEBUG, "Shutting down %d client threads.", XplSafeRead(POP3.client.worker.active)); /* Make sure the kids have flown the coop. */ for (ccode = 0; XplSafeRead(POP3.client.worker.active) && (ccode < 60); ccode++) { @@ -1875,7 +1824,7 @@ POP3Server(void *ignored) } if (XplSafeRead(POP3.client.worker.active)) { - XplConsolePrintf("\rPOP3D: %d threads outstanding; attempting forceful unload.\r\n", XplSafeRead(POP3.client.worker.active)); + Log(LOG_INFO, "%d threads outstanding; attempting forceful unload.", XplSafeRead(POP3.client.worker.active)); } if (POP3.server.ssl.enable) { @@ -1908,24 +1857,18 @@ POP3Server(void *ignored) } } - XPLCryptoLockDestroy(); - LoggerClose(POP3.loggingHandle); POP3.loggingHandle = NULL; MsgShutdown(); -/* MDBShutdown(); */ - CONN_TRACE_SHUTDOWN(); ConnShutdown(); MemPrivatePoolFree(POP3.client.pool); MemoryManagerClose(MSGSRV_AGENT_POP); -#if VERBOSE - XplConsolePrintf("\rPOP3D: Shutdown complete\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown complete."); XplSignalLocalSemaphore(POP3.sem.main); XplWaitOnLocalSemaphore(POP3.sem.shutdown); @@ -2029,7 +1972,6 @@ client->CSSL = NULL; default: { if (POP3.state < POP3_STOPPING) { Log(LOG_ERROR, "Secure server exiting after an accept() failure (%d)", errno); - XplConsolePrintf("POP3D: Exiting after an accept() failure; error %d\n", errno); POP3.state = POP3_STOPPING; } @@ -2065,69 +2007,36 @@ client->CSSL = NULL; XplSafeDecrement(POP3.server.active); -#if VERBOSE - XplConsolePrintf("\rPOP3D: SSL listener down.\r\n"); -#endif + Log(LOG_DEBUG, "SSL listener down."); return; } +static BongoConfigItem POP3Config[] = { + { BONGO_JSON_INT, "o:port/i", &POP3ServerPort }, + { BONGO_JSON_INT, "o:port_ssl/i", &POP3ServerPortSSL }, + { BONGO_JSON_NULL, NULL, NULL } +}; + static BOOL ReadConfiguration(void) { - MDBValueStruct *config; - - config = MDBCreateValueStruct(POP3.directoryHandle, MsgGetServerDN(NULL)); + POP3.server.ssl.config.options |= SSL_ALLOW_CHAIN; + POP3.server.ssl.config.options |= SSL_ALLOW_SSL3; + POP3.server.ssl.enable = TRUE; + POP3.nmap.ssl.enable = FALSE; // FIXME: why? - if (MDBRead(MSGSRV_AGENT_POP, MSGSRV_A_PORT, config)>0) { - POP3ServerPort = atol (config->Value[0]); - } - MDBFreeValues(config); - if (MDBRead(MSGSRV_AGENT_POP, MSGSRV_A_SSL_PORT, config)>0) { - POP3ServerPortSSL = atol (config->Value[0]); - } - MDBFreeValues(config); + if (! MsgGetServerCredential(POP3.nmap.hash)) + return FALSE; - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_SSL_ALLOW_CHAINED, config)) { - if (atol(config->Value[0])) { - POP3.server.ssl.config.options |= SSL_ALLOW_CHAIN; - } - } - MDBFreeValues(config); - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_SSL_TLS, config)) { - if (atol(config->Value[0])) { - POP3.server.ssl.config.options |= SSL_ALLOW_SSL3; - POP3.server.ssl.enable = TRUE; - POP3.nmap.ssl.enable = FALSE; - } - } - MDBFreeValues(config); - - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_URL, config)) { - strcpy(POP3.managementURL, config->Value[0]); - - MDBFreeValues(config); + if (! ReadBongoConfiguration(POP3Config, "pop3")) { + return FALSE; } - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_OFFICIAL_NAME, config)) { - if (config->Value[0]) { - strcpy(POP3.hostName, config->Value[0]); - } else { - gethostname(POP3.hostName, sizeof(POP3.hostName)); - } - - MDBFreeValues(config); - } else { - gethostname(POP3.hostName, sizeof(POP3.hostName)); + if (! ReadBongoConfiguration(GlobalConfig, "global")) { + return FALSE; } - MDBSetValueStructContext(NULL, config); - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, config)) { - HashCredential(MsgGetServerDN(NULL), config->Value[0], POP3.nmap.hash); - } - - MDBDestroyValueStruct(config); - return(TRUE); } @@ -2140,8 +2049,8 @@ XplServiceMain(int argc, char *argv[]) XplThreadID id; if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongopop3: Could not drop to unprivileged user '%s', exiting.\n", MsgGetUnprivilegedUser()); - return 1; + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); + return 1; } XplInit(); @@ -2164,8 +2073,6 @@ XplServiceMain(int argc, char *argv[]) POP3.server.ssl.context = NULL; POP3.server.ssl.config.options = 0; - POP3.directoryHandle = NULL; - POP3.loggingHandle = NULL; POP3.managementURL[0] = '\0'; @@ -2192,30 +2099,19 @@ XplServiceMain(int argc, char *argv[]) } else { MemoryManagerClose(MSGSRV_AGENT_POP); - XplConsolePrintf("POP3D: Unable to create connection pool; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to create connection pool; shutting down."); return(-1); } } else { - XplConsolePrintf("POP3D: Unable to initialize memory manager; shutting down.\r\n"); + Log(LOG_ERROR, "Unable to initialize memory manager; shutting down."); return(-1); } ConnStartup(CONNECTION_TIMEOUT, TRUE); - MDBInit(); - POP3.directoryHandle = (MDBHandle)MsgInit(); - if (POP3.directoryHandle == NULL) { - XplBell(); - XplConsolePrintf("\rPOP3D: Invalid directory credentials; exiting!\n"); - XplBell(); - - MemoryManagerClose(MSGSRV_AGENT_POP); - - return(-1); - } - - NMAPInitialize(POP3.directoryHandle); - CMInitialize(POP3.directoryHandle, "POP3"); + MsgInit(); + MsgAuthInit(); + NMAPInitialize(); POP3.loggingHandle = LoggerOpen("bongopop3"); if (POP3.loggingHandle == NULL) { @@ -2228,18 +2124,16 @@ XplServiceMain(int argc, char *argv[]) if (ServerSocketInit () < 0) { - XplConsolePrintf("bongopop3: Exiting.\n"); + Log(LOG_ERROR, "Server Initialization failed."); return -1; } if (POP3.server.ssl.enable) { if (!ServerSocketSSLInit()) { - XPLCryptoLockInit(); - - POP3.server.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); + POP3.server.ssl.config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + POP3.server.ssl.config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); POP3.server.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - POP3.server.ssl.config.key.file = MsgGetTLSKeyPath(NULL); POP3.server.ssl.context = ConnSSLContextAlloc(&(POP3.server.ssl.config)); if (POP3.server.ssl.context) { @@ -2252,17 +2146,17 @@ XplServiceMain(int argc, char *argv[]) } } - /* Done binding, drop privs permanentely */ + /* Done binding, drop privs permanently */ if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongopop3: Could not drop to unprivileged user '%s', exiting.\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); return -1; } POP3.nmap.ssl.enable = FALSE; - POP3.nmap.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); + POP3.nmap.ssl.config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + POP3.nmap.ssl.config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); POP3.nmap.ssl.config.key.type = GNUTLS_X509_FMT_PEM; - POP3.nmap.ssl.config.key.file = MsgGetTLSKeyPath(NULL); - + POP3.nmap.ssl.context = ConnSSLContextAlloc(&(POP3.nmap.ssl.config)); if (POP3.nmap.ssl.context) { POP3.nmap.ssl.enable = TRUE; diff --git a/src/agents/queue/Bongo.rules b/src/agents/queue/Bongo.rules index 257f53a..29595fb 100644 --- a/src/agents/queue/Bongo.rules +++ b/src/agents/queue/Bongo.rules @@ -1,7 +1,7 @@ # -*- Makefile -*- sbin_PROGRAMS += bongoqueue -bongoqueue_SOURCES := \ +bongoqueue_SOURCES = \ src/agents/queue/conf.c \ src/agents/queue/conf.h \ src/agents/queue/domain.c \ @@ -14,11 +14,9 @@ bongoqueue_SOURCES := \ src/agents/queue/queue.h \ src/agents/queue/messages.h -bongoqueue_LDADD := \ +bongoqueue_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/queue/conf.c b/src/agents/queue/conf.c index 7e5cf27..6f9b559 100644 --- a/src/agents/queue/conf.c +++ b/src/agents/queue/conf.c @@ -17,24 +17,24 @@ * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * + * (C) 2007 Patrick Felt ****************************************************************************/ #include +#include "conf.h" #include "queue.h" #include #include #include #include -#include -#include + #include #include #include #include -#include "conf.h" #include "domain.h" #include "messages.h" @@ -46,7 +46,9 @@ #define QLIMIT_CONCURRENT 250 #define QLIMIT_SEQUENTIAL 500 -QueueConfiguration Conf = { {0, }, }; +int aliasCmpFunc (const void *lft, const void *rgt); + +QueueConfiguration Conf = { 0, {0, }, }; long CalculateCheckQueueLimit(unsigned long concurrent, unsigned long sequential) @@ -58,196 +60,111 @@ CalculateCheckQueueLimit(unsigned long concurrent, unsigned long sequential) return(sequential); } -static BOOL -ReadStartupConfiguration(BOOL *recover) +int hostedSortFunc(const void *str1, const void *str2) { + int i = strcasecmp(*(char **)str1, *(char **)str2); + return i; +} + + +static BongoConfigItem trustedHostsConfig[] = { + { BONGO_JSON_STRING, NULL, &Conf.trustedHosts}, + { BONGO_JSON_NULL, NULL, NULL } +}; + +static BongoConfigItem domainsConfig[] = { + { BONGO_JSON_STRING, NULL, &Conf.domains}, + { BONGO_JSON_NULL, NULL, NULL } +}; + +static BongoConfigItem QueueConfig[] = { + { BONGO_JSON_BOOL, "o:debug/b", &Conf.debug }, + { BONGO_JSON_ARRAY, "o:domains/a", &domainsConfig }, + { BONGO_JSON_BOOL, "o:limitremoteprocessing/b", &Conf.deferEnabled }, + { BONGO_JSON_INT, "o:limitremotebegweekday/i", &Conf.i_deferStartWD }, + { BONGO_JSON_INT, "o:limitremotebegweekend/i", &Conf.i_deferStartWE }, + { BONGO_JSON_INT, "o:limitremoteendweekday/i", &Conf.i_deferEndWD }, + { BONGO_JSON_INT, "o:limitremoteendweekend/i", &Conf.i_deferEndWE }, + { BONGO_JSON_INT, "o:queuetuning_concurrent/i", &Conf.maxConcurrentWorkers }, + { BONGO_JSON_INT, "o:queuetuning_sequential/i", &Conf.maxSequentialWorkers }, + { BONGO_JSON_INT, "o:queuetuning_load_high/i", &Conf.loadMonitorHigh }, + { BONGO_JSON_INT, "o:queuetuning_load_low/i", &Conf.loadMonitorLow }, + { BONGO_JSON_INT, "o:queuetuning_trigger/i", &Conf.limitTrigger }, + { BONGO_JSON_INT, "o:queuetimeout/i", &Conf.maxLinger }, + { BONGO_JSON_STRING, "o:quotamessage/s", &Conf.quotaMessage }, + { BONGO_JSON_INT, "o:port/i", &Agent.agent.port }, + { BONGO_JSON_BOOL, "o:forwardundeliverable_enabled/b", &Conf.forwardUndeliverableEnabled }, + { BONGO_JSON_STRING, "o:forwardundeliverable_to/s", &Conf.forwardUndeliverableAddress }, + { BONGO_JSON_INT, "o:queueinterval/i", &Conf.queueInterval }, + { BONGO_JSON_INT, "o:minimumfreespace/i", &Conf.minimumFree }, + { BONGO_JSON_ARRAY, "o:trustedhosts/a", &trustedHostsConfig }, + { BONGO_JSON_BOOL, "o:rtsantispamconfig_enabled/b", &Conf.bounceBlockSpam }, + { BONGO_JSON_INT, "o:rtsantispamconfig_delay/i", &Conf.bounceInterval }, + { BONGO_JSON_INT, "o:rtsantispamconfig_threshold/i", &Conf.bounceMax }, + { BONGO_JSON_BOOL, "o:bouncereturn/b", &Conf.b_bounceReturn }, + { BONGO_JSON_BOOL, "o:bounceccpostmaster/b", &Conf.b_bounceCCPostmaster }, + { BONGO_JSON_NULL, NULL, NULL } +}; + +int aliasCmpFunc (const void *lft, const void *rgt){ + struct _AliasStruct *l = (struct _AliasStruct *)(lft); + struct _AliasStruct *r = (struct _AliasStruct *)(rgt);; + return strcasecmp(l->original, r->original); +} + +BOOL +ReadConfiguration (BOOL *recover) { - MDBValueStruct *vs; - - gethostname(Conf.hostname, sizeof(Conf.hostname)); - - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - - if (recover) { - *recover = FALSE; - if (MDBRead(MsgGetServerDN(NULL), MSGSRV_A_SERVER_STATUS, vs) > 0) { - if (XplStrCaseCmp(vs->Value[0], "Shutdown") != 0) { - *recover = TRUE; - } - } - - MDBFreeValues(vs); + if (!MsgGetServerCredential((char *)&Conf.serverHash)) { + return FALSE; } - - if (vs && MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, vs)) { - HashCredential(MsgGetServerDN(NULL), vs->Value[0], Conf.serverHash); - MDBFreeValues(vs); - } else { + + if (!ReadBongoConfiguration(QueueConfig, "queue")) { return FALSE; } - if (MDBRead(MsgGetServerDN(NULL), MSGSRV_A_OFFICIAL_NAME, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_OFFICIAL_NAME", vs->Value[0], 0, 0, NULL, 0); - - strcpy(Conf.officialName, vs->Value[0]); - - MDBFreeValues(vs); + if (!ReadBongoConfiguration(GlobalConfig, "global")) { + return FALSE; } - - if (MDBRead(MsgGetServerDN(NULL), MSGSRV_A_POSTMASTER, vs) > 0) { - if (vs->Value[0]) { - char *ptr; - - if ((ptr = strrchr(vs->Value[0], '\\')) != NULL) { - strcpy(Conf.postMaster, ptr + 1); - } else { - strcpy(Conf.postMaster, vs->Value[0]); - } - } else { - strcpy(Conf.postMaster, "admin"); - } - - MDBFreeValues(vs); - } - - MDBSetValueStructContext(MsgGetServerDN(NULL), vs); - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_LIMIT_REMOTE_PROCESSING, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_LIMIT_REMOTE_PROCESSING", vs->Value[0], 0, 0, NULL, 0); - - if (atol(vs->Value[0])) { - Conf.deferEnabled = TRUE; - } else { - Conf.deferEnabled = FALSE; - } - - MDBFreeValues(vs); - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_LIMIT_REMOTE_START_WD, vs) > 0) { - int count; - - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_LIMIT_REMOTE_START_WD", vs->Value[0], 0, 0, NULL, 0); - for (count = 1; count < 6; count++) { - /* Counting weekdays */ - Conf.deferStart[count] = (unsigned char)atoi(vs->Value[0]); - } - - MDBFreeValues(vs); - } else { - Conf.deferEnabled = FALSE; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_LIMIT_REMOTE_START_WE, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_LIMIT_REMOTE_START_WE", vs->Value[0], 0, 0, NULL, 0); - - Conf.deferStart[0] = (unsigned char)atoi(vs->Value[0]); - Conf.deferStart[6] = (unsigned char)atoi(vs->Value[0]); - - MDBFreeValues(vs); - } else { - Conf.deferEnabled = FALSE; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_LIMIT_REMOTE_END_WD, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_LIMIT_REMOTE_END_WD", vs->Value[0], 0, 0, NULL, 0); - int count; - - for (count = 1; count < 6; count++) { - /* Counting weekdays */ - Conf.deferEnd[count] = (unsigned char)atoi(vs->Value[0]); - } - - MDBFreeValues(vs); - } else { - Conf.deferEnabled = FALSE; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_LIMIT_REMOTE_END_WE, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_LIMIT_REMOTE_END_WE", vs->Value[0], 0, 0, NULL, 0); - - Conf.deferEnd[0] = (unsigned char)atoi(vs->Value[0]); - Conf.deferEnd[6] = (unsigned char)atoi(vs->Value[0]); - - MDBFreeValues(vs); - } else { - Conf.deferEnabled = FALSE; - } - } - - Conf.maxConcurrentWorkers = QLIMIT_CONCURRENT; - Conf.maxSequentialWorkers = QLIMIT_SEQUENTIAL; - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_QUEUE_TUNING, vs) > 0) { - unsigned int used; + *recover = MsgGetRecoveryFlag("queue"); + + /* set some arrays up */ + if (Conf.deferEnabled) { + Conf.deferStart[0] = Conf.i_deferStartWE; /* sunday */ + Conf.deferStart[1] = Conf.i_deferStartWD; + Conf.deferStart[2] = Conf.i_deferStartWD; + Conf.deferStart[3] = Conf.i_deferStartWD; + Conf.deferStart[4] = Conf.i_deferStartWD; + Conf.deferStart[5] = Conf.i_deferStartWD; + Conf.deferStart[6] = Conf.i_deferStartWE; /* saturday */ - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_QUEUE_TUNING", vs->Value[0], 0, 0, NULL, 0); - - for (used = 0; used < vs->Used; used++) { - if (XplStrNCaseCmp(vs->Value[used], "concurrent", 10) == 0) { - sscanf(vs->Value[used], "Concurrent: %ld Sequential: %ld", &Conf.maxConcurrentWorkers, &Conf.maxSequentialWorkers); - } - - else if (XplStrNCaseCmp(vs->Value[used], "Load", 4) == 0) { - sscanf(vs->Value[used], "Load high: %ld Load Low: %ld Queue Trigger: %ld", &Conf.loadMonitorHigh, &Conf.loadMonitorLow, &Conf.limitTrigger); - } else if (XplStrNCaseCmp(vs->Value[used], "Debug", 5) == 0) { - if (atol(vs->Value[used]) + 6) { - Agent.flags |= QUEUE_AGENT_DEBUG; - } else { - Agent.flags &= ~QUEUE_AGENT_DEBUG; - } - } - } - - MDBFreeValues(vs); + Conf.deferEnd[0] = Conf.i_deferEndWE; + Conf.deferEnd[1] = Conf.i_deferEndWD; + Conf.deferEnd[2] = Conf.i_deferEndWD; + Conf.deferEnd[3] = Conf.i_deferEndWD; + Conf.deferEnd[4] = Conf.i_deferEndWD; + Conf.deferEnd[5] = Conf.i_deferEndWD; + Conf.deferEnd[6] = Conf.i_deferEndWE; } - + + if (Conf.debug) { + Agent.flags |= QUEUE_AGENT_DEBUG; + } else { + Agent.flags &= ~QUEUE_AGENT_DEBUG; + } + Conf.queueCheck = CalculateCheckQueueLimit(Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers); - + /* Set the globals for loadmonitor */ Conf.defaultConcurrentWorkers = Conf.maxConcurrentWorkers; Conf.defaultSequentialWorkers = Conf.maxSequentialWorkers; - - strcpy(Conf.spoolPath, XPL_DEFAULT_SPOOL_DIR); - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_SPOOL_DIRECTORY, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_SPOOL_DIRECTORY", vs->Value[0], 0, 0, NULL, 0); - - MsgCleanPath(vs->Value[0]); - strcpy(Conf.spoolPath, vs->Value[0]); - MDBFreeValues(vs); - } + strcpy(Conf.spoolPath, XPL_DEFAULT_SPOOL_DIR); MsgMakePath(Conf.spoolPath); - - sprintf(Conf.queueClientsPath, "%s/qclients", MsgGetDBFDir(NULL)); - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_QUEUE_TIMEOUT, vs) > 0) { - Conf.maxLinger = atoi(vs->Value[0]) * 24 * 60 * 60; - if (!Conf.maxLinger) { - Conf.maxLinger = DEFAULT_MAX_LINGER; - } - - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_NUMERIC, LOG_INFO, 0, "MSGSRV_A_QUEUE_TIMEOUT", NULL, Conf.maxLinger, 0, NULL, 0); - - MDBFreeValues(vs); - } else { - Conf.maxLinger = DEFAULT_MAX_LINGER; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_QUOTA_MESSAGE, vs) > 0) { - Conf.quotaMessage = MemStrdup(vs->Value[0]); - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_QUOTA_MESSAGE", Conf.quotaMessage, 0, 0, NULL, 0); - - MDBFreeValues(vs); - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_PORT, vs) > 0) { - Agent.agent.port = atol(vs->Value[0]); - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_NUMERIC, LOG_INFO, 0, "MSGSRV_A_PORT", NULL, Agent.agent.port, 0, NULL, 0); - - MDBFreeValues(vs); - } - + + sprintf(Conf.queueClientsPath, "%s/qclients", MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); + Conf.bounceMaxBodySize = 0; - /* Some sanity checking on the QLimit stuff to prevent running out of memory */ if (XplGetMemAvail() < (unsigned long)((STACKSPACE_Q + STACKSPACE_S) * Conf.maxSequentialWorkers)) { Conf.maxSequentialWorkers = (XplGetMemAvail() / (STACKSPACE_Q+STACKSPACE_S)) / 2; @@ -258,158 +175,92 @@ ReadStartupConfiguration(BOOL *recover) XplConsolePrintf("bongoqueue: WARNING - Tuning parameters adjusted to %ld par./%ld seq.\r\n", Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers); XplBell(); - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_QLIMITS_ADJUSTED, LOG_WARNING, 0, NULL, NULL, Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers, NULL, 0); + Log(LOG_INFO, "Not enough memory; tuning parameters adjusted; concurrent limit: %d, sequential limit: %d", Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers); Conf.defaultConcurrentWorkers = Conf.maxConcurrentWorkers; Conf.defaultSequentialWorkers = Conf.maxSequentialWorkers; } - MDBDestroyValueStruct(vs); - - return TRUE; -} - -static BOOL -ReadLiveConfiguration(void) -{ - MDBValueStruct *vs; + BongoArraySort(Conf.trustedHosts, (ArrayCompareFunc)strcmp); - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, MsgGetServerDN(NULL)); - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_FORWARD_UNDELIVERABLE, vs) > 0) { - if (vs->Value[0][0] != '\0') { - strcpy(Conf.forwardUndeliverableAddress, vs->Value[0]); - Conf.forwardUndeliverableEnabled = TRUE; - } else { - Conf.forwardUndeliverableAddress[0] = '\0'; - Conf.forwardUndeliverableEnabled = FALSE; - } - - MDBFreeValues(vs); + if (Conf.b_bounceReturn) { + Conf.bounceHandling |= BOUNCE_RETURN; } else { - Conf.forwardUndeliverableAddress[0] = '\0'; - Conf.forwardUndeliverableEnabled = FALSE; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_QUEUE_INTERVAL, vs) > 0) { - Conf.queueInterval = atol(vs->Value[0])*60; - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_NUMERIC, LOG_INFO, 0, "MSGSRV_A_QUEUE_INTERVAL", NULL, Conf.queueInterval, 0, NULL, 0); - if (Conf.queueInterval < 1) { - Conf.queueInterval = 4 * 60; - } - - MDBFreeValues(vs); - } else { - Conf.queueInterval = 4 * 60; - } - - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_MINIMUM_SPACE, vs) > 0) { - Conf.minimumFree = atol(vs->Value[0]) * 1024; - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_NUMERIC, LOG_INFO, 0, "MSGSRV_A_MINIMUM_SPACE", NULL, Conf.minimumFree, 0, NULL, 0); - - MDBFreeValues(vs); - } else { - Conf.minimumFree = 5 * 1024 * 1024; - } - - /* FIXME: we need to move the trusted hosts somewhere better */ - Conf.trustedHosts.count = MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_STORE_TRUSTED_HOSTS, vs); - - if (Conf.trustedHosts.hosts) { - MemFree(Conf.trustedHosts.hosts); + Conf.bounceHandling &= ~BOUNCE_RETURN; } - if (Conf.trustedHosts.count) { - Conf.trustedHosts.hosts = MemMalloc(Conf.trustedHosts.count * sizeof(unsigned long)); - if (Conf.trustedHosts.hosts) { - unsigned long used; - int count = 0; + if (Conf.b_bounceCCPostmaster) { + Conf.bounceHandling |= BOUNCE_CC_POSTMASTER; + } else { + Conf.bounceHandling &= ~BOUNCE_CC_POSTMASTER; + } + + /* sort the hostedDomains to make searching later faster. */ + BongoArraySort(Conf.domains, (ArrayCompareFunc)hostedSortFunc); - for (used = 0; used < vs->Used; used++) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "NMAP_TRUSTED_HOSTS", vs->Value[used], 0, 0, NULL, 0); - - Conf.trustedHosts.hosts[count++] = inet_addr(vs->Value[used]); + /* now let's iterate over the domains and read in any aliasing information for those domains */ + { + Conf.aliasList = BongoArrayNew(sizeof(struct _AliasStruct), Conf.domains->len); + + unsigned int x; + for(x=0;xlen;x++) { + unsigned char *aconfig; + unsigned char path[100]; + BongoJsonNode *node; + struct _AliasStruct a; + + a.original = MemStrdup(BongoArrayIndex(Conf.domains, unsigned char *, x)); + a.to = NULL; + a.aliases = NULL; + a.mapping_type = 0; + + sprintf(path, "aliases/%s", a.original); + if(NMAPReadConfigFile(path, &aconfig)) { + if (BongoJsonParseString(aconfig, &node) == BONGO_JSON_OK) { + BongoJsonObject *obj; + + BongoJsonJPathGetString(node, "o:domainalias/s", (char **)&(a.to)); + BongoJsonJPathGetInt(node, "o:username-mapping/i", &a.mapping_type); + + /* now get any specific aliases */ + if (BongoJsonJPathGetObject(node, "o:aliases/o", &obj) == BONGO_JSON_OK) { + BongoJsonObjectIter iter; + + a.aliases = BongoArrayNew(sizeof(struct _AliasStruct), 1); + + BongoJsonObjectIterFirst(obj, &iter); + while (iter.key) { + /* TODO: do i need to parse the addresses? + * I'd need to parse original and only use the user portion + * I'd need to parse the to and append the domain if none exists + */ + struct _AliasStruct b; + b.original = MemStrdup(iter.key); + b.to = MemStrdup(BongoJsonNodeAsString(iter.value)); + b.aliases = NULL; + b.mapping_type = 0; + + BongoArrayAppendValue(a.aliases, b); + + BongoJsonObjectIterNext(obj, &iter); + } + BongoArraySort(a.aliases, (ArrayCompareFunc)aliasCmpFunc); + } + BongoJsonNodeFree(node); + } } - } else { - Conf.trustedHosts.count = 0; + + BongoArrayAppendValue(Conf.aliasList, a); } - } - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_RTS_ANTISPAM_CONFIG, vs) > 0) { - LoggerEvent(Agent.agent.loggingHandle, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_RTS_ANTISPAM_CONFIG", vs->Value[0], 0, 0, NULL, 0); - if (sscanf(vs->Value[0], "Enabled:%d Delay:%ld Threshhold:%lu", &Conf.bounceBlockSpam, &Conf.bounceInterval, &Conf.bounceMax) != 3) { - Conf.bounceBlockSpam = FALSE; - } - - if ((Conf.bounceMax < 1) || (Conf.bounceInterval < 1)) { - Conf.bounceBlockSpam = FALSE; - } - MDBFreeValues(vs); - } else { - Conf.bounceBlockSpam = FALSE; + /* sort the list for speed later */ + BongoArraySort(Conf.aliasList, (ArrayCompareFunc)aliasCmpFunc); } - - Conf.bounceHandling = BOUNCE_RETURN; - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_BOUNCE_RETURN, vs) > 0) { - if (atol(vs->Value[0])) { - Conf.bounceHandling |= BOUNCE_RETURN; - } else { - Conf.bounceHandling &= ~BOUNCE_RETURN; - } - } - MDBFreeValues(vs); - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_BOUNCE_CC_POSTMASTER, vs) > 0) { - if (atol(vs->Value[0])) { - Conf.bounceHandling |= BOUNCE_CC_POSTMASTER; - } else { - Conf.bounceHandling &= ~BOUNCE_RETURN; - } - } - MDBFreeValues(vs); - - if ((MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_CONFIG_CHANGED, vs) > 0)) { - Conf.lastRead = atol(vs->Value[0]); - } - - MDBDestroyValueStruct(vs); - return TRUE; } -BOOL -ReadConfiguration (BOOL *recover) -{ - if (!ReadStartupConfiguration (recover)) { - return FALSE; - } - - return ReadLiveConfiguration(); -} - - void CheckConfig(BongoAgent *agent) { - MDBValueStruct *vs; - - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, MsgGetServerDN(NULL)); - if (!vs) { - return; - } - - if ((MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_CONFIG_CHANGED, vs) > 0) - && ((unsigned long)atol(vs->Value[0]) != Conf.lastRead)) { - /* Clear what we just read */ - Conf.lastRead = atol(vs->Value[0]); - - /* Acquire Write Lock */ - XplRWWriteLockAcquire(&Conf.lock); - - ReadLiveConfiguration(); - - XplRWWriteLockRelease(&Conf.lock); - } - - MDBDestroyValueStruct(vs); +/* TODO: Figure out how we are going to handle this type of situation */ + return; } - - diff --git a/src/agents/queue/conf.h b/src/agents/queue/conf.h index 46430fe..fa57083 100644 --- a/src/agents/queue/conf.h +++ b/src/agents/queue/conf.h @@ -24,8 +24,6 @@ #include #include -#include -#include #include #include #include @@ -38,22 +36,18 @@ typedef enum { } BounceFlags; typedef struct _QueueConfiguration { + BOOL debug; + XplRWLock lock; /* Server info */ - char hostname[MAXEMAILNAMESIZE + 1]; char serverHash[NMAP_HASH_SIZE]; - char postMaster[MAXEMAILNAMESIZE + 1]; - char officialName[MAXEMAILNAMESIZE + 1]; /* Quotas */ char *quotaMessage; /* Trusted hosts */ - struct { - int count; - unsigned long *hosts; - } trustedHosts; + BongoArray *trustedHosts; /* Paths */ char spoolPath[XPL_MAX_PATH + 1]; @@ -61,6 +55,10 @@ typedef struct _QueueConfiguration { /* Deferral */ BOOL deferEnabled; + char i_deferStartWD; + char i_deferStartWE; + char i_deferEndWD; + char i_deferEndWE; char deferStart[7]; char deferEnd[7]; @@ -70,7 +68,7 @@ typedef struct _QueueConfiguration { /* Forward Undeliverable */ BOOL forwardUndeliverableEnabled; - char forwardUndeliverableAddress[MAXEMAILNAMESIZE + 1]; + char *forwardUndeliverableAddress; /* Queue tuning */ long defaultConcurrentWorkers; @@ -95,12 +93,29 @@ typedef struct _QueueConfiguration { unsigned long bounceMaxBodySize; unsigned long bounceMax; + BOOL b_bounceReturn; + BOOL b_bounceCCPostmaster; BounceFlags bounceHandling; /* Bookkeeping */ unsigned long lastRead; + + /* aliasing system */ + BongoArray *hostedDomains; + BongoArray *aliasList; + + BongoArray *domains; } QueueConfiguration; +struct _AliasStruct{ + unsigned char* original; + unsigned char* to; + unsigned int mapping_type; + BongoArray *aliases; +}; + +typedef struct _AliasStruct AliasStruct; + extern QueueConfiguration Conf; void CheckConfig(BongoAgent *agent); @@ -109,4 +124,6 @@ BOOL ReadConfiguration(BOOL *recover); long CalculateCheckQueueLimit(unsigned long concurrent, unsigned long sequential); +int hostedSortFunc(const void *str1, const void *str2); + #endif /* _DELIVERYQUEUE_H */ diff --git a/src/agents/queue/domain.c b/src/agents/queue/domain.c index 4fae270..304c414 100644 --- a/src/agents/queue/domain.c +++ b/src/agents/queue/domain.c @@ -25,644 +25,71 @@ #include "domain.h" -#if 0 - -typedef enum { - QDBHANDLE_FLAG_INUSE = (1 << 0), - QDBHANDLE_FLAG_NON_POOLABLE = (1 << 1) -} QDBHandleFlags; - -typedef struct _QDBHandle { - struct _QDBHandle *next; - struct _QDBHandle *previous; - - QDBHandleFlags flags; - - sqlite3 *handle; -} QDBHandle; - -struct { - QDBHandle *available; - QDBHandle *inUse; - - XplSemaphore sem; - - struct { - unsigned int minimum; - unsigned int maximum; - - unsigned int allocated; - } eCount; - - struct { - unsigned long pitches; - unsigned long strikes; - } stats; -} QDBHandles; - -static int -QDBSearchCB(void *param, int cCount, char **cValues, char **cNames) -{ - int i; - MDBValueStruct *vs = (MDBValueStruct *)param; - - for (i = 0; i < cCount; i++) { - MDBAddValue(cValues[i], vs); - } - - return(0); -} - -static int -QueryResultsCB(void *param, int cCount, char **cValues, char **cNames) -{ - int i; - QueryResults *qData = (QueryResults *)param; - - if (qData->column.count == 0) { - qData->column.count = cCount; - - for (i = 0; i < cCount; i++) { - MDBAddValue(cNames[i], qData->column.names); - } - } - - qData->row.count++; - for (i = 0; i < cCount; i++) { - if (cValues[1]) { - MDBAddValue(cValues[i], qData->row.values); - } else { - MDBAddValue("NULL", qData->row.values); - } - } - - return(0); -} - -#endif - int QDBStartup(int minimum, int maximum) { return 0; -#if 0 - int i; - int ccode = SQLITE_ERROR; - unsigned char *ptr; - char *errmsg = NULL; - sqlite3 *handle = NULL; - QDBHandle *qdb; - - memset(&QDBHandles, 0, sizeof(QDBHandles)); - - XplOpenLocalSemaphore(QDBHandles.sem, 0); - - QDBHandles.eCount.minimum = minimum; - QDBHandles.eCount.maximum = maximum; - - if (access(NMAP.path.qDomains, 0) != 0) { - ccode = sqlite3_open(NMAP.path.qDomains, &handle); - if (ccode == SQLITE_OK) { - ccode = sqlite3_exec(handle, NMAP_QDB_SQLITE_CREATE, NULL, NULL, &errmsg); - if (ccode == SQLITE_OK) { - ccode = sqlite3_exec(handle, NMAP_QDB_SQLITE_INDEX, NULL, NULL, &errmsg); - if (ccode != SQLITE_OK) { - ptr = "index"; - } - } else { - ptr = "table"; - } - } else { - ptr = "database"; - } - - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed to create NMAP QDB %s; error: \"%s\".\r\n", ptr, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed to create NMAP QDB %s; error %d.\r\n", ptr, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (handle) { - sqlite3_close(handle); - handle = NULL; - } - - if (ccode != SQLITE_OK) { - return(-1); - } - } - - for (i = 0; i < maximum; i++) { - qdb = (QDBHandle *)MemMalloc(sizeof(QDBHandle)); - if (qdb) { - memset(qdb, 0, sizeof(QDBHandle)); - - if (sqlite3_open(NMAP.path.qDomains, &(qdb->handle)) == SQLITE_OK) { - if ((qdb->next = QDBHandles.available) != NULL) { - QDBHandles.available->previous = qdb; - } - QDBHandles.available = qdb; - - continue; - } - - if (qdb->handle) { - sqlite3_close(qdb->handle); - } - - MemFree(qdb); - } - - break; - } - - if (i) { - XplSignalLocalSemaphore(QDBHandles.sem); - - return(0); - } - - return(-1); -#endif } void QDBShutdown(void) { -#if 0 - QDBHandle *qdb; - QDBHandle *next; - - XplWaitOnLocalSemaphore(QDBHandles.sem); - - qdb = QDBHandles.available; - QDBHandles.available = NULL; - - while (qdb) { - next = qdb->next; - - sqlite3_close(qdb->handle); - - qdb = next; - } - - qdb = QDBHandles.inUse; - QDBHandles.inUse = NULL; - - while (qdb) { - next = qdb->next; - - sqlite3_close(qdb->handle); - - qdb = next; - } - - XplCloseLocalSemaphore(QDBHandles.sem); -#endif } void * QDBHandleAlloc(void) { return NULL; -#if 0 - QDBHandle *qdb; - - XplWaitOnLocalSemaphore(QDBHandles.sem); - - QDBHandles.stats.pitches++; - - if (QDBHandles.available != NULL) { - qdb = QDBHandles.available; - if ((QDBHandles.available = qdb->next) != NULL) { - QDBHandles.available->previous = NULL; - } - - qdb->previous = NULL; - if ((qdb->next = QDBHandles.inUse) != NULL) { - QDBHandles.inUse->previous = qdb; - } - QDBHandles.inUse = qdb; - - XplSignalLocalSemaphore(QDBHandles.sem); - - qdb->flags |= QDBHANDLE_FLAG_INUSE; - - return(qdb); - } - - QDBHandles.stats.strikes++; - - XplSignalLocalSemaphore(QDBHandles.sem); - - qdb = (QDBHandle *)MemMalloc(sizeof(QDBHandle)); - if (qdb) { - memset(qdb, 0, sizeof(QDBHandle)); - - if (sqlite3_open(NMAP.path.qDomains, &(qdb->handle)) == SQLITE_OK) { - XplWaitOnLocalSemaphore(QDBHandles.sem); - - QDBHandles.eCount.allocated++; - if (QDBHandles.eCount.allocated < QDBHandles.eCount.maximum) { - qdb->flags = QDBHANDLE_FLAG_INUSE; - } else { - qdb->flags = QDBHANDLE_FLAG_INUSE | QDBHANDLE_FLAG_NON_POOLABLE; - } - - if ((qdb->next = QDBHandles.inUse) != NULL) { - QDBHandles.inUse->previous = qdb; - } - QDBHandles.inUse = qdb; - - XplSignalLocalSemaphore(QDBHandles.sem); - - return(qdb); - } - - if (qdb->handle) { - sqlite3_close(qdb->handle); - } - - MemFree(qdb); - } - - return(NULL); -#endif } void QDBHandleRelease(void *handle) { -#if 0 - QDBHandle *qdb = handle; - - qdb->flags &= ~QDBHANDLE_FLAG_INUSE; - - XplWaitOnLocalSemaphore(QDBHandles.sem); - if (qdb->next != NULL) { - qdb->next->previous = qdb->previous; - } - - if (qdb->previous != NULL) { - qdb->previous->next = qdb->next; - } else { - QDBHandles.inUse = qdb->next; - } - - if (!(qdb->flags & QDBHANDLE_FLAG_NON_POOLABLE)) { - qdb->previous = NULL; - if ((qdb->next = QDBHandles.available) != NULL) { - QDBHandles.available->previous = qdb; - } - - QDBHandles.available = qdb; - } else { - sqlite3_close(qdb->handle); - - MemFree(qdb); - } - - XplSignalLocalSemaphore(QDBHandles.sem); -#endif } int QDBAdd(void *handle, unsigned char *domain, unsigned long queueID, int queue) { return -1; - -#if 0 - int ccode; - char *errmsg = NULL; - char buffer[MAXEMAILNAMESIZE + 96]; - QDBHandle *qdb = (QDBHandle *)handle; - - sprintf(buffer, "INSERT INTO DOMAINS (DOMAIN, ENTRYID, ENTRYQ) VALUES ('%s', %lu, %d);", domain, queueID, queue); - ccode = sqlite3_exec(qdb->handle, buffer, NULL, NULL, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed to insert NMAP QDB '%s' %08x.%03d; error: \"%s\".\r\n", domain, (unsigned int)queueID, queue, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed to insert NMAP QDB '%s' %08x.%03d; error %d.\r\n", domain, (unsigned int)queueID, queue, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int QDBRemoveID(void *handle, unsigned long queueID) { return -1; - -#if 0 - int ccode; - char *errmsg = NULL; - char buffer[MAXEMAILNAMESIZE + 48]; - QDBHandle *qdb = (QDBHandle *)handle; - - sprintf(buffer, "DELETE FROM DOMAINS WHERE ENTRYID = %lu;", queueID); - ccode = sqlite3_exec(qdb->handle, buffer, NULL, NULL, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed to delete NMAP QDB entry %08x; error: \"%s\".\r\n", (unsigned int)queueID, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed to delete NMAP QDB entry %08x; error %d.\r\n", (unsigned int)queueID, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int QDBRemoveDomain(void *handle, unsigned char *domain) { return -1; - -#if 0 - int ccode; - char *errmsg = NULL; - char buffer[MAXEMAILNAMESIZE + 48]; - QDBHandle *qdb = (QDBHandle *)handle; - - sprintf(buffer, "DELETE FROM DOMAINS WHERE ENTRY = '%s';", domain); - ccode = sqlite3_exec(qdb->handle, buffer, NULL, NULL, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed to delete NMAP QDB entry \"%s\"; error: \"%s\".\r\n", domain, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed to delete NMAP QDB entry \"%s\"; error %d.\r\n", domain, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int -QDBSearchID(void *handle, unsigned long queueID, MDBValueStruct *vs) +QDBSearchID(void *handle, unsigned long queueID) { return -1; - -#if 0 - int ccode; - char *errmsg = NULL; - char buffer[MAXEMAILNAMESIZE + 48]; - QDBHandle *qdb = (QDBHandle *)handle; - - sprintf(buffer, "SELECT DOMAIN FROM DOMAINS WHERE ENTRYID = %lu;", queueID); - ccode = sqlite3_exec(qdb->handle, buffer, QDBSearchCB, (void *)vs, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry %08x; error: \"%s\".\r\n", (unsigned int)queueID, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry %08x; error %d.\r\n", (unsigned int)queueID, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int -QDBSearchDomain(void *handle, unsigned char *domain, MDBValueStruct *vs) +QDBSearchDomain(void *handle, unsigned char *domain) { return -1; -#if 0 - int ccode; - char *errmsg = NULL; - char buffer[MAXEMAILNAMESIZE + 48]; - QDBHandle *qdb = (QDBHandle *)handle; - - sprintf(buffer, "SELECT ENTRYID FROM DOMAINS WHERE DOMAIN = '%s';", domain); - ccode = sqlite3_exec(qdb->handle, buffer, QDBSearchCB, (void *)vs, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry \"%s\"; error: \"%s\".\r\n", domain, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry \"%s\"; error %d.\r\n", domain, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int QDBQuery(void *handle, unsigned char *query, QDBQueryResults *results) { return -1; -#if 0 - int ccode; - char *errmsg = NULL; - QDBHandle *qdb = (QDBHandle *)handle; - - ccode = sqlite3_exec(qdb->handle, query, QDBQueryResultsCB, (void *)results, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed query on NMAP QDB for \"%s\"; error: \"%s\".\r\n", query, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed query on NMAP QDB for \"%s\"; error %d.\r\n", query, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - if (ccode == SQLITE_OK) { - return(0); - } - - return(-1); -#endif } int QDBDump(unsigned char *domain) { return -1; - -#if 0 - int ccode; - unsigned long used; - unsigned long queueID; - unsigned long *idLock; - char *errmsg = NULL; - unsigned char path[XPL_MAX_PATH + 1]; - char buffer[MAXEMAILNAMESIZE + 48]; - MDBValueStruct *vs; - QDBHandle *qdb; - - if (domain) { - XplConsolePrintf("bongonmap: Removing queued entries for domain: %s\r\n", domain); - } else { - XplConsolePrintf("bongonmap: Removing all queued entries\r\n"); - } - - vs = MDBCreateValueStruct(NMAP.handle.directory, NULL); - if (vs) { - qdb = QDBHandleAlloc(); - } else { - LoggerEvent(NMAP.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_OUT_OF_MEMORY, LOG_CRITICAL, 0, __FILE__, NULL, sizeof(MDBValueStruct), 0, NULL, 0); - return(-1); - } - - if (qdb) { - if (domain) { - sprintf(buffer, "SELECT ENTRYID FROM DOMAINS WHERE DOMAIN = '%s';", domain); - } else { - strcpy(buffer, "SELECT ENTRYID FROM DOMAINS;"); - } - - ccode = sqlite3_exec(qdb->handle, buffer, QDBSearchCB, (void *)vs, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry \"%s\"; error: \"%s\".\r\n", domain, errmsg); - } else { - XplConsolePrintf("bongonmap: Failed search for NMAP QDB entry \"%s\"; error %d.\r\n", domain, ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - } else { - LoggerEvent(NMAP.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_OUT_OF_MEMORY, LOG_CRITICAL, 0, __FILE__, NULL, sizeof(QDBHandle), 0, NULL, 0); - return(-1); - } - - ccode = 0; - for (used = 0; (ccode != -1) && (used < vs->Used); used++) { - queueID = atol(vs->Value[used]); - - idLock = SpoolEntryIDLock(queueID); - if (idLock) { - sprintf(path, "%s/c%07x.007", NMAP.path.spool, queueID); - unlink(path); - - sprintf(path, "%s/d%s.msg", NMAP.path.spool, vs->Value[used]); - unlink(path); - - QDBRemoveID(qdb, queueID); - - XplSafeDecrement(NMAP.stats.queuedLocal.messages); - - SpoolEntryIDUnlock(idLock); - } - } - - QDBHandleRelease(qdb); - - MDBDestroyValueStruct(vs); - - return(used); -#endif } void QDBSummarizeQueue(void) { -#if 0 - int ccode; - unsigned long used; - char *errmsg; - unsigned char path[XPL_MAX_PATH + 1]; - FILE *fh; - MDBValueStruct *vs; - QDBHandle *qdb; - - vs = MDBCreateValueStruct(NMAP.handle.directory, NULL); - if (vs) { - qdb = QDBHandleAlloc(); - } else { - LoggerEvent(NMAP.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_OUT_OF_MEMORY, LOG_CRITICAL, 0, __FILE__, NULL, sizeof(MDBValueStruct), 0, NULL, 0); - return; - } - - if (qdb) { - ccode = sqlite3_exec(qdb->handle, "SELECT DOMAIN, COUNT(DOMAIN) FROM DOMAINS GROUP BY DOMAIN;", QDBSearchCB, (void *)vs, &errmsg); - if (ccode != SQLITE_OK) { - if (errmsg) { - XplConsolePrintf("bongonmap: Failed count for NMAP QDB domains; error: \"%s\".\r\n", errmsg); - } else { - XplConsolePrintf("bongonmap: Failed count for NMAP QDB domains; error %d.\r\n", ccode); - } - } - - if (errmsg) { - sqlite3_free(errmsg); - } - - QDBHandleRelease(qdb); - } else { - LoggerEvent(NMAP.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_OUT_OF_MEMORY, LOG_CRITICAL, 0, __FILE__, NULL, sizeof(QDBHandle), 0, NULL, 0); - return; - } - - if (vs->Used) { - sprintf(path, "%s/queue.ims", NMAP.path.dbf); - fh = fopen(path, "wb"); - if (fh) { - fprintf(fh, "Domains:\r\n"); - - ccode = 0; - for (used = 0; (ccode != -1) && (used < vs->Used); used += 2) { - fprintf(fh, "[%6lu] %s\r\n", atol(vs->Value[used + 1]), vs->Value[used]); - } - - fclose(fh); - } - } - - MDBDestroyValueStruct(vs); -#endif -} +} \ No newline at end of file diff --git a/src/agents/queue/domain.h b/src/agents/queue/domain.h index e13e989..82edd8f 100644 --- a/src/agents/queue/domain.h +++ b/src/agents/queue/domain.h @@ -1,19 +1,9 @@ #ifndef DOMAIN_H #define DOMAIN_H -#include "mdb.h" - typedef struct _QDBQueryResults { - struct { - unsigned long count; - MDBValueStruct *names; - } column; - struct { - unsigned long count; - MDBValueStruct *values; - } row; } QDBQueryResults; @@ -24,8 +14,8 @@ void QDBHandleRelease(void *handle); int QDBAdd(void *handle, unsigned char *domain, unsigned long queueID, int queue); int QDBRemoveID(void *handle, unsigned long queueID); int QDBRemoveDomain(void *handle, unsigned char *domain); -int QDBSearchID(void *handle, unsigned long queueID, MDBValueStruct *vs); -int QDBSearchDomain(void *handle, unsigned char *domain, MDBValueStruct *vs); +int QDBSearchID(void *handle, unsigned long queueID); +int QDBSearchDomain(void *handle, unsigned char *domain); int QDBQuery(void *handle, unsigned char *query, QDBQueryResults *results); int QDBDump(unsigned char *domain); void QDBSummarizeQueue(void); diff --git a/src/agents/queue/messages.h b/src/agents/queue/messages.h index c7ea5b1..4c36b55 100644 --- a/src/agents/queue/messages.h +++ b/src/agents/queue/messages.h @@ -109,8 +109,23 @@ #define NMAP_QFLUSH_COMMAND "QFLUSH" #define NMAP_QFLUSH_HELP "QFLUSH - Attempt to deliver all queued mail.\r\n" -#define MSG1000READY "Bongo NMAP server ready" -#define MSG1000BYE "Bongo NMAP signing off" +/* --------------------------------------------------- */ +#define NMAP_ADDRESS_RESOLVE_COMMAND "ADDRESS RESOLVE" +#define NMAP_ADDRESS_RESOLVE_HELP "ADDRESS RESOLVE - Determine if an email address is local or remote and resolve any aliasing.\r\n" + +#define NMAP_DOMAIN_LOCATION_COMMAND "DOMAIN LOCATION" +#define NMAP_DOMAIN_LOCATION_HELP "DOMAIN LOCATION - Determine if a domain is local or remote.\r\n" + +#define MSG1000LOCAL "1000 LOCAL %s" +#define MSG1001RELAY "1001 RELAY %s" +#define MSG1002REMOTE "1002 REMOTE %s" +#define MSG4001NO_USER "4001 Invalid address %s" +#define MSG4000LOOP "4000 Aliasing loop" +#define MSG4000UNKNOWN_TYPE "4000 Unknown mapping type" +/* --------------------------------------------------- */ + +#define MSG1000READY "bongoqueue server ready" +#define MSG1000BYE "bongoqueue signing off" #define MSG1000LOGINOK "1000 Login ok\r\n" #define MSG1000FLAGSET "Flags set" #define MSG1000FLAGINFO "Current Flags" @@ -242,8 +257,8 @@ #define MSG4230PATHTOOLONG "4230 Path exceeds allowed length\r\n" #define MSG4240NOPERMISSION "4240 Permission denied\r\n" #define MSG4241AUTHDONE "4241 Already authenticated\r\n" -#define MSG4242AUTHREQUIRED "4242 NMAP <%s>\r\n" -#define MSG4242AUTHREQUIREDF "4242 NMAP <%x%s%x>\r\n" +#define MSG4242AUTHREQUIRED "4242 bongoqueue <%s>\r\n" +#define MSG4242AUTHREQUIREDF "4242 bongoqueue <%x%s%x>\r\n" #define MSG4260NOQENTRY "4260 No queue entry open, try QCREA\r\n" #define MSG4261NODOMAIN "4261 No queue entry with that domain\r\n" #define MSG4262NOTFOUND "4262 Field/Content not found\r\n" diff --git a/src/agents/queue/queue.c b/src/agents/queue/queue.c index 81bf231..5262d8d 100644 --- a/src/agents/queue/queue.c +++ b/src/agents/queue/queue.c @@ -17,6 +17,7 @@ * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * + * (C) 2007 Patrick Felt ****************************************************************************/ #include @@ -28,7 +29,6 @@ #include #include -#include #include #include @@ -294,7 +294,7 @@ SpoolEntryIDLock(unsigned long id) XplSignalLocalSemaphore(Queue.spoolLocks.semaphores[SPOOL_LOCK_ARRAY_MASK & id]); - Log(LOG_INFO, "Unable to lock spool entry %x, table full", (unsigned int) id); + Log(LOG_ERROR, "Unable to lock spool entry %x, table full", (unsigned int) id); } return(NULL); @@ -356,7 +356,7 @@ AddPushAgent(QueueClient *client, int count; QueuePushClient *temp; - Log(LOG_INFO, "Adding client on host %s:%d to queue %d", LOGIP(client->conn->socketAddress), port, queue); + Log(LOG_INFO, "Adding client (%s) on host %s:%d to queue %d", identifier, LOGIP(client->conn->socketAddress), port, queue); XplMutexLock(Queue.pushClients.lock); @@ -499,7 +499,7 @@ GetNMAPConnection(NMAPConnections *list, conn = NMAPConnect(NULL, address); if (conn == NULL) { - XplConsolePrintf("bongoqueue: Couldn't connect to NMAP\r\n"); + Log(LOG_ERROR, "Could not connect to bongoqueue."); return DELIVER_TRY_LATER; } @@ -573,8 +573,6 @@ DeliverToStore(NMAPConnections *list, (ccode = ConnFlush(nmap->conn)) == -1) { nmap->error = TRUE; - FCLOSE_CHECK(fh); - return DELIVER_TRY_LATER; } } @@ -677,7 +675,6 @@ ProcessQueueEntry(unsigned char *entryIn) FILE *data = NULL; FILE *newFH = NULL; MIMEReportStruct *report = NULL; - MDBValueStruct *vs; QueueClient *client; void *handle; @@ -876,8 +873,7 @@ StartOver: return(TRUE); } - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - +/* TODO: look this over to make sure this is still valid */ count = 0; cur = qEnvelope; while (cur < limit) { @@ -897,47 +893,7 @@ StartOver: } case QUEUE_RECIP_LOCAL: - case QUEUE_RECIP_MBOX_LOCAL: { - if (ptr) { - *ptr = '\0'; - } - - ptr2 = strchr(cur + 1, ' '); - if (ptr2) { - *ptr2 = '\0'; - } - - if (MsgFindObject(cur + 1, NULL, NULL, NULL, vs)) { - if (ptr2) { - for (used = 0; (used < vs->Used); used++) { - fprintf(newFH, "%c%s %s\n", *cur, vs->Value[used], ptr2 + 1); - count++; - } - } else { - for (used = 0; (used < vs->Used); used++) { - fprintf(newFH, "%c%s %s %d\r\n", *cur, vs->Value[used], vs->Value[used], DSN_FAILURE); - count++; - } - } - - MDBFreeValues(vs); - } else { - Log(LOG_INFO, "Entry %ld queue %d, can't find %s", entryID, queue, cur + 1); - - if (ptr2) { - *ptr2 = ' '; - } - - if (ptr) { - *ptr = '\n'; - } - - fwrite(cur, sizeof(unsigned char), next - cur, newFH); - } - - break; - } - + case QUEUE_RECIP_MBOX_LOCAL: case QUEUE_RECIP_REMOTE: { if (ptr) { *ptr = '\0'; @@ -948,13 +904,45 @@ StartOver: *ptr2 = '\0'; } - if (ptr2) { - fprintf(newFH, QUEUES_RECIP_REMOTE"%s %s\n", cur + 1, ptr2 + 1); - } else { - fprintf(newFH, QUEUES_RECIP_REMOTE"%s %s %d\r\n", cur + 1, cur + 1, DSN_FAILURE); - } + /* alias this user */ + unsigned char buffer[1024]; /* FIXME: is this too big? */ + unsigned char *addrptr; + unsigned char *flags = strchr(ptr2+1,' '); /* the original flags */ + int cnt; - break; + aliasing(cur+1, &cnt, buffer); + + /* find the address in teh result buffer so that we can rewrite it properly */ + addrptr = strrchr(buffer, ' '); + addrptr++; + switch(atoi(buffer)) { + case 1000: + /* this is a local user, change the envelope to reflect that + * in this case ptr2+1 is the orecip which will also include the flags */ + fprintf(newFH, QUEUES_RECIP_LOCAL"%s %s\r\n", addrptr, ptr2+1); + break; + case 1002: + /* in this case ptr2+1 is the orecip which will also contain the flags */ + fprintf(newFH, QUEUES_RECIP_REMOTE"%s %s\r\n", addrptr, ptr2+1); + break; + default: + /* in this case we need to chop the flags off so that we can replace them + * with DSN_FAILURE */ + if (flags) { + *flags = '\0'; + } + fprintf(newFH, "%c%s %s %d\r\n", *cur, addrptr, ptr2+1, DSN_FAILURE); + if (flags) { + *flags = ' '; + } + break; + } + if (ptr) { + *ptr = '\n'; + } + if (ptr2) { + *ptr2 = ' '; + } } case QUEUE_ADDRESS: @@ -975,8 +963,6 @@ StartOver: cur = next; } - MDBDestroyValueStruct(vs); - MemFree(qEnvelope); FCLOSE_CHECK(newFH); @@ -1068,6 +1054,7 @@ StartOver: sprintf(dataFilename, "d%s.msg", entry); if (!dSize) { + sprintf(path, "%s/%s", Conf.spoolPath, dataFilename); if (stat(path, &sb)) { ProcessQueueEntryCleanUp(idLock, report); return(TRUE); @@ -1172,18 +1159,17 @@ StartOver: *ptr = ' '; } - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - if (!MsgFindObject(recipient, NULL, NULL, &siaddr, vs)) { + if (MsgAuthFindUser(recipient) != 0) { Log(LOG_WARNING, "User %s unknown, entry %ld", recipient, entryID); status = DELIVER_USER_UNKNOWN; } else { + MsgAuthGetUserStore(recipient, &siaddr); Log(LOG_DEBUG, "Delivering %s on queue %d to %s", entry, queue, line+1); status = DeliverToStore(&list, &siaddr, NMAP_DOCTYPE_CAL, sender, authenticatedSender, dataFilename, data, dSize, recipient, mailbox, flags); if (Agent.agent.state == BONGO_AGENT_STATE_STOPPING) { status = DELIVER_TRY_LATER; } } - MDBDestroyValueStruct(vs); /* Restore our buffer */ if (ptr2) { @@ -1221,7 +1207,7 @@ StartOver: while (ptr[0]!='\0') { if (ptr[0]==' ') { i++; - if (i > 2) { + if (i > 2) { switch(i) { case 3: { preMailboxDelim = ptr; @@ -1278,8 +1264,8 @@ StartOver: } /* Attempt delivery, check if local or remote */ - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - if (MsgFindObject(recipient, NULL, NULL, &siaddr, vs)) { + if (MsgAuthFindUser(recipient) == 0) { + MsgAuthGetUserStore(recipient, &siaddr); Log(LOG_DEBUG, "Deliver to store entry %s in queue %d for host %s", entry, queue, LOGIP(siaddr)); status = DeliverToStore(&list, &siaddr, NMAP_DOCTYPE_MAIL, sender, authenticatedSender, dataFilename, data, dSize, recipient, mailbox, messageFlags); @@ -1318,8 +1304,6 @@ StartOver: } } - MDBDestroyValueStruct(vs); - if (status < DELIVER_SUCCESS) { Log(LOG_WARNING, "Couldn't deliver entry %s on queue %d, status %d", entry, queue, status); if ((status == DELIVER_USER_UNKNOWN) || (status == DELIVER_INTERNAL_ERROR) || (status == DELIVER_QUOTA_EXCEEDED)) { @@ -1611,6 +1595,9 @@ StartOver: saddr.sin_addr.s_addr = Queue.pushClients.array[used].address; saddr.sin_port = Queue.pushClients.array[used].port; + /* FIXME: this is the lazy fix until we can figure this out */ + memcpy(&(client->conn->socketAddress), &saddr, sizeof(struct sockaddr)); + len = connect(client->conn->socket, (struct sockaddr *)&saddr, sizeof(saddr)); if (!len) { /* Non-blocking, w/o nagele */ @@ -1641,6 +1628,7 @@ StartOver: return(TRUE); } + Log(LOG_DEBUG, "Handing off to agent queue %d", queue); /* We got a connection to the guy, tell him what to do */ ConnWriteF(client->conn, "6020 %03d-%s %ld %ld %ld\r\n", queue, entry, (unsigned long)sb.st_size, dSize, lines); ConnWriteFile(client->conn, fh); @@ -1663,10 +1651,7 @@ StartOver: /* fixme - evaluate this section. Clean up behind us ? */ if (client->entry.work) { - if (Agent.flags & QUEUE_AGENT_DEBUG) { - XplConsolePrintf("bongoqueue: Ran into queue resend [C%s.%03d]!\r\n", entry, queue); - XplConsolePrintf("bongoqueue: Last command:%s\r\n", client->buffer); - } + Log(LOG_DEBUG, "Ran into queue resend [C%s.%03d] Last Command: %s", entry, queue, client->buffer); FCLOSE_CHECK(client->entry.work); client->entry.work = NULL; @@ -2021,7 +2006,6 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO unsigned char *transcript; unsigned char timeLine[80]; unsigned char line[CONN_BUFSIZE + 1]; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; unsigned char postmaster[MAXEMAILNAMESIZE + 1]; unsigned char sender[MAXEMAILNAMESIZE + 1]; unsigned char aSender[MAXEMAILNAMESIZE + 1] = ""; @@ -2031,7 +2015,6 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO BOOL mBounce=FALSE; BOOL header; time_t now; - MDBValueStruct *vs; /* Step 0, check if we want to bounce at all */ now = time(NULL); @@ -2104,10 +2087,14 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO return(FALSE); } - sprintf(postmaster, "%s@%s", Conf.postMaster, Conf.officialName); + sprintf(postmaster, "%s@%s", BongoGlobals.postmaster, BongoGlobals.hostname); handling = Conf.bounceHandling; /* We're guaranteed to have a recipient */ +/* TODO: fix postmaster */ + +// REMOVE-MDB +#if 0 ptr = strchr(recipient, '@'); if (ptr) { if (MsgDomainExists(ptr + 1, dn)) { @@ -2140,15 +2127,16 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO MDBDestroyValueStruct(vs); } } +#endif /* Step 2, create the bounce; we've got all information */ MsgGetRFC822Date(-1, 0, timeLine); fprintf(rtsData, "Date: %s\r\n", timeLine); fprintf(rtsData, "From: Mail Delivery System <%s>\r\n", postmaster); - fprintf(rtsData, "Message-Id: <%lu-%lu@%s>\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "Message-Id: <%lu-%lu@%s>\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); fprintf(rtsData, "To: <%s>\r\n", sender); - fprintf(rtsData, "MIME-Version: 1.0\r\nContent-Type: multipart/report; report-type=delivery-status;\r\n\tboundary=\"%lu-%lu-%s\"\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "MIME-Version: 1.0\r\nContent-Type: multipart/report; report-type=delivery-status;\r\n\tboundary=\"%lu-%lu-%s\"\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); switch (reason) { case DELIVER_FAILURE: fprintf(rtsData, "Subject: Returned mail: Delivery failure\r\n"); break; case DELIVER_HOST_UNKNOWN: fprintf(rtsData, "Subject: Returned mail: Host unknown\r\n"); break; @@ -2173,7 +2161,7 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO fprintf(rtsData, "Precedence: bulk\r\n\r\nThis is a MIME-encapsulated message\r\n\r\n"); /* First section, human readable */ - fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: text/plain; charset=US-ASCII\r\n\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: text/plain; charset=US-ASCII\r\n\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); MsgGetRFC822Date(-1, received, timeLine); fprintf(rtsData, "The original message was received %s\r\nfrom %s\r\n\r\n", timeLine, aSender[0]!='\0' ? aSender : sender); @@ -2341,14 +2329,14 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO } while (!feof(control) && !ferror(control)); /* Second section, computer readable */ - fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: message/delivery-status\r\n\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: message/delivery-status\r\n\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); /* Per message fields */ if (envID[0]!='\0') { fprintf(rtsData, "Original-Envelope-Id: %s\r\n", envID); } - fprintf(rtsData, "Reporting-MTA: dns; %s\r\n", Conf.officialName); + fprintf(rtsData, "Reporting-MTA: dns; %s\r\n", BongoGlobals.hostname); MsgGetRFC822Date(-1, received, timeLine); fprintf(rtsData, "Arrival-Date: %s\r\n", timeLine); @@ -2409,7 +2397,7 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO } while (!feof(control) && !ferror(control)); /* Third section, original message */ - fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: message/rfc822\r\n\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "--%lu-%lu-%s\r\nContent-type: message/rfc822\r\n\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); header = TRUE; maxBodySize = -1; @@ -2447,7 +2435,7 @@ CreateDSNMessage(FILE *data, FILE *control, FILE *rtsData, FILE *rtsControl, BOO } /* End of message */ - fprintf(rtsData, "\r\n--%lu-%lu-%s--\r\n", now, (long unsigned int)XplGetThreadID(), Conf.officialName); + fprintf(rtsData, "\r\n--%lu-%lu-%s--\r\n", now, (long unsigned int)XplGetThreadID(), BongoGlobals.hostname); /* Now create the control file */ fprintf(rtsControl, "D%lu\r\n", now); @@ -2563,17 +2551,13 @@ CheckQueue(void *queueIn) Queue.restartNeeded = Queue.flushNeeded = FALSE; if (flushing) { - XplConsolePrintf ("bongoqueue: flushing the queue\n"); - } - - if (Agent.flags & QUEUE_AGENT_DEBUG) { - XplConsolePrintf("bongoqueue: Restarting queue:"); - } - - if (!flushing) { + Log(LOG_INFO, "Flushing the queue."); + } else { now = time(NULL) - Conf.queueInterval + 60; } + Log(LOG_DEBUG, "Restarting the queue"); + dirP = XplOpenDir(Conf.spoolPath); if (dirP == NULL) { goto delayQueue; @@ -2617,12 +2601,10 @@ CheckQueue(void *queueIn) } XplCloseDir(dirP); - if (Agent.flags & QUEUE_AGENT_DEBUG) { - XplConsolePrintf(" Entries found: %4lu, handled:%4lu, %srestart\r\n", found, handled, Queue.restartNeeded ? "Have " : "No "); - } + Log(LOG_DEBUG, "Entries found: %4lu, handled: %4lu, %srestart", found, handled, Queue.restartNeeded ? "Have " : "No "); if (flushing) { - XplConsolePrintf ("bongoqueue: finished flushing the queue\n"); + Log(LOG_INFO, "Finished flushing the queue."); } delayQueue: @@ -2637,9 +2619,7 @@ CheckQueue(void *queueIn) XplSafeDecrement(Queue.activeWorkers); -#if VERBOSE - XplConsolePrintf("bongoqueue: Message queue monitor done.\r\n"); -#endif + Log(LOG_DEBUG, "Message queue monitor done."); XplExitThread(EXIT_THREAD, 0); @@ -2650,7 +2630,7 @@ BOOL QueueInit(void) { if (!InitSpoolEntryIDLocks()) { - XplConsolePrintf(AGENT_NAME ": Couldn't create spool locks.\r\n"); + Log(LOG_ERROR, "Could not create spool locks."); return FALSE; } @@ -2672,9 +2652,7 @@ QueueInit(void) void QueueShutdown(void) { -#if VERBOSE - XplConsolePrintf("bongoqueue: Writing queue agent list\r\n"); -#endif + Log(LOG_DEBUG, "Writing queue agent list."); RemoveAllPushAgents(); QDBShutdown(); @@ -2704,19 +2682,16 @@ CreateQueueThreads(BOOL failed) } if (failed) { - XplConsolePrintf("bongoqueue: System not shut down properly, verifying queue integrity.\r\n"); + Log(LOG_INFO, "System not shut down properly, verifying queue integrity."); + } else { + Log(LOG_DEBUG, "Verifying queue integrity, quick mode."); } -#if VERBOSE - else { - XplConsolePrintf("bongoqueue: Verifying queue integrity, quick mode.\r\n"); - } -#endif sprintf(path, "%s", Conf.spoolPath); dirP = XplOpenDir(path); - sprintf(path, "%s/fragfile", MsgGetDBFDir(NULL)); + sprintf(path, "%s/fragfile", MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); FOPEN_CHECK(killFile, path, "wb"); if (!killFile) { if (dirP) { @@ -2839,14 +2814,12 @@ CreateQueueThreads(BOOL failed) killFile=NULL; } -#if VERBOSE - XplConsolePrintf("bongoqueue: Queue integrity check complete, now cleaning irrelevant entries.\r\n"); -#endif + Log(LOG_DEBUG, "Queue integrity check complete, now cleaning irrelevant entries."); - sprintf(path, "%s/fragfile", MsgGetDBFDir(NULL)); + sprintf(path, "%s/fragfile", MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); FOPEN_CHECK(killFile, path, "rb"); if (!killFile) { - XplConsolePrintf("bongoqueue: Could not re-open killfile.\r\n"); + Log(LOG_ERROR, "Could not re-open killfile."); } else { current = 0; while (!feof(killFile) && !ferror(killFile)) { @@ -2861,7 +2834,7 @@ CreateQueueThreads(BOOL failed) FCLOSE_CHECK(killFile); } - sprintf(path, "%s/killfile", MsgGetDBFDir(NULL)); + sprintf(path, "%s/killfile", MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); UNLINK_CHECK(path); XplCloseDir(dirP); @@ -2900,13 +2873,13 @@ CreateQueueThreads(BOOL failed) } } -#if VERBOSE - XplConsolePrintf("bongoqueue: Queue integrity check complete, starting Queue Monitor [%d].\r\n", XplSafeRead(Queue.queuedLocal)); -#endif + Log(LOG_DEBUG, "Queue integrity check complete, starting Queue Monitor [%d].", XplSafeRead(Queue.queuedLocal)); XplSafeWrite(Queue.activeWorkers, 0); - XplBeginCountedThread(&id, CheckQueue, STACKSPACE_Q, NULL, i, Agent.activeThreads); + if (!Conf.debug) { + XplBeginCountedThread(&id, CheckQueue, STACKSPACE_Q, NULL, i, Agent.activeThreads); + } return(0); } @@ -2972,16 +2945,13 @@ CommandQaddm(void *param) if (data) { NMAPConnections list = { 0, }; struct sockaddr_in saddr; - MDBValueStruct *vs; - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - - if (MsgFindObject(recipient, NULL, NULL, &saddr, vs)) { - result = DeliverToStore(&list, &saddr, NMAP_DOCTYPE_MAIL, sender, authSender, client->path, data, sb.st_size, recipient, mailbox, 0); - EndStoreDelivery(&list); + if (MsgAuthFindUser(recipient) == 0) { + if (MsgAuthGetUserStore(recipient, &saddr) == TRUE) { + result = DeliverToStore(&list, &saddr, NMAP_DOCTYPE_MAIL, sender, authSender, client->path, data, sb.st_size, recipient, mailbox, 0); + EndStoreDelivery(&list); + } } - MDBDestroyValueStruct(vs); - } else { return(ConnWrite(client->conn, MSG4224CANTREAD, sizeof(MSG4224CANTREAD) - 1)); } @@ -4260,24 +4230,17 @@ int CommandQsrchDomain(void *param) { int ccode; - unsigned long used; unsigned char *ptr; void *handle = NULL; - MDBValueStruct *vs = NULL; QueueClient *client = (QueueClient *)param; ptr = client->buffer + 12; /* QSRCH DOMAIN */ if ((*ptr++ == ' ') && (!isspace(*ptr))) { - if (((vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL)) != NULL) - && ((handle = QDBHandleAlloc()) != NULL)) { - ccode = QDBSearchDomain(handle, ptr, vs); + if ((handle = QDBHandleAlloc()) != NULL) { + ccode = QDBSearchDomain(handle, ptr); if (!ccode) { - for (used = 0; (ccode != -1) && (used < vs->Used); used++) { - ccode = ConnWriteF(client->conn, "2001-007-%s\r\n", vs->Value[used]); - } - if (ccode != -1) { ccode = ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1); } @@ -4290,10 +4253,6 @@ CommandQsrchDomain(void *param) ccode = ConnWrite(client->conn, MSG5230NOMEMORYERR, sizeof(MSG5230NOMEMORYERR) - 1); } - if (vs) { - MDBDestroyValueStruct(vs); - } - if (handle) { QDBHandleRelease(handle); } @@ -4704,6 +4663,16 @@ CommandQstorMessage(void *param) } MsgGetRFC822Date(-1, 0, TimeBuf); + fprintf(client->entry.data, + "Received: from %s (%d.%d.%d.%d) by %s\r\n\twith NMAP (bongoqueue Agent); %s\r\n", + BongoGlobals.hostname, /* FIXME: this should eventually be the remote hsotname of the agent */ + client->conn->socketAddress.sin_addr.s_net, + client->conn->socketAddress.sin_addr.s_host, + client->conn->socketAddress.sin_addr.s_lh, + client->conn->socketAddress.sin_addr.s_impno, + BongoGlobals.hostname, + TimeBuf); +/* fprintf(client->entry.data, "Received: from %d.%d.%d.%d [%d.%d.%d.%d] by %s\r\n\twith NMAP (%s); %s\r\n", client->conn->socketAddress.sin_addr.s_net, @@ -4716,10 +4685,10 @@ CommandQstorMessage(void *param) client->conn->socketAddress.sin_addr.s_lh, client->conn->socketAddress.sin_addr.s_impno, - Agent.agent.officialName, + BongoGlobals.hostname, AGENT_NAME, TimeBuf); - +*/ if (count) { ccode = ConnReadToFile(client->conn, client->entry.data, count); } else { @@ -4800,7 +4769,7 @@ CommandQwait(void *param) && ((identifier = strchr(ptr + 1, ' ')) != NULL) && (identifier[1]) && (!isspace(identifier[1])) - && (strlen(identifier + 1) < MDB_MAX_OBJECT_CHARS)) { + && (strlen(identifier + 1) < 100)) { // FIXME: REMOVE-MDB 100 was MDB maximum object identifier length *ptr++ = '\0'; *identifier++ = '\0'; diff --git a/src/agents/queue/queue.h b/src/agents/queue/queue.h index e1cf148..6e579a6 100644 --- a/src/agents/queue/queue.h +++ b/src/agents/queue/queue.h @@ -36,7 +36,7 @@ typedef struct _QueuePushClient { unsigned long usageCount; unsigned long errorCount; - unsigned char identifier[MDB_MAX_OBJECT_CHARS + 1]; + unsigned char identifier[101]; } QueuePushClient; typedef struct _Queue { diff --git a/src/agents/queue/queued.c b/src/agents/queue/queued.c index 95eee42..e887c32 100644 --- a/src/agents/queue/queued.c +++ b/src/agents/queue/queued.c @@ -27,8 +27,6 @@ #include #include #include -#include -#include #include #include #include @@ -44,12 +42,17 @@ static int CommandAuth(void *param); static int CommandPass(void *param); static int CommandQuit(void *param); static int CommandHelp(void *param); +static int CommandAddressResolve(void *param); +static int CommandDomainLocation(void *param); +int aliasFindFunc(const void *str, const void *node); static ProtocolCommand authCommands[] = { { NMAP_AUTH_COMMAND, NMAP_AUTH_HELP, sizeof(NMAP_AUTH_COMMAND) - 1, CommandAuth, NULL, NULL }, { NMAP_HELP_COMMAND, NMAP_HELP_HELP, sizeof(NMAP_HELP_COMMAND) - 1, CommandHelp, NULL, NULL }, { NMAP_PASS_COMMAND, NMAP_PASS_HELP, sizeof(NMAP_PASS_COMMAND) - 1, CommandPass, NULL, NULL }, { NMAP_QUIT_COMMAND, NMAP_QUIT_HELP, sizeof(NMAP_QUIT_COMMAND) - 1, CommandQuit, NULL, NULL }, + { NMAP_ADDRESS_RESOLVE_COMMAND, NMAP_ADDRESS_RESOLVE_HELP, sizeof(NMAP_ADDRESS_RESOLVE_COMMAND) -1, CommandAddressResolve, NULL, NULL }, + { NMAP_DOMAIN_LOCATION_COMMAND, NMAP_DOMAIN_LOCATION_HELP, sizeof(NMAP_DOMAIN_LOCATION_COMMAND) -1, CommandDomainLocation, NULL, NULL }, { NULL, NULL, 0, NULL, NULL, NULL } }; @@ -95,9 +98,176 @@ static ProtocolCommand commands[] = { { NMAP_QUIT_COMMAND, NMAP_QUIT_HELP, sizeof(NMAP_QUIT_COMMAND) - 1, CommandQuit, NULL, NULL }, { NMAP_QWAIT_COMMAND, NMAP_QWAIT_HELP, sizeof(NMAP_QWAIT_COMMAND) - 1, CommandQwait, NULL, NULL }, { NMAP_QFLUSH_COMMAND, NMAP_QFLUSH_HELP, sizeof(NMAP_QFLUSH_COMMAND) -1, CommandQflush, NULL, NULL }, + { NMAP_ADDRESS_RESOLVE_COMMAND, NMAP_ADDRESS_RESOLVE_HELP, sizeof(NMAP_ADDRESS_RESOLVE_COMMAND) -1, CommandAddressResolve, NULL, NULL }, + { NMAP_DOMAIN_LOCATION_COMMAND, NMAP_DOMAIN_LOCATION_HELP, sizeof(NMAP_DOMAIN_LOCATION_COMMAND) -1, CommandDomainLocation, NULL, NULL }, { NULL, NULL, 0, NULL, NULL, NULL } }; +int aliasFindFunc(const void *str, const void *node) { + AliasStruct *n = (AliasStruct *)(node); + return strcasecmp((char *)str, n->original); +} + +int hostedFindFunc(const void *str1, const void *str2) { + int i = strcasecmp((char *)str1, *(char **)str2); + return i; +} + +/* TODO: error handling on MsgParseAddress() */ +/* mapping types + * 0: username == local + * 1: username == local@domain + * 2: username == domain + * 3: username == auth subsystem +*/ +BOOL aliasing(char *addr, int *cnt, unsigned char *buffer) { + unsigned char *local = NULL; + unsigned char *domain = NULL; + int i=-1; + BOOL result=FALSE; + + if (addr[0] == '\0') { + sprintf(buffer, MSG4001NO_USER, ""); + return TRUE; + } + + /* very rudimentary way to prevent loops */ + if (*cnt > 5) { + strcpy(buffer, MSG4000LOOP); + return TRUE; + } + + (*cnt)++; + + /* first parse out the address so that i can loop over the domains */ + MsgParseAddress(addr, strlen(addr), &local, &domain); + + if (local && !domain) { + /* if i get here, then i don't have a domain. assume this is the username. the only possible + * choices here are type 0 and type 3 */ + if (MsgAuthFindUser(local) == 0) { + sprintf(buffer, MSG1000LOCAL, local); + result = TRUE; + goto ExitAliasing; + } else { + /* the user was not found. it must be an invalid user */ + sprintf(buffer, MSG4001NO_USER, local); + result = TRUE; + goto ExitAliasing; + } + } + + /* if i get here, i've got a domain name that i can look up in the alias system */ + i = BongoArrayFindSorted(Conf.aliasList, domain, (ArrayCompareFunc)aliasFindFunc); + if (i > -1) { + char new_addr[1000]; /* FIXME: seems a bit large */ + AliasStruct a; + + new_addr[0] = '\0'; + a = BongoArrayIndex(Conf.aliasList, AliasStruct, i); + + /* user aliases should take precedence over domain aliases. check for one of those first */ + if (a.aliases && a.aliases->len && ((i = BongoArrayFindSorted(a.aliases, local, (ArrayCompareFunc)aliasFindFunc)) > -1)) { + AliasStruct b; + b = BongoArrayIndex(a.aliases, AliasStruct, i); + result = aliasing(b.to, cnt, buffer); + } else if (a.to && a.to[0] != '\0') { + /* there are no user aliasess is there a domain alias? */ + snprintf(new_addr, 999, "%s@%s", local, a.to); + result = aliasing(new_addr, cnt, buffer); + } + + /* we haven't already handled the address. it must be a local address */ + if (result == FALSE) { + /* based off the mapping_type of the current domain (a), i need to resolve username now */ + switch (a.mapping_type) { + case 0: + if (MsgAuthFindUser(local) == 0) { + sprintf(buffer, MSG1000LOCAL, local); + result = TRUE; + } + break; + case 1: + if (MsgAuthFindUser(addr) == 0) { + sprintf(buffer, MSG1000LOCAL, addr); + result = TRUE; + } + break; + case 2: + if (MsgAuthFindUser(domain) == 0) { + sprintf(buffer, MSG1000LOCAL, domain); + result = TRUE; + } + break; + case 3: + /* unhandled for now */ + strcpy(buffer, MSG4000UNKNOWN_TYPE); + result = TRUE; + break; + default: + /* unhandled forever */ + strcpy(buffer, MSG4000UNKNOWN_TYPE); + result = TRUE; + break; + } + } + + /* if we still haven't resolved the address, it is an unknown user */ + if (result == FALSE) { + sprintf(buffer, MSG4001NO_USER, addr); + result = TRUE; + } + } else { + /* the user must be remote */ + sprintf(buffer, MSG1002REMOTE, addr); + result = TRUE; + goto ExitAliasing; + } + + ExitAliasing: + if (local) { + MemFree(local); + } + + if (domain) { + MemFree(domain); + } + + return result; +} + +int CommandAddressResolve(void *param) { + BOOL handled=FALSE; + int cnt=0; + unsigned char buffer[1024]; /* FIXME: is this too big? */ + QueueClient *client = (QueueClient *)param; + + handled = aliasing(client->buffer + 16, &cnt, &buffer); + if (!handled) { + ConnWriteF(client->conn, MSG4001NO_USER"\r\n", client->buffer + 16); + } else { + ConnWriteF(client->conn, "%s\r\n", buffer); + } + return 0; +} + +int CommandDomainLocation(void *param) { + QueueClient *client = (QueueClient *)param; + + /* first find the domain in the request */ + unsigned char *domain = client->buffer + 16; + + /* now search for it */ + int idx = BongoArrayFindSorted(Conf.hostedDomains, domain, (ArrayCompareFunc)hostedFindFunc); + if (idx > -1) { + ConnWriteF(client->conn, MSG1000LOCAL"\r\n", domain); + } else { + /* TODO: add the relay domain stuff */ + ConnWriteF(client->conn, MSG1002REMOTE"\r\n", domain); + } + return 0; +} + int CommandAuth(void *param) { @@ -136,9 +306,8 @@ CommandPass(void *param) { unsigned char *ptr; unsigned char *pass; - BOOL result; + int result; struct sockaddr_in nmap; - MDBValueStruct *vs; QueueClient *client = (QueueClient *)param; ptr = client->buffer + 4; @@ -155,20 +324,9 @@ CommandPass(void *param) ptr += 5; *pass++ = '\0'; - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - if (vs) { - result = MsgFindObject(ptr, client->line, NULL, &nmap, vs); - } else { - return(ConnWrite(client->conn, MSG5001NOMEMORY, sizeof(MSG5001NOMEMORY) - 1)); - } + result = MsgAuthVerifyPassword(ptr, pass); - if (result) { - result = MDBVerifyPassword(client->line, pass, vs); - } - - MDBDestroyValueStruct(vs); - - if (result && (nmap.sin_addr.s_addr == MsgGetHostIPAddress())) { + if ((result==0) && (nmap.sin_addr.s_addr == MsgGetHostIPAddress())) { return(ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1)); } else { return(ConnWrite(client->conn, MSG4120USERLOCKED, sizeof(MSG4120USERLOCKED) - 1)); @@ -265,18 +423,15 @@ QueueClientFree(void *clientp) static BOOL CheckTrustedHost(QueueClient *client) { - int i; + int i = 0; - XplRWReadLockAcquire(&Conf.lock); - for (i = 0; i < Conf.trustedHosts.count; i++) { - if (client->conn->socketAddress.sin_addr.s_addr == Conf.trustedHosts.hosts[i]) { - XplRWReadLockRelease(&Conf.lock); - return TRUE; - } + if (Conf.trustedHosts) { + /* TODO: this can be optimized a little bit */ + XplRWReadLockAcquire(&Conf.lock); + i = BongoArrayFindSorted(Conf.trustedHosts, inet_ntoa(client->conn->socketAddress.sin_addr), (ArrayCompareFunc)hostedFindFunc); + XplRWReadLockRelease(&Conf.lock); } - XplRWReadLockRelease(&Conf.lock); - - return FALSE; + return (i > -1); } int @@ -308,7 +463,7 @@ HandleCommand(QueueClient *client) ccode = ConnWrite(client->conn, MSG3240NOAUTH, sizeof(MSG3240NOAUTH) - 1); } - Log(LOG_INFO, "Handled command from %s", LOGIP(client->conn->socketAddress)); + Log(LOG_DEBUG, "Handled command from %s", LOGIP(client->conn->socketAddress)); } } else if (ccode == -1) { break; @@ -332,10 +487,10 @@ ProcessClient(void *clientp, Connection *conn) client->authorized = CheckTrustedHost(client); if (!client->authorized) { - sprintf(client->authChallenge, "%x%s%x", (unsigned int)XplGetThreadID(), Conf.hostname, (unsigned int)time(NULL)); + sprintf(client->authChallenge, "%x%s%x", (unsigned int)XplGetThreadID(), BongoGlobals.hostname, (unsigned int)time(NULL)); ccode = ConnWriteF(client->conn, MSG4242AUTHREQUIRED, client->authChallenge); } else { - ccode = ConnWriteF(client->conn, "1000 %s %s\r\n", Conf.hostname, MSG1000READY); + ccode = ConnWriteF(client->conn, "1000 %s %s\r\n", BongoGlobals.hostname, MSG1000READY); } if (ccode == -1) { @@ -349,23 +504,6 @@ ProcessClient(void *clientp, Connection *conn) return HandleCommand(client); } -static BOOL -InternalSetServerState(const unsigned char *state) -{ - MDBValueStruct *vs; - - vs = MDBCreateValueStruct(Agent.agent.directoryHandle, NULL); - if (vs) { - MDBAddValue(state, vs); - MDBWrite(MsgGetServerDN(NULL), MSGSRV_A_SERVER_STATUS, vs); - MDBDestroyValueStruct(vs); - - return(TRUE); - } - - return(FALSE); -} - static void QueueServer(void *ignored) { @@ -382,36 +520,27 @@ QueueServer(void *ignored) ProcessClient, &Agent.clientMemPool); - InternalSetServerState("Shutting down"); - /* Shutting down */ if (Agent.clientListener) { ConnClose(Agent.clientListener, 1); Agent.clientListener = NULL; } -#if VERBOSE - XplConsolePrintf("bongoqueue: Closing queue database\r\n"); -#endif + Log(LOG_DEBUG, "Closing queue database."); QueueShutdown(); XplRWLockDestroy(&Conf.lock); -#if VERBOSE - /* Shutting down */ - XplConsolePrintf(AGENT_NAME ": Shutting down.\r\n"); -#endif + Log(LOG_DEBUG, "Shutting down."); BongoThreadPoolShutdown(Agent.clientThreadPool); - InternalSetServerState("Shutdown"); + MsgClearRecoveryFlag("queue"); BongoAgentShutdown(&Agent.agent); -#if VERBOSE - XplConsolePrintf(AGENT_NAME ": Shutdown complete\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown complete"); } @@ -431,18 +560,18 @@ ServerSocketInit(int port) conn->socket = ConnServerSocket(conn, 2048); if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongoqueue: Could not drop to unprivileged user '%s'\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'.", MsgGetUnprivilegedUser()); ConnFree(conn); return NULL; } if (conn->socket == -1) { - XplConsolePrintf("bongoqueue: Could not bind to port %d\n", port); + Log(LOG_ERROR, "Could not bind to port %d.", port); ConnFree(conn); return NULL; } } else { - XplConsolePrintf("bongoqueue: Could not allocate connection\n"); + Log(LOG_ERROR, "Could not allocate connection."); return NULL; } @@ -539,7 +668,7 @@ XplServiceMain(int argc, char *argv[]) LogStart(); if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf(AGENT_NAME ": Could not drop to unprivileged user '%s'\r\n" AGENT_NAME ": exiting.\n", MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); return -1; } @@ -549,10 +678,11 @@ XplServiceMain(int argc, char *argv[]) Agent.agent.port = BONGO_QUEUE_PORT; /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_MDB | BA_STARTUP_CONNIO | BA_STARTUP_NMAP; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_NMAP | BA_STARTUP_MSGLIB | BA_STARTUP_MSGAUTH; + //ccode = BongoAgentInit(&Agent.agent, AGENT_NAME, DEFAULT_CONNECTION_TIMEOUT, startupOpts); ccode = BongoAgentInit(&Agent.agent, AGENT_NAME, MSGSRV_AGENT_QUEUE, DEFAULT_CONNECTION_TIMEOUT, startupOpts); if (ccode == -1) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); + Log(LOG_ERROR, "Initialization failed exiting."); return -1; } @@ -567,12 +697,12 @@ XplServiceMain(int argc, char *argv[]) Agent.clientListener = ServerSocketInit(Agent.agent.port); if (Agent.clientListener == NULL) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); + Log(LOG_ERROR, "Server Initialization failed exiting."); return -1; } if (QueueInit() == FALSE) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); + Log(LOG_ERROR, "Queue Initialization failed exiting."); return -1; } @@ -590,7 +720,7 @@ XplServiceMain(int argc, char *argv[]) BongoAgentStartMonitor(&Agent.agent); - InternalSetServerState("Running"); + MsgSetRecoveryFlag("queue"); /* Start the server thread */ XplStartMainThread(AGENT_NAME, &id, QueueServer, 8192, NULL, ccode); diff --git a/src/agents/queue/queued.h b/src/agents/queue/queued.h index ff413cc..257dc83 100644 --- a/src/agents/queue/queued.h +++ b/src/agents/queue/queued.h @@ -17,6 +17,7 @@ * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * + * (C) 2007 Patrick Felt ****************************************************************************/ #ifndef QUEUED_H @@ -26,9 +27,8 @@ #include #include -#include -#include #include +#include #include #include #include @@ -99,10 +99,7 @@ extern QueueAgent Agent; void QueueClientFree(void *clientp); int HandleCommand(QueueClient *client); - -/* management.c */ -int QueueManagementStart(void); -void QueueManagementShutdown(void); +BOOL aliasing(char *addr, int *cnt, unsigned char *buffer); #define STACKSPACE_Q (1024*80) diff --git a/src/agents/rules/Bongo.rules b/src/agents/rules/Bongo.rules index 082ad1b..a0bcaae 100644 --- a/src/agents/rules/Bongo.rules +++ b/src/agents/rules/Bongo.rules @@ -1,17 +1,15 @@ # -*- Makefile -*- sbin_PROGRAMS += bongorules -bongorules_SOURCES := \ +bongorules_SOURCES = \ src/agents/rules/rules.c \ src/agents/rules/rules.h \ src/agents/rules/stream.c -bongorules_LDADD := \ +bongorules_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongostreamio.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/rules/rules.c b/src/agents/rules/rules.c index 207981d..6f51940 100644 --- a/src/agents/rules/rules.c +++ b/src/agents/rules/rules.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -885,7 +884,8 @@ IsNMAPShare(RulesClient *client, unsigned char *name, unsigned char *type, unsig MDBFreeValues(vs); - MsgGetUserSetting(client->dn, MSGSRV_A_AVAILABLE_SHARES, vs); + // FIXME + // MsgGetUserSetting(client->dn, MSGSRV_A_AVAILABLE_SHARES, vs); /* if (MsgGetUserSettingsDN(client->dn, configDn, vs, FALSE)) { MDBRead(configDn, MSGSRV_A_AVAILABLE_SHARES, vs); @@ -957,7 +957,8 @@ IsNMAPShare(RulesClient *client, unsigned char *name, unsigned char *type, unsig memcpy(pattern + length, client->user, count); count += length; - MsgGetUserSetting(dn, MSGSRV_A_OWNED_SHARES, vs); + //FIXME + //MsgGetUserSetting(dn, MSGSRV_A_OWNED_SHARES, vs); /* if (MsgGetUserSettingsDN(dn, configDn, vs, FALSE)) { MDBRead(configDn, MSGSRV_A_OWNED_SHARES, vs); @@ -1808,8 +1809,9 @@ ProcessConnection(RulesClient *client) if (MsgFindObject(client->recipient, client->dn, NULL, &(client->nmap), vs)) { strcpy(client->user, vs->Value[0]); - if (MDBFreeValues(vs) - && MsgGetUserFeature(client->dn, FEATURE_RULES, MSGSRV_A_RULE, vs)) { + if (MDBFreeValues(vs)) { + // FIXME + // && MsgGetUserFeature(client->dn, FEATURE_RULES, MSGSRV_A_RULE, vs)) { ParseRules(client, vs); if (client->rules.head) { ccode = ProcessRules(client, ©, &flags); @@ -2099,36 +2101,11 @@ static BOOL ReadConfiguration(void) { unsigned long used; - MDBValueStruct *vs; - vs = MDBCreateValueStruct(Rules.handle.directory, MsgGetServerDN(NULL)); - if (vs) { - if (MDBRead(MSGSRV_AGENT_RULESRV, MSGSRV_A_CONFIGURATION, vs)) { - used = atol(vs->Value[0]); - if (used & RULESRV_USER_RULES) { - Rules.flags |= RULES_FLAG_USER_RULES; - } + Rules.flags = RULES_FLAG_USER_RULES | RULES_FLAG_SYSTEM_RULES; + Rules.officialName[0] = '\0'; - if (used & RULESRV_SYSTEM_RULES) { - Rules.flags |= RULES_FLAG_SYSTEM_RULES; - } - - MDBFreeValues(vs); - } - - if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_OFFICIAL_NAME, vs)) { - strcpy(Rules.officialName, vs->Value[0]); - MDBFreeValues(vs); - } else { - Rules.officialName[0] = '\0'; - } - - MDBDestroyValueStruct(vs); - - return(TRUE); - } - - return(FALSE); + return(TRUE); } #if defined(NETWARE) || defined(LIBC) || defined(WIN32) @@ -2215,7 +2192,7 @@ QueueSocketInit(void) return(-1); } - if (NMAPRegister(MSGSRV_AGENT_ANTISPAM, Rules.nmap.queue, Rules.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { + if (QueueRegister(MSGSRV_AGENT_ANTISPAM, Rules.nmap.queue, Rules.nmap.conn->socketAddress.sin_port) != REGISTRATION_COMPLETED) { XplConsolePrintf("bongorules: Could not register with bongonmap\r\n"); ConnFree(Rules.nmap.conn); Rules.nmap.conn = NULL; @@ -2307,7 +2284,7 @@ XplServiceMain(int argc, char *argv[]) } StreamioInit(); - NMAPInitialize(Rules.handle.directory); + NMAPInitialize(); SetCurrentNameSpace(NWOS2_NAME_SPACE); SetTargetNameSpace(NWOS2_NAME_SPACE); diff --git a/src/agents/rules/rules.h b/src/agents/rules/rules.h index 5856702..908f0e4 100644 --- a/src/agents/rules/rules.h +++ b/src/agents/rules/rules.h @@ -23,8 +23,6 @@ #define _BONGORULES_H #include -#include -#include #include #include #include @@ -263,14 +261,6 @@ typedef struct _RulesGlobals { extern RulesGlobals Rules; -/* management.c */ -ManagementVariables *GetRulesManagementVariables(void); -int GetRulesManagementVariablesCount(void); -ManagementCommands *GetRulesManagementCommands(void); -int GetRulesManagementCommandsCount(void); - -void RulesStartManagement(void); - /* stream.c */ BOOL MWHandleNamedTemplate(void *ClientIn, unsigned char *TemplateName, void *ObjectData); int RulesStreamToMemory(StreamStruct *codec, StreamStruct *next); diff --git a/src/agents/smtp/Bongo.rules b/src/agents/smtp/Bongo.rules index fd83986..019e6d2 100644 --- a/src/agents/smtp/Bongo.rules +++ b/src/agents/smtp/Bongo.rules @@ -1,16 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongosmtp -bongosmtp_SOURCES := \ +bongosmtp_SOURCES = \ src/agents/smtp/smtpd.c \ src/agents/smtp/smtpd.h -bongosmtp_LDADD := \ +bongosmtp_LDADD = \ libbongonmap.la \ - libbongoconnmgr.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/smtp/smtpd.c b/src/agents/smtp/smtpd.c index 99591e3..578dd85 100644 --- a/src/agents/smtp/smtpd.c +++ b/src/agents/smtp/smtpd.c @@ -39,18 +39,65 @@ #include -#include #include -#include +#include #include #include "smtpd.h" +struct { + int port; + int port_ssl; + BOOL allow_client_ssl; + BOOL allow_expn; + BOOL allow_auth; + BOOL require_auth; + BOOL allow_vrfy; + BOOL verify_address; + BOOL accept_etrn; + BOOL send_etrn; + int max_recips; + int message_limit; + BOOL use_relay; + BOOL relay_local; + char *relay_host; + BOOL block_rts; + int max_thread_load; + int max_flood_count; + int max_null_sender; + int max_mx_servers; + int socket_timeout; +} SMTP; + +static BongoConfigItem SMTPConfig[] = { + { BONGO_JSON_INT, "o:port/i", &SMTP.port }, + { BONGO_JSON_INT, "o:port_ssl/i", &SMTP.port_ssl }, + { BONGO_JSON_BOOL, "o:allow_client_ssl/b", &SMTP.allow_client_ssl }, + { BONGO_JSON_BOOL, "o:allow_expn/b", &SMTP.allow_expn }, + { BONGO_JSON_BOOL, "o:allow_vrfy/b", &SMTP.allow_vrfy }, + { BONGO_JSON_BOOL, "o:allow_auth/b", &SMTP.allow_auth }, + { BONGO_JSON_BOOL, "o:verify_address/b", &SMTP.verify_address }, + { BONGO_JSON_BOOL, "o:accept_etrn/b", &SMTP.accept_etrn }, + { BONGO_JSON_BOOL, "o:send_etrn/b", &SMTP.send_etrn }, + { BONGO_JSON_INT, "o:maximum_recipients/i", &SMTP.max_recips }, + { BONGO_JSON_INT, "o:message_size_limit/i", &SMTP.message_limit }, + { BONGO_JSON_BOOL, "o:use_relay_host/b", &SMTP.use_relay }, + { BONGO_JSON_STRING, "o:relay_host/s", &SMTP.relay_host }, + { BONGO_JSON_BOOL, "o:block_rts_spam/b", &SMTP.block_rts }, + { BONGO_JSON_INT, "o:max_thread_load/i", &SMTP.max_thread_load }, + { BONGO_JSON_INT, "o:max_flood_count/i", &SMTP.max_flood_count }, // UNUSED ? + { BONGO_JSON_INT, "o:max_null_sender/i", &SMTP.max_null_sender }, + { BONGO_JSON_INT, "o:socket_timeout/i", &SMTP.socket_timeout }, + { BONGO_JSON_INT, "o:max_mx_servers/i", &SMTP.max_mx_servers }, + { BONGO_JSON_BOOL, "o:relay_local_mail/b", &SMTP.relay_local }, + { BONGO_JSON_BOOL, "o:require_auth/b", &SMTP.require_auth }, + { BONGO_JSON_NULL, NULL, NULL } +}; + /* Globals */ BOOL Exiting = FALSE; XplSemaphore SMTPShutdownSemaphore; XplSemaphore SMTPServerSemaphore; -long SMTPMaxThreadLoad = 100000; XplAtomic SMTPServerThreads; XplAtomic SMTPConnThreads; XplAtomic SMTPIdleConnThreads; @@ -59,48 +106,20 @@ Connection *SMTPServerConnection; Connection *SMTPServerConnectionSSL; Connection *SMTPQServerConnection; Connection *SMTPQServerConnectionSSL; -unsigned long SMTPServerPort = SMTP_PORT; -unsigned long SMTPServerPortSSL = SMTP_PORT_SSL; -unsigned char Hostname[MAXEMAILNAMESIZE + 128]; -unsigned char Hostaddr[MAXEMAILNAMESIZE + 1]; int TGid; -unsigned long MaxMXServers = 0; - -unsigned char **Domains = NULL; -unsigned int DomainCount = 0; -unsigned char **UserDomains = NULL; -unsigned int UserDomainCount = 0; -unsigned char **RelayDomains = NULL; -unsigned int RelayDomainCount = 0; /* UBE measures */ -unsigned long UBEConfig = 0; XplRWLock ConfigLock; BOOL SMTPReceiverStopped = FALSE; -unsigned char Postmaster[MAXEMAILNAMESIZE + 1] = "admin"; -unsigned char OfficialName[MAXEMAILNAMESIZE + 1] = ""; -unsigned char RelayHost[MAXEMAILNAMESIZE + 1] = ""; -BOOL UseRelayHost = FALSE; -BOOL RelayLocalMail = FALSE; BOOL Notify = FALSE; BOOL AllowClientSSL = FALSE; -BOOL AllowEXPN = FALSE; -BOOL AllowVRFY = FALSE; -BOOL CheckRCPT = FALSE; -BOOL SendETRN = FALSE; -BOOL AcceptETRN = FALSE; BOOL DomainUsernames = TRUE; -BOOL BlockRTSSpam = FALSE; time_t LastBounce; time_t BounceInterval; unsigned long MaxBounceCount; unsigned long BounceCount; unsigned char NMAPServer[20] = "127.0.0.1"; -unsigned long MessageLimit = 0; -unsigned long MaximumRecipients = 15; -unsigned long MaxNullSenderRecips = ULONG_MAX; -unsigned long MaxFloodCount = 1000; unsigned long LocalAddress = 0; bongo_ssl_context *SSLContext = NULL; static unsigned char NMAPHash[NMAP_HASH_SIZE]; @@ -126,7 +145,6 @@ int MAX_HOPS = 16; /* Minutes * 60 (1 second granularity) */ /*#define CONNECTION_TIMEOUT (10*60)*/ -unsigned long SocketTimeout = 10 * 60; /* Seconds */ #define MAILBOX_TIMEOUT 15 @@ -183,17 +201,12 @@ typedef struct void *SMTPConnectionPool = NULL; -MDBHandle SMTPDirectoryHandle = NULL; - /* Prototypes */ long ReadConnection(Connection *conn, char **buffer, unsigned long *buflen); void ProcessRemoteEntry (ConnectionStruct * Client, unsigned long Size, int Lines); -void FreeDomains (void); -int RewriteAddress (unsigned char *Source, unsigned char *Target, unsigned int TargetSize); +int RewriteAddress (Connection * conn, unsigned char *Source, unsigned char *Target, unsigned int TargetSize); BOOL FlushClient (ConnectionStruct * Client); BOOL EndClientConnection (ConnectionStruct * Client); -void FreeUserDomains (void); -void FreeRelayDomains (void); static int PullLine (unsigned char *Line, unsigned long LineSize, unsigned char **NextLine); /* this PullLine will strip off the crlf where the other one only seems to strip off the lf * eventually i'd like to remove the first and convert everything to using the straight connio @@ -203,7 +216,7 @@ static int PullLine2 (unsigned char *Line, unsigned long LineSize, unsigned char static BOOL SMTPConnectionAllocCB (void *Buffer, void *ClientData) { - register ConnectionStruct *c = (ConnectionStruct *) Buffer; + ConnectionStruct *c = (ConnectionStruct *) Buffer; memset (c, 0, sizeof (ConnectionStruct)); c->State = STATE_FRESH; @@ -215,7 +228,7 @@ SMTPConnectionAllocCB (void *Buffer, void *ClientData) static void ReturnSMTPConnection (ConnectionStruct * Client) { - register ConnectionStruct *c = Client; + ConnectionStruct *c = Client; memset (c, 0, sizeof (ConnectionStruct)); c->State = STATE_FRESH; @@ -231,8 +244,8 @@ __inline static unsigned char * strchrRN (unsigned char *Buffer, unsigned char SrchChar, unsigned char *EndPtr) { - register unsigned char *ptr = Buffer; - register unsigned char srchChar = SrchChar; + unsigned char *ptr = Buffer; + unsigned char srchChar = SrchChar; do { while (*ptr != '\0') { @@ -272,6 +285,8 @@ strchrRN (unsigned char *Buffer, unsigned char SrchChar, BOOL EndClientConnection (ConnectionStruct * Client) { + unsigned char Reply[BUFSIZE + 1]; + if (Client) { if (Client->State == STATE_ENDING) { return (TRUE); @@ -295,16 +310,19 @@ EndClientConnection (ConnectionStruct * Client) /* state, the dot on a line by itself will not hurt */ /* anything. NMAP will just send 'unknown command' */ NMAPSendCommand (Client->nmap.conn, "\r\n.\r\n", 5); + NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply), TRUE); //empty line + NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply), TRUE); //. NMAPSendCommand (Client->nmap.conn, "QABRT\r\nQUIT\r\n", 13); + NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply), TRUE); //qabrt which we've already done once.... + NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply), TRUE); //quit } else { NMAPSendCommand (Client->nmap.conn, "QUIT\r\n", 6); + NMAPReadResponse(Client->nmap.conn, Reply, sizeof(Reply), TRUE); //quit } FreeInternalConnection(Client->nmap); } if (Client->client.conn) { - CMDisconnected (Client->client.conn->socketAddress.sin_addr.s_addr); - FreeInternalConnection(Client->client); } @@ -344,7 +362,6 @@ HandleConnection (void *param) BOOL AllowAuth = TRUE; BOOL NullSender = FALSE; BOOL TooManyNullSenderRecips = FALSE; - BOOL RequireAuth = FALSE; unsigned char *ptr, *ptr2; unsigned char Answer[BUFSIZE + 1]; unsigned char Reply[BUFSIZE + 1]; @@ -364,66 +381,10 @@ HandleConnection (void *param) } XplRWReadLockAcquire (&ConfigLock); - if (UBEConfig & UBE_DISABLE_AUTH) { + if (! SMTP.allow_auth) { AllowAuth = FALSE; } - ReplyInt = CMVerifyConnect (Client->client.conn->socketAddress.sin_addr.s_addr, Answer, &RequireAuth); - if (ReplyInt == CM_RESULT_DENY_PERMANENT) { - /* We don't like the guy */ - XplRWReadLockRelease (&ConfigLock); - Log(LOG_INFO, "Connection from %s blocked", LOGIP(Client->client.conn->socketAddress)); - - if (Answer[0] != '\0') { - ConnWrite (Client->client.conn, MSG553COMMENT, MSG553COMMENT_LEN); - ConnWrite (Client->client.conn, Answer, strlen (Answer)); - ConnWrite (Client->client.conn, "\r\n", 2); - } - else { - ConnWrite (Client->client.conn, MSG550SPAMBLOCK, MSG550SPAMBLOCK_LEN); - } - ConnFlush (Client->client.conn); - return (EndClientConnection (Client)); - } else if (ReplyInt != CM_RESULT_ALLOWED) { - /* Either we don't like the guy, or there was an error */ - XplRWReadLockRelease (&ConfigLock); - Log(LOG_INFO, "Connection from %s blocked by blocklist %d", - LOGIP(Client->client.conn->socketAddress), - LOGGING_BLOCK_BLOCKLIST); - - if (Answer[0] != '\0') { - ConnWrite (Client->client.conn, MSG453COMMENT, MSG453COMMENT_LEN); - ConnWrite (Client->client.conn, Answer, strlen (Answer)); - ConnWrite (Client->client.conn, "\r\n", 2); - } else { - ConnWrite (Client->client.conn, MSG453TRYLATER, MSG453TRYLATER_LEN); - } - ConnFlush (Client->client.conn); - return (EndClientConnection (Client)); - } - - if (UBEConfig & UBE_DEFAULT_NOT_TRUSTED) { - IsTrusted = FALSE; - - if (UBEConfig & UBE_SMTP_AFTER_POP) { - ReplyInt = CMVerifyRelay (Client->client.conn->socketAddress.sin_addr.s_addr, Answer); - if (ReplyInt == CM_RESULT_ALLOWED) { - if (Answer[0] != '\0') { - if (Client->AuthFrom == NULL) { - Client->AuthFrom = MemStrdup (Answer); - IsTrusted = TRUE; - } else { - MemFree (Client->AuthFrom); - Client->AuthFrom = MemStrdup (Answer); - IsTrusted = TRUE; - } - } else { - IsTrusted = TRUE; - } - } - } - } - XplRWReadLockRelease (&ConfigLock); /* Connect to Queue agent */ @@ -442,15 +403,14 @@ HandleConnection (void *param) LOGIP(Client->client.conn->socketAddress), ReplyInt); } - count = snprintf(Reply, sizeof(Reply), "421 %s %s\r\n", Hostname, MSG421SHUTDOWN); + count = snprintf(Reply, sizeof(Reply), "421 %s %s\r\n", BongoGlobals.hostname, MSG421SHUTDOWN); ConnWrite (Client->client.conn, Reply, count); ConnFlush (Client->client.conn); return (EndClientConnection (Client)); } - snprintf (Answer, sizeof (Answer), "220 %s %s %s\r\n", Hostname, - MSG220READY, PRODUCT_VERSION); + snprintf (Answer, sizeof (Answer), "220 %s %s %s\r\n", BongoGlobals.hostname, MSG220READY, PRODUCT_VERSION); ConnWrite (Client->client.conn, Answer, strlen (Answer)); ConnFlush (Client->client.conn); @@ -460,8 +420,7 @@ HandleConnection (void *param) if (Exiting == FALSE) { count = ConnReadToAllocatedBuffer(Client->client.conn, &(Client->client.buffer), &(Client->client.buflen)); } else { - snprintf (Answer, sizeof (Answer), "421 %s %s\r\n", - Hostname, MSG421SHUTDOWN); + snprintf (Answer, sizeof (Answer), "421 %s %s\r\n", BongoGlobals.hostname, MSG421SHUTDOWN); ConnWrite (Client->client.conn, Answer, strlen (Answer)); ConnFlush(Client->client.conn); return (EndClientConnection (Client)); @@ -476,8 +435,7 @@ HandleConnection (void *param) LOGIP(soc_address), time(NULL) - connectionTime); return (EndClientConnection (Client)); } else if (count < 1) { - snprintf (Answer, sizeof (Answer), "421 %s %s\r\n", - Hostname, MSG421SHUTDOWN); + snprintf (Answer, sizeof (Answer), "421 %s %s\r\n", BongoGlobals.hostname, MSG421SHUTDOWN); ConnWrite (Client->client.conn, Answer, strlen (Answer)); ConnFlush(Client->client.conn); return (EndClientConnection (Client)); @@ -489,8 +447,7 @@ HandleConnection (void *param) switch (toupper (Client->Command[3])) { case 'O': /* HELO */ if (Client->State == STATE_FRESH) { - snprintf (Answer, sizeof (Answer), "250 %s %s\r\n", - Hostname, MSG250HELLO); + snprintf (Answer, sizeof (Answer), "250 %s %s\r\n", BongoGlobals.hostname, MSG250HELLO); ConnWrite (Client->client.conn, Answer, strlen (Answer)); strncpy (Client->RemoteHost, Client->Command + 5, sizeof (Client->RemoteHost)); @@ -517,7 +474,7 @@ HandleConnection (void *param) case 'S':{ /* SAML, SOML, SEND */ switch (toupper (Client->Command[1])) { case 'T':{ /* STARTTLS */ - if (!AllowClientSSL) { + if (!SMTP.allow_client_ssl) { ConnWrite (Client->client.conn, MSG500UNKNOWN, MSG500UNKNOWN_LEN); break; } @@ -553,7 +510,6 @@ HandleConnection (void *param) case 'A':{ /* AUTH */ unsigned char *PW; - MDBValueStruct *User; if (AllowAuth == FALSE) { ConnWrite (Client->client.conn, MSG500UNKNOWN, MSG500UNKNOWN_LEN); @@ -600,38 +556,28 @@ HandleConnection (void *param) PW = DecodeBase64 (Client->client.buffer); DecodeBase64 (Reply); - User = MDBCreateValueStruct (SMTPDirectoryHandle, NULL); - if (MsgFindObject (Reply, Answer, NULL, NULL, User)) { - if (!MDBVerifyPassword (Answer, PW, User)) { + if (MsgAuthFindUser(Reply) == 0) { + if (MsgAuthVerifyPassword(Reply, PW) != 0) { ConnWrite (Client->client.conn, "501 Authentication failed!\r\n", 28); Log(LOG_NOTICE, "Wrong password from user %s at host %s", - User->Used ? User->Value[0] : Reply, + Reply, LOGIP(Client->client.conn->socketAddress)); } else { Log(LOG_NOTICE, "Successful login for user %s at host %s", - User->Value[0], + Reply, LOGIP(Client->client.conn->socketAddress)); - if (Client->AuthFrom == NULL) { - Client->AuthFrom = MemStrdup (User->Value[0]); - Client->State = STATE_AUTH; - ConnWrite (Client->client.conn, "235 Authentication successful!\r\n", 32); - IsAuthed = TRUE; - IsTrusted = TRUE; - } else { - MemFree (Client->AuthFrom); - Client->AuthFrom = MemStrdup (User->Value[0]); - Client->State = STATE_AUTH; - ConnWrite (Client->client.conn, "235 Authentication successful!\r\n", 32); - IsAuthed = TRUE; - IsTrusted = TRUE; - } + if (Client->AuthFrom != NULL) MemFree (Client->AuthFrom); + Client->AuthFrom = MemStrdup (Reply); + Client->State = STATE_AUTH; + ConnWrite (Client->client.conn, "235 Authentication successful!\r\n", 32); + IsAuthed = TRUE; + IsTrusted = TRUE; } } else { Log(LOG_NOTICE, "Unknown user %s at host %s", Reply, LOGIP(Client->client.conn->socketAddress)); ConnWrite (Client->client.conn, "501 Authentication failed!\r\n", 28); } - MDBDestroyValueStruct (User); break; } @@ -810,15 +756,13 @@ HandleConnection (void *param) break; } - if ((ReplyInt = - RewriteAddress (name, To, - sizeof (To))) == MAIL_BOGUS) { + if ((ReplyInt = RewriteAddress (Client->nmap.conn, name, To, sizeof (To))) == MAIL_BOGUS) { ConnWrite (Client->client.conn, MSG501RECIPNO, MSG501RECIPNO_LEN); } else { switch (ReplyInt) { case MAIL_REMOTE:{ - if (!IsTrusted) { + if (!IsAuthed) { Log(LOG_INFO, "Recipient %s by host %s blocked", name, LOGIP(Client->client.conn->socketAddress)); ConnWrite (Client->client.conn, @@ -827,7 +771,7 @@ HandleConnection (void *param) goto QuitRcpt; } XplRWReadLockAcquire (&ConfigLock); - if (Client->RecipCount >= MaximumRecipients) { + if (Client->RecipCount >= SMTP.max_recips) { XplRWReadLockRelease (&ConfigLock); Log(LOG_INFO, "Recipient limit from %s at host %s to user %s", Client->AuthFrom? @@ -870,34 +814,22 @@ HandleConnection (void *param) case MAIL_LOCAL:{ XplRWReadLockAcquire (&ConfigLock); - if ((NullSender == FALSE) - || (Client->RecipCount < - MaxNullSenderRecips)) { - if (!CheckRCPT) { + if ((NullSender == FALSE) || (Client->RecipCount < SMTP.max_null_sender)) { + if (!SMTP.verify_address) { XplRWReadLockRelease (&ConfigLock); snprintf (Answer, sizeof (Answer), "QSTOR LOCAL %s %s %lu\r\n", To, Orcpt ? Orcpt : To, - (unsigned long) (Client-> - Flags & - DSN_FLAGS)); - } - else { + (unsigned long) (Client->Flags & DSN_FLAGS)); + } else { XplRWReadLockRelease (&ConfigLock); - if (MsgFindObject - (To, NULL, NULL, NULL, NULL)) { + if (MsgAuthFindUser(To) == 0) { snprintf (Answer, sizeof (Answer), "QSTOR LOCAL %s %s %lu\r\n", To, Orcpt ? Orcpt : To, - (unsigned - long) (Client-> - Flags & - DSN_FLAGS)); - } - else { - ConnWrite (Client->client.conn, - MSG550NOTFOUND, - MSG550NOTFOUND_LEN); + (unsigned long) (Client->Flags & DSN_FLAGS)); + } else { + ConnWrite (Client->client.conn, MSG550NOTFOUND, MSG550NOTFOUND_LEN); goto QuitRcpt; } } @@ -951,7 +883,7 @@ HandleConnection (void *param) unsigned char *Envid = NULL; unsigned char *more; - if (RequireAuth && !IsTrusted) { + if (SMTP.require_auth && !IsTrusted) { ConnWrite (Client->client.conn, MSG553SPAMBLOCK, MSG553SPAMBLOCK_LEN); break; } @@ -1051,7 +983,7 @@ HandleConnection (void *param) #if 0 /* We're abusing size, so we don't need another stack variable */ /* Spam block */ - if (BlockRTSSpam && (name[0] == '\0')) { + if (SMTP.block_rts && (name[0] == '\0')) { XplRWReadLockAcquire (&ConfigLock); time (&size); @@ -1158,7 +1090,7 @@ HandleConnection (void *param) ptr++; size = atol (ptr); XplRWReadLockAcquire (&ConfigLock); - if (MessageLimit > 0 && size > MessageLimit) { + if (SMTP.message_limit > 0 && size > SMTP.message_limit) { XplRWReadLockRelease (&ConfigLock); ConnWrite (Client->client.conn, MSG552MSGTOOBIG, MSG552MSGTOOBIG_LEN); @@ -1317,29 +1249,17 @@ HandleConnection (void *param) } else { snprintf(WithProtocol, 5, "SMTP"); } - - snprintf(Answer, sizeof(Answer), - "Received: from %d.%d.%d.%d (%s%s%s) [%d.%d.%d.%d]\r\n\tby %s with %s (%s %s%s);\r\n\t%s\r\n", - Client->client.conn->socketAddress.sin_addr.s_net, - Client->client.conn->socketAddress.sin_addr.s_host, - Client->client.conn->socketAddress.sin_addr.s_lh, - Client->client.conn->socketAddress.sin_addr.s_impno, - - Client->AuthFrom ? (char *)Client->AuthFrom : "not authenticated", - Client->RemoteHost[0] ? " HELO " : "", - Client->RemoteHost, - - Client->client.conn->socketAddress.sin_addr.s_net, - Client->client.conn->socketAddress.sin_addr.s_host, - Client->client.conn->socketAddress.sin_addr.s_lh, - Client->client.conn->socketAddress.sin_addr.s_impno, - - Hostname, - WithProtocol, - PRODUCT_NAME, - PRODUCT_VERSION, - Client->client.conn->ssl.enable ? "\r\n\tvia secured & encrypted transport [TLS]" : "", - TimeBuf); + snprintf(Answer, sizeof(Answer), "Received: from %s (%d.%d.%d.%d) by %s\r\n\twith %sSMTP%s%s (bongosmtp Agent); %s\r\n", + Client->RemoteHost, + Client->client.conn->socketAddress.sin_addr.s_net, + Client->client.conn->socketAddress.sin_addr.s_host, + Client->client.conn->socketAddress.sin_addr.s_lh, + Client->client.conn->socketAddress.sin_addr.s_impno, + BongoGlobals.hostname, + (Client->IsEHLO) ? "E" : "", + (Client->client.conn->ssl.enable) ? "S" : "", + (Client->AuthFrom) ? "A" : "", + TimeBuf); NMAPSendCommand(Client->nmap.conn, Answer, strlen(Answer)); /* read all the data to the nmap connection. this function @@ -1350,7 +1270,7 @@ HandleConnection (void *param) } XplRWReadLockAcquire (&ConfigLock); - if (MessageLimit > 0 && BReceived > MessageLimit) { /* Message over limit */ + if (SMTP.message_limit > 0 && BReceived > SMTP.message_limit) { /* Message over limit */ XplRWReadLockRelease (&ConfigLock); if ((NMAPSendCommand (Client->nmap.conn, "QABRT\r\n", 7) < 0) || NMAPReadResponse (Client->nmap.conn, Reply, sizeof (Reply), TRUE) != 1000) { @@ -1364,7 +1284,7 @@ HandleConnection (void *param) XplRWReadLockRelease (&ConfigLock); if ((NullSender == FALSE) - || (Client->RecipCount < MaxNullSenderRecips)) { + || (Client->RecipCount < SMTP.max_null_sender)) { if (NMAPSendCommand (Client->nmap.conn, "QRUN\r\n", 6)<0) { ConnWrite (Client->client.conn, MSG451INTERNALERR, MSG451INTERNALERR_LEN); @@ -1417,8 +1337,7 @@ HandleConnection (void *param) } } } - snprintf (Answer, sizeof (Answer), "221 %s %s\r\n", Hostname, - MSG221QUIT); + snprintf (Answer, sizeof (Answer), "221 %s %s\r\n", BongoGlobals.hostname, MSG221QUIT); ConnWrite (Client->client.conn, Answer, strlen (Answer)); return (EndClientConnection (Client)); break; @@ -1432,23 +1351,23 @@ HandleConnection (void *param) case 'H':{ /* EHLO */ if (Client->State == STATE_FRESH) { XplRWReadLockAcquire (&ConfigLock); - if (MessageLimit > 0) { + if (SMTP.message_limit > 0) { snprintf (Answer, sizeof (Answer), "250-%s %s\r\n%s%s%s%s %lu\r\n", - Hostname, MSG250HELLO, - AcceptETRN ? MSG250ETRN : "", - (AllowClientSSL + BongoGlobals.hostname, MSG250HELLO, + SMTP.accept_etrn ? MSG250ETRN : "", + (SMTP.allow_client_ssl && !Client->client.conn->ssl.enable) ? MSG250TLS : "", (AllowAuth == TRUE) ? MSG250AUTH : "", - MSG250EHLO, MessageLimit); + MSG250EHLO, SMTP.message_limit); } else { snprintf (Answer, sizeof (Answer), "250-%s %s\r\n%s%s%s%s\r\n", - Hostname, MSG250HELLO, - AcceptETRN ? MSG250ETRN : "", - (AllowClientSSL + BongoGlobals.hostname, MSG250HELLO, + SMTP.accept_etrn ? MSG250ETRN : "", + (SMTP.allow_client_ssl && !Client->client.conn->ssl.enable) ? MSG250TLS : "", (AllowAuth == TRUE) ? MSG250AUTH : "", @@ -1474,7 +1393,7 @@ HandleConnection (void *param) case 'T':{ /* ETRN */ count = 0; XplRWReadLockAcquire (&ConfigLock); - if (AcceptETRN) { + if (SMTP.accept_etrn) { XplRWReadLockRelease (&ConfigLock); ReplyInt = snprintf (Answer, sizeof (Answer), @@ -1505,7 +1424,7 @@ HandleConnection (void *param) case 'X':{ /* EXPN */ XplRWReadLockAcquire (&ConfigLock); - if (AllowEXPN) { + if (SMTP.allow_expn) { BOOL Found = FALSE; XplRWReadLockRelease (&ConfigLock); @@ -1543,7 +1462,7 @@ HandleConnection (void *param) case 'V':{ /* VRFY */ XplRWReadLockAcquire (&ConfigLock); - if (AllowVRFY) { + if (SMTP.allow_vrfy) { BOOL Found = FALSE; XplRWReadLockRelease (&ConfigLock); @@ -1749,12 +1668,14 @@ DeliverSMTPMessage (ConnectionStruct * Client, unsigned char *Sender, unsigned int i; BOOL EscapedState = FALSE; unsigned long LastNMAPContact; - unsigned char TimeBuf[80]; + unsigned char TimeBuf[80]; + BOOL ehlo=TRUE; + BOOL tls=FALSE; status = GetAnswer (Client, Reply, sizeof (Reply)); HandleFailure (220); - snprintf (Answer, sizeof (Answer), "EHLO %s\r\n", Hostname); + snprintf (Answer, sizeof (Answer), "EHLO %s\r\n", BongoGlobals.hostname); if (ConnWrite(Client->remotesmtp.conn, Answer, strlen(Answer)) < 1) { DELIVER_ERROR (DELIVER_TRY_LATER); } @@ -1762,19 +1683,20 @@ DeliverSMTPMessage (ConnectionStruct * Client, unsigned char *Sender, status = GetEHLO (Client, &Extensions, &Size); if (status != 250) { - snprintf (Answer, sizeof (Answer), "HELO %s\r\n", Hostname); + snprintf (Answer, sizeof (Answer), "HELO %s\r\n", BongoGlobals.hostname); if (ConnWrite(Client->remotesmtp.conn, Answer, strlen(Answer)) < 1) { DELIVER_ERROR (DELIVER_TRY_LATER); } ConnFlush(Client->remotesmtp.conn); status = GetAnswer (Client, Reply, sizeof (Reply)); HandleFailure (250); + ehlo=FALSE; } else { /* The other server supports ESMTP */ // SSL delivery disabled per bug #9536 - if (0 && AllowClientSSL && (Extensions & EXT_TLS)) { + if (0 && SMTP.allow_client_ssl && (Extensions & EXT_TLS)) { snprintf (Answer, sizeof (Answer), "STARTTLS\r\n"); if (ConnWrite(Client->remotesmtp.conn, Answer, strlen(Answer)) < 1) { DELIVER_ERROR (DELIVER_TRY_LATER); @@ -1785,12 +1707,13 @@ DeliverSMTPMessage (ConnectionStruct * Client, unsigned char *Sender, if(ConnEncrypt(Client->remotesmtp.conn, SSLContext) < 0) { DELIVER_ERROR (DELIVER_FAILURE); } - status = snprintf (Answer, sizeof (Answer), "EHLO %s\r\n", Hostname); + status = snprintf (Answer, sizeof (Answer), "EHLO %s\r\n", BongoGlobals.hostname); if (ConnWrite(Client->remotesmtp.conn, Answer, status) < 1) { DELIVER_ERROR (DELIVER_TRY_LATER); } ConnFlush(Client->remotesmtp.conn); status = GetAnswer (Client, Reply, sizeof (Reply)); + tls=TRUE; } } @@ -2113,19 +2036,14 @@ DeliverSMTPMessage (ConnectionStruct * Client, unsigned char *Sender, HandleFailure (354); MsgGetRFC822Date(-1, 0, TimeBuf); - snprintf(Answer, sizeof(Answer), "Received: from %d.%d.%d.%d [%d.%d.%d.%d] by %s\r\n\twith NMAP (%s %s); %s\r\n", - Client->client.conn->socketAddress.sin_addr.s_net, - Client->client.conn->socketAddress.sin_addr.s_host, - Client->client.conn->socketAddress.sin_addr.s_lh, - Client->client.conn->socketAddress.sin_addr.s_impno, - Client->client.conn->socketAddress.sin_addr.s_net, - Client->client.conn->socketAddress.sin_addr.s_host, - Client->client.conn->socketAddress.sin_addr.s_lh, - Client->client.conn->socketAddress.sin_addr.s_impno, - Hostname, - PRODUCT_NAME, - PRODUCT_VERSION, - TimeBuf); + snprintf(Answer, sizeof(Answer), "Received: from %s (%d.%d.%d.%d) by %s\r\n\twith NMAP (bongosmtp Agent); %s\r\n", + BongoGlobals.hostname, /* FIXME: this should eventually refelct the queue agent's ip hostname */ + Client->client.conn->socketAddress.sin_addr.s_net, + Client->client.conn->socketAddress.sin_addr.s_host, + Client->client.conn->socketAddress.sin_addr.s_lh, + Client->client.conn->socketAddress.sin_addr.s_impno, + BongoGlobals.hostname, + TimeBuf); ConnWrite(Client->remotesmtp.conn, Answer, strlen(Answer)); snprintf(Answer, sizeof(Answer), "QRETR %s MESSAGE\r\n", Client->RemoteHost); @@ -2183,19 +2101,6 @@ DeliverSMTPMessage (ConnectionStruct * Client, unsigned char *Sender, } } - XplRWReadLockAcquire (&ConfigLock); - if (SendETRN && (Extensions & EXT_ETRN)) { - for (i = 0; i < DomainCount; i++) { - len = snprintf (Reply, sizeof (Reply), "ETRN %s\r\n", Domains[i]); - if (ConnWrite(Client->remotesmtp.conn, Reply, len) < 1) { - XplRWReadLockRelease (&ConfigLock); - FreeInternalConnection(Client->remotesmtp); - return (DELIVER_SUCCESS); - } - } - } - XplRWReadLockRelease (&ConfigLock); - if (ConnWrite(Client->remotesmtp.conn, "QUIT\r\n", 6) < 1) { status = GetAnswer (Client, Reply, sizeof (Reply)); } @@ -2219,17 +2124,17 @@ DeliverRemoteMessage (ConnectionStruct * Client, unsigned char *Sender, { unsigned char Host[MAXEMAILNAMESIZE + 1]; unsigned char *ptr; - unsigned int status; + int status; int RetVal; XplDns_MxLookup *mx = NULL; XplDns_IpList *list = NULL; // If we have a relay configured, use that. // Any type of failure is treated as temporary. - if (UseRelayHost) { // SMTP.use_relay) { + if (SMTP.use_relay) { Connection *conn = ConnAlloc(TRUE); - conn->socketAddress.sin_addr.s_addr = inet_addr(RelayHost); // SMTP.relay_host); + conn->socketAddress.sin_addr.s_addr = inet_addr(SMTP.relay_host); conn->socketAddress.sin_family = AF_INET; conn->socketAddress.sin_port = htons (25); // TODO: configurable? if (conn->socketAddress.sin_addr.s_addr == -1) { @@ -2351,7 +2256,7 @@ finish: } int -RewriteAddress (unsigned char *Source, unsigned char *Target, unsigned int TargetSize) +RewriteAddress(Connection * conn, unsigned char *Source, unsigned char *Target, unsigned int TargetSize) { unsigned char WorkSpace[1024]; unsigned char *Src, *Dst; @@ -2492,70 +2397,54 @@ RewriteAddress (unsigned char *Source, unsigned char *Target, unsigned int Targe } /* Clean address now in WorkSpace */ - RetVal = MAIL_REMOTE; - /** Check if host matches local host **/ - Src = WorkSpace + strlen (WorkSpace) - 1; - while (Src > WorkSpace) { - if (*Src == '@') { - XplRWReadLockAcquire (&ConfigLock); - for (i = 0; i < UserDomainCount; i++) { - if (XplStrCaseCmp ((Src + 1), UserDomains[i]) == 0) { - *Src = '\0'; - if (strrchr (WorkSpace, '%') != NULL) { - RetVal = MAIL_BOGUS; - } - else { - RetVal = MAIL_LOCAL; - } - *Src = '@'; - break; - } - } - for (i = 0; i < RelayDomainCount; i++) { - if (XplStrCaseCmp ((Src + 1), RelayDomains[i]) == 0) { - *Src = '\0'; - if (strrchr (WorkSpace, '%') != NULL) { - RetVal = MAIL_REMOTE; - } - else { - RetVal = MAIL_RELAY; - } - *Src = '@'; - break; - } - } - if (RetVal == MAIL_REMOTE) { - for (i = 0; i < DomainCount; i++) { - if (XplStrCaseCmp ((Src + 1), Domains[i]) == 0) { - *Src = '\0'; - if ((Dst = strrchr (WorkSpace, '%')) != NULL) { - *Dst = '@'; - RetVal = MAIL_REMOTE; - } - else { - RetVal = MAIL_LOCAL; - } - break; - } - } - } - XplRWReadLockRelease (&ConfigLock); - } - Src--; - } - - /* Clean address now in WorkSpace */ - - if (WorkSpace[0] == '\0') + if (WorkSpace[0] == '\0') { return (MAIL_BOGUS); - - /** We're done **/ - if (strlen (WorkSpace) < TargetSize) { - strcpy (Target, WorkSpace); } - else { - strncpy (Target, WorkSpace, TargetSize - 1); - Target[TargetSize - 1] = '\0'; + + /* TODO: i'm not sure this code is functionally equivalient with its replacement due to the address checking */ + { + unsigned char addr[1024]; + unsigned char *ptr; + + NMAPSendCommandF(conn, "ADDRESS RESOLVE %s\r\n", WorkSpace); + RetVal = NMAPReadResponse(conn, addr, 1023, FALSE); + + /* find the second space */ + ptr = strchr(addr, ' '); + if (ptr) { + ptr++; + ptr = strchr(ptr, ' '); + if (ptr) { + ptr++; + } + } + + if (!ptr) { + /* there was an error getting back the address */ + ptr = WorkSpace; + } + + if (strlen (ptr) < TargetSize) { + strcpy (Target, ptr); + } else { + strncpy (Target, ptr, TargetSize - 1); + Target[TargetSize - 1] = '\0'; + } + + switch (RetVal) { + case 1000: + RetVal = MAIL_LOCAL; + break; + case 1001: + RetVal = MAIL_RELAY; + break; + case 1002: + RetVal = MAIL_REMOTE; + break; + default: + RetVal = MAIL_BOGUS; + break; + } } return (RetVal); @@ -2655,7 +2544,7 @@ ProcessRemoteEntry (ConnectionStruct * Client, unsigned long Size, int Lines) *ptr = '\0'; } - rc = RewriteAddress (Reply + 1, Recips[NumRecips].To, MAXEMAILNAMESIZE); + rc = RewriteAddress (Client->client.conn, Reply + 1, Recips[NumRecips].To, MAXEMAILNAMESIZE); if (rc == MAIL_BOGUS) { rc = DELIVER_BOGUS_NAME; Recips[NumRecips].Result = rc; @@ -2910,8 +2799,7 @@ RelayRemoteEntry (ConnectionStruct * client, unsigned long size, int lines) *bufferPtr = '\0'; - rc = RewriteAddress (reply + 1, bufferPtr, - size - (bufferPtr - buffer)); + rc = RewriteAddress (client->client.conn, reply + 1, bufferPtr, size - (bufferPtr - buffer)); if (rc == MAIL_BOGUS) { rc = DELIVER_BOGUS_NAME; recips[recipCount].Result = rc; @@ -3246,7 +3134,7 @@ RelayLocalEntry (ConnectionStruct * client, unsigned long size, } } - rc = RewriteAddress (buffer + 1, to, sizeof (to)); + rc = RewriteAddress (client->client.conn, buffer + 1, to, sizeof (to)); switch (rc) { case MAIL_BOGUS:{ if (flags & DSN_FAILURE) { @@ -3445,7 +3333,7 @@ ProcessLocalEntry (ConnectionStruct * Client, unsigned long Size, } } - rc = RewriteAddress (Line + 1, To, sizeof (To)); + rc = RewriteAddress (Client->client.conn, Line + 1, To, sizeof (To)); switch (rc) { case MAIL_BOGUS:{ if (Flags & DSN_FAILURE) { @@ -3591,7 +3479,7 @@ HandleQueueConnection (void *ClientIn) } Lines = atol (ptr + 1); - if (!RelayLocalMail) { + if (!SMTP.relay_local) { if (Queue == Q_OUTGOING) { ProcessRemoteEntry (Client, Size, Lines); } @@ -3622,6 +3510,7 @@ QueueServerStartup (void *ignored) ConnectionStruct *client; int ccode; XplThreadID id = 0; + BOOL qd = FALSE, qo = FALSE; XplRenameThread (XplGetThreadID (), "SMTP NMAP Q Monitor"); @@ -3643,13 +3532,23 @@ QueueServerStartup (void *ignored) } /* register on the two queues we need to be on */ - if (NMAPRegister(MSGSRV_AGENT_SMTP, Q_DELIVER, SMTPQServerConnection->socketAddress.sin_port) != REGISTRATION_COMPLETED || - NMAPRegister(MSGSRV_AGENT_SMTP, Q_OUTGOING, SMTPQServerConnection->socketAddress.sin_port) != REGISTRATION_COMPLETED) { - XplConsolePrintf("bongosmtp: Could not register with bongonmap\r\n"); - ConnFree(SMTPQServerConnection); - raise(SIGTERM); - return; - } + while (!qd && !qo) { + if (!qd) { + qd = (QueueRegister(MSGSRV_AGENT_SMTP, Q_DELIVER, SMTPQServerConnection->socketAddress.sin_port) == REGISTRATION_COMPLETED); + } + if (!qo) { + qo = (QueueRegister(MSGSRV_AGENT_SMTP, Q_OUTGOING, SMTPQServerConnection->socketAddress.sin_port) == REGISTRATION_COMPLETED); + } + if (Exiting) { + ConnFree(SMTPQServerConnection); + raise(SIGTERM); + return; + } + if (!qd || !qo) { + Log(LOG_ERROR, "Could not register with bongoqueue, sleeping for 3 seconds"); + XplDelay(3000); + } + }; while (!Exiting) { if (ConnAccept(SMTPQServerConnection, &conn) != -1) { @@ -3677,9 +3576,7 @@ QueueServerStartup (void *ignored) XplSafeDecrement (SMTPServerThreads); -#if VERBOSE - XplConsolePrintf ("SMTPD: Queue monitor thread done.\r\n"); -#endif + Log(LOG_DEBUG, "Queue monitor thread done."); return; } @@ -3713,12 +3610,12 @@ ServerSocketInit (void) SMTPServerConnection = ConnAlloc(FALSE); if (!SMTPServerConnection) { - XplConsolePrintf("bongoimap: Could not allocate the connection\n"); + Log(LOG_ERROR, "Could not allocate the connection."); return -1; } SMTPServerConnection->socketAddress.sin_family = AF_INET; - SMTPServerConnection->socketAddress.sin_port = htons(SMTPServerPort); + SMTPServerConnection->socketAddress.sin_port = htons(SMTP.port); SMTPServerConnection->socketAddress.sin_addr.s_addr = MsgGetAgentBindIPAddress(); /* Get root privs back for the bind. It's ok if this fails - @@ -3729,15 +3626,13 @@ ServerSocketInit (void) /* drop the privs back */ if (XplSetEffectiveUser (MsgGetUnprivilegedUser ()) < 0) { - Log(LOG_ERROR, "Priv failure User %s", MsgGetUnprivilegedUser ()); - XplConsolePrintf ("bongosmtp: Could not drop to unprivileged user '%s'\n", MsgGetUnprivilegedUser ()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser ()); return -1; } if (SMTPServerConnection->socket < 0) { ccode = SMTPServerConnection->socket; - Log(LOG_ERROR, "Create socket failed %s Line %d", "", __LINE__); - XplConsolePrintf ("bongosmtp: Could not allocate socket.\n"); + Log(LOG_ERROR, "Could not allocate SMTP socket"); ConnFree(SMTPServerConnection); return ccode; } @@ -3751,13 +3646,13 @@ ServerSocketSSLInit (void) SMTPServerConnectionSSL = ConnAlloc(FALSE); if (SMTPServerConnectionSSL == NULL) { - XplConsolePrintf("bongoimap: Could not allocate the connection\n"); + Log(LOG_ERROR, "Could not allocate the SSL connection"); ConnFree(SMTPServerConnection); return -1; } SMTPServerConnectionSSL->socketAddress.sin_family = AF_INET; - SMTPServerConnectionSSL->socketAddress.sin_port = htons (SMTPServerPortSSL); + SMTPServerConnectionSSL->socketAddress.sin_port = htons (SMTP.port_ssl); SMTPServerConnectionSSL->socketAddress.sin_addr.s_addr = MsgGetAgentBindIPAddress (); /* Get root privs back for the bind. It's ok if this fails - @@ -3767,15 +3662,13 @@ ServerSocketSSLInit (void) SMTPServerConnectionSSL->socket = ConnServerSocket(SMTPServerConnectionSSL, 2048); /* drop the privs back */ if (XplSetEffectiveUser (MsgGetUnprivilegedUser ()) < 0) { - Log(LOG_ERROR, "Priv failure User %s", MsgGetUnprivilegedUser ()); - XplConsolePrintf ("bongosmtp: Could not drop to unprivileged user '%s'\n", MsgGetUnprivilegedUser ()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s' for SSL", MsgGetUnprivilegedUser ()); return -1; } if (SMTPServerConnectionSSL->socket < 0) { ccode = SMTPServerConnectionSSL->socket; - Log(LOG_ERROR, "Create socket failed %s Line %d", "", __LINE__); - XplConsolePrintf ("bongosmtp: Could not allocate socket.\n"); + Log(LOG_ERROR, "Could not allocate SSL socket"); ConnFree(SMTPServerConnection); return ccode; } @@ -3799,7 +3692,7 @@ SMTPServer (void *ignored) if (ConnAccept(SMTPServerConnection, &conn) != -1) { if (!Exiting) { if (!SMTPReceiverStopped) { - if (XplSafeRead(SMTPConnThreads) < SMTPMaxThreadLoad) { + if (XplSafeRead(SMTPConnThreads) < SMTP.max_thread_load) { client = GetSMTPConnection(); if (client) { client->client.conn = conn; @@ -3852,10 +3745,7 @@ SMTPServer (void *ignored) } default:{ - arg = errno; - - Log(LOG_ALERT, "Accept failure %s Errno %d", "Server", arg); - XplConsolePrintf ("SMTPD: Exiting after an accept() failure with an errno: %d\n", arg); + Log(LOG_ALERT, "Accept failure: Errno %d", errno); break; } @@ -3873,9 +3763,8 @@ SMTPServer (void *ignored) oldTGID = XplSetThreadGroupID (TGid); -#if VERBOSE - XplConsolePrintf ("\rSMTPD: Closing server sockets\r\n"); -#endif + Log(LOG_DEBUG, "Closing server socket"); + if (SMTPServerConnection) { ConnClose(SMTPServerConnection, 1); ConnFree(SMTPServerConnection); @@ -3908,12 +3797,10 @@ SMTPServer (void *ignored) } if (XplSafeRead (SMTPServerThreads) > 1) { - XplConsolePrintf ("SMTPD: %d server threads outstanding; attempting forceful unload.\r\n", XplSafeRead (SMTPServerThreads) - 1); + Log(LOG_ERROR, "%d server threads outstanding; attempting forceful unload.", XplSafeRead(SMTPServerThreads)-1); } -#if VERBOSE - XplConsolePrintf ("SMTPD: Shutting down %d conn client threads and %d queue client threads\r\n", XplSafeRead (SMTPConnThreads), XplSafeRead (SMTPQueueThreads)); -#endif + Log(LOG_DEBUG, "Shutting down %d conn client threads and %d queue client threads.", XplSafeRead(SMTPConnThreads), XplSafeRead(SMTPQueueThreads)); /* Make sure the kids have flown the coop. */ for (arg = 0; (XplSafeRead (SMTPConnThreads) + XplSafeRead (SMTPQueueThreads)) && (arg < 3 * 60); arg++) { @@ -3921,20 +3808,10 @@ SMTPServer (void *ignored) } if (XplSafeRead (SMTPConnThreads) + XplSafeRead (SMTPQueueThreads)) { - XplConsolePrintf ("SMTPD: %d threads outstanding; attempting forceful unload.\r\n", XplSafeRead (SMTPConnThreads) + XplSafeRead (SMTPQueueThreads)); + Log(LOG_ERROR, "%d threads outstanding; attempting forceful unload.", XplSafeRead(SMTPConnThreads)+XplSafeRead(SMTPQueueThreads)); } -#if VERBOSE - XplConsolePrintf ("SMTPD: Freeing data structures\r\n"); -#endif - - FreeDomains (); - FreeUserDomains (); - FreeRelayDomains (); - -#if VERBOSE - XplConsolePrintf ("SMTPD: Removing SSL data\r\n"); -#endif + Log(LOG_DEBUG, "Removing SSL data"); /* Cleanup SSL */ if (SSLContext) { @@ -3946,16 +3823,13 @@ SMTPServer (void *ignored) XplRWLockDestroy (&ConfigLock); MsgShutdown (); -// MDBShutdown(); ConnShutdown (); MemPrivatePoolFree (SMTPConnectionPool); MemoryManagerClose (MSGSRV_AGENT_SMTP); -#if VERBOSE - XplConsolePrintf ("SMTPD: Shutdown complete.\r\n"); -#endif + Log(LOG_DEBUG, "Shutdown complete."); XplSignalLocalSemaphore (SMTPServerSemaphore); XplWaitOnLocalSemaphore (SMTPShutdownSemaphore); @@ -3985,7 +3859,7 @@ SMTPSSLServer (void *ignored) conn->ssl.enable = TRUE; if (!Exiting) { if (!SMTPReceiverStopped) { - if (XplSafeRead(SMTPConnThreads) < SMTPMaxThreadLoad) { + if (XplSafeRead(SMTPConnThreads) < SMTP.max_thread_load) { client = GetSMTPConnection(); if (client) { client->client.conn = conn; @@ -4047,9 +3921,7 @@ SMTPSSLServer (void *ignored) break; } default:{ - arg = errno; - Log(LOG_ALERT, "Accept failure %s Errno %d", "Server", arg); - XplConsolePrintf ("SMTPD: Exiting after an accept() failure with an errno: %d\n", arg); + Log(LOG_ALERT, "Accept failure Errno %d", errno); break; } } @@ -4059,9 +3931,7 @@ SMTPSSLServer (void *ignored) XplSafeDecrement (SMTPServerThreads); -#if VERBOSE - XplConsolePrintf ("SMTPD: SSL listening thread done.\r\n"); -#endif + Log(LOG_DEBUG, "SSL Listening thread terminated."); if (SMTPServerConnectionSSL) { ConnFree(SMTPServerConnectionSSL); @@ -4075,786 +3945,35 @@ SMTPSSLServer (void *ignored) return; } -static void -AddDomain (unsigned char *DomainValue) -{ - Domains = - MemRealloc (Domains, (DomainCount + 1) * sizeof (unsigned char *)); - if (!Domains) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, (DomainCount + 1) * sizeof (unsigned char *), __LINE__); - return; - } - Domains[DomainCount] = MemStrdup (DomainValue); - if (!Domains[DomainCount]) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, strlen (DomainValue) + 1, __LINE__); - return; - } - DomainCount++; -} - -void -FreeDomains (void) -{ - unsigned int i; - - for (i = 0; i < DomainCount; i++) - MemFree (Domains[i]); - - if (Domains) { - MemFree (Domains); - } - - Domains = NULL; - DomainCount = 0; -} - -static void -AddUserDomain (unsigned char *UserDomainValue) -{ - UserDomains = - MemRealloc (UserDomains, - (UserDomainCount + 1) * sizeof (unsigned char *)); - if (!UserDomains) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, (UserDomainCount + 1) * sizeof (unsigned char *), __LINE__); - return; - } - UserDomains[UserDomainCount] = MemStrdup (UserDomainValue); - if (!UserDomains[UserDomainCount]) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, strlen (UserDomainValue) + 1, __LINE__); - return; - } - UserDomainCount++; -} - -void -FreeUserDomains (void) -{ - unsigned int i; - - for (i = 0; i < UserDomainCount; i++) - MemFree (UserDomains[i]); - - if (UserDomains) { - MemFree (UserDomains); - } - - UserDomains = NULL; - UserDomainCount = 0; -} - -static void -AddRelayDomain (unsigned char *RelayDomainValue) -{ - RelayDomains = - MemRealloc (RelayDomains, - (RelayDomainCount + 1) * sizeof (unsigned char *)); - if (!RelayDomains) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, (RelayDomainCount + 1) * sizeof (unsigned char *), __LINE__); - return; - } - RelayDomains[RelayDomainCount] = MemStrdup (RelayDomainValue); - if (!RelayDomains[RelayDomainCount]) { - Log(LOG_ERROR, "Out of memory File %s %d Line %d", - __FILE__, strlen (RelayDomainValue) + 1, __LINE__); - return; - } - RelayDomainCount++; -} - -void -FreeRelayDomains (void) -{ - unsigned int i; - - for (i = 0; i < RelayDomainCount; i++) - MemFree (RelayDomains[i]); - - if (RelayDomains) { - MemFree (RelayDomains); - } - - RelayDomains = NULL; - RelayDomainCount = 0; -} - #define SetPtrToValue(Ptr,String) Ptr=String;while(isspace(*Ptr)) Ptr++;if ((*Ptr=='=') || (*Ptr==':')) Ptr++; while(isspace(*Ptr)) Ptr++; -static void -SmtpdConfigMonitor (void) -{ - MDBValueStruct *Config; - MDBValueStruct *Parents; - unsigned int i, j; - struct sockaddr_in soc_address; - struct hostent *he; - struct sockaddr_in *sin = &soc_address; - BOOL Added, Exists; - char *ptr; - MDBEnumStruct *ES; - long PrevConfigNumber; - - XplRenameThread (XplGetThreadID (), "SMTP Config Monitor"); - - Config = - MDBCreateValueStruct (SMTPDirectoryHandle, MsgGetServerDN (NULL)); - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_CONFIG_CHANGED, Config) > 0) { - PrevConfigNumber = atol (Config->Value[0]); - } - else { - PrevConfigNumber = 0; - } - MDBDestroyValueStruct (Config); - - while (!Exiting) { - Config = - MDBCreateValueStruct (SMTPDirectoryHandle, MsgGetServerDN (NULL)); - Parents = - MDBCreateValueStruct (SMTPDirectoryHandle, MsgGetServerDN (NULL)); - - ES = MDBCreateEnumStruct (Config); - - for (i = 0; (i < 300) && !Exiting; i++) { - XplDelay (1000); - } - - if (!Exiting) { - Log(LOG_INFO, "Agent heartbeat"); - - if ((MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_CONFIG_CHANGED, Config) - > 0) && (atol (Config->Value[0]) != PrevConfigNumber)) { - /* Clear what we just read */ - PrevConfigNumber = atol (Config->Value[0]); - MDBFreeValues (Config); - - /* Acquire Write Lock */ - XplRWWriteLockAcquire (&ConfigLock); - - FreeDomains (); - FreeUserDomains (); - FreeRelayDomains (); - - soc_address.sin_addr.s_addr = XplGetHostIPAddress (); - sprintf (Hostaddr, "[%d.%d.%d.%d]", sin->sin_addr.s_net, - sin->sin_addr.s_host, sin->sin_addr.s_lh, - sin->sin_addr.s_impno); - AddDomain (Hostaddr); - - strcpy (OfficialName, Hostname); - - MDBReadDN (MSGSRV_AGENT_SMTP, MSGSRV_A_PARENT_OBJECT, - Parents); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_DOMAIN, Config) > 0) { - for (i = 0; i < Config->Used; i++) { - AddDomain (Config->Value[i]); - /* XplConsolePrintf("[%04d] MDB_A_DOMAIN:%s", __LINE__, Config->Value[i]); */ - } - } - he = gethostbyaddr ((unsigned char *) - &(soc_address.sin_addr.s_addr), - sizeof (soc_address.sin_addr.s_addr), - AF_INET); - - Added = FALSE; - if (he) { - Exists = FALSE; - for (j = 0; j < DomainCount; j++) { - if (XplStrCaseCmp (Domains[j], he->h_name) == 0) { - Exists = TRUE; - break; - } - } - if (!Exists) { - AddDomain (he->h_name); - MDBAddValue (he->h_name, Config); - Added = TRUE; - } - - if (he->h_aliases) { - i = 0; - while (he->h_aliases[i]) { - Exists = FALSE; - for (j = 0; j < DomainCount; j++) { - if (XplStrCaseCmp - (Domains[j], he->h_aliases[i]) == 0) { - Exists = TRUE; - break; - } - } - if (!Exists) { - AddDomain (he->h_aliases[i]); - MDBAddValue (he->h_aliases[i], Config); - Added = TRUE; - } - i++; - } - } - } - - if (Added) { - MDBWrite (MSGSRV_AGENT_SMTP, MSGSRV_A_DOMAIN, Config); - } - - MDBFreeValues (Config); - - for (j = 0; j < Parents->Used; j++) { - Log(LOG_INFO, "Configuration string %s Value %s" - "MSGSRV_A_PARENT_OBJECT", Parents->Value[j]); - if (MDBRead (Parents->Value[j], MSGSRV_A_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddDomain (Config->Value[i]); - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_USER_DOMAIN, Config) - > 0) { - for (i = 0; i < Config->Used; i++) { - AddUserDomain (Config->Value[i]); - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_USER_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - - for (j = 0; j < Parents->Used; j++) { - if (MDBRead - (Parents->Value[j], MSGSRV_A_USER_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddUserDomain (Config->Value[i]); - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_USER_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_RELAY_DOMAIN, Config) - > 0) { - for (i = 0; i < Config->Used; i++) { - AddRelayDomain (Config->Value[i]); - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_RELAY_DOMAIN", Config->Value[i]); - } - } - for (j = 0; j < Parents->Used; j++) { - if (MDBRead - (Parents->Value[j], MSGSRV_A_RELAY_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddRelayDomain (Config->Value[i]); - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_RELAY_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (".", MSGSRV_A_OFFICIAL_NAME, Config) > 0) { - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_OFFICIAL_NAME", Config->Value[0]); - AddDomain (Hostname); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ALLOW_EXPN, Config)) { - AllowEXPN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ALLOW_EXPN", AllowEXPN); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ALLOW_VRFY, Config)) { - AllowVRFY = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ALLOW_VRFY", AllowVRFY); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_VERIFY_ADDRESS, - Config)) { - CheckRCPT = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_VERIFY_ADDRESS", CheckRCPT); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ACCEPT_ETRN, Config)) { - AcceptETRN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ACCEPT_ETRN", AcceptETRN); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_SEND_ETRN, Config)) { - SendETRN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_SEND_ETRN", SendETRN); - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_RECIPIENT_LIMIT, Config)) { - MaximumRecipients = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_RECIPIENT_LIMIT", MaximumRecipients); - if (MaximumRecipients == 0) { - MaximumRecipients = ULONG_MAX; - } - } - else { - MaximumRecipients = ULONG_MAX; - } - MDBFreeValues (Config); - - MaxNullSenderRecips = ULONG_MAX; - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_CONFIGURATION, Config) > 0) { - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_CONFIGURATION", Config->Value[i]); - - for (i = 0; i < Config->Used; i++) { - if (XplStrNCaseCmp - (Config->Value[i], "MaxFloodCount=", 14) == 0) { - MaxFloodCount = atol (Config->Value[i] + 14); - } - else if (XplStrNCaseCmp - (Config->Value[i], "MaxNullSenderRecips=", - 20) == 0) { - ptr = Config->Value[i] + 20; - while (isspace (*ptr)) { - ptr++; - } - - MaxNullSenderRecips = atol (ptr); - if (MaxNullSenderRecips == 0) { - MaxNullSenderRecips = ULONG_MAX; - } - } - } - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_UBE_SMTP_AFTER_POP, - Config)) { - if (Config->Value[0]) { - UBEConfig |= UBE_SMTP_AFTER_POP; - } else { - UBEConfig &= ~UBE_SMTP_AFTER_POP; - } - } - MDBFreeValues (Config); - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_UBE_REMOTE_AUTH_ONLY, - Config)) { - if (Config->Value[0]) { - UBEConfig |= UBE_REMOTE_AUTH_ONLY; - } else { - UBEConfig &= ~UBE_REMOTE_AUTH_ONLY; - } - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_RTS_ANTISPAM_CONFIG, - Config) > 0) { - if (sscanf - (Config->Value[0], - "Enabled:%d Delay:%ld Threshhold:%lu", &BlockRTSSpam, - &BounceInterval, &MaxBounceCount) != 3) { - BlockRTSSpam = FALSE; - } - if ((MaxBounceCount < 1) || (BounceInterval < 1)) { - BlockRTSSpam = FALSE; - } - } - else { - BlockRTSSpam = FALSE; - } - MDBFreeValues (Config); - - if (MDBRead - (MSGSRV_AGENT_SMTP, MSGSRV_A_MESSAGE_LIMIT, Config)) { - MessageLimit = atol (Config->Value[0]) * 1024 * 1024; /* Convert megabytes to bytes */ - Log(LOG_INFO, "Configuration numeric", - "MSGSRV_A_MESSAGE_LIMIT", MessageLimit); - } - MDBFreeValues (Config); - - XplRWWriteLockRelease (&ConfigLock); - } - } - - MDBDestroyEnumStruct (ES, Config); - MDBDestroyValueStruct (Parents); - MDBDestroyValueStruct (Config); - } - -#if VERBOSE - XplConsolePrintf ("SMTPD: Configuration monitor thread done.\r\n"); -#endif - - XplSafeDecrement (SMTPServerThreads); - - XplExitThread (TSR_THREAD, 0); -} - - static BOOL ReadConfiguration (void) { - unsigned char *ptr; +/* struct sockaddr_in soc_address; - struct hostent *he; struct sockaddr_in *sin = &soc_address; - MDBValueStruct *Config; - MDBValueStruct *Parents; - MDBEnumStruct *ES; - unsigned int i = 0, j; - BOOL Exists, Added; - - - Config = - MDBCreateValueStruct (SMTPDirectoryHandle, MsgGetServerDN (NULL)); - Parents = - MDBCreateValueStruct (SMTPDirectoryHandle, MsgGetServerDN (NULL)); - - ES = MDBCreateEnumStruct (Config); soc_address.sin_addr.s_addr = XplGetHostIPAddress (); - sprintf (Hostaddr, "[%d.%d.%d.%d]", sin->sin_addr.s_net, + sprintf (SMTP.hostaddr, "[%d.%d.%d.%d]", sin->sin_addr.s_net, sin->sin_addr.s_host, sin->sin_addr.s_lh, sin->sin_addr.s_impno); - AddDomain (Hostaddr); - if (strlen (Hostname) < sizeof (OfficialName)) { - strcpy (OfficialName, Hostname); - } - - MDBReadDN (MSGSRV_AGENT_SMTP, MSGSRV_A_PARENT_OBJECT, Parents); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_DOMAIN, Config) > 0) { - for (i = 0; i < Config->Used; i++) { - AddDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_DOMAIN", Config->Value[i]); - } - } - - he = gethostbyaddr ((unsigned char *) &(soc_address.sin_addr.s_addr), - sizeof (soc_address.sin_addr.s_addr), AF_INET); - - Added = FALSE; - if (he) { - Exists = FALSE; - for (j = 0; j < DomainCount; j++) { - if (XplStrCaseCmp (Domains[j], he->h_name) == 0) { - Exists = TRUE; - break; - } - } - if (!Exists) { - AddDomain (he->h_name); - MDBAddValue (he->h_name, Config); - Added = TRUE; - } - - if (he->h_aliases) { - i = 0; - while (he->h_aliases[i]) { - Exists = FALSE; - for (j = 0; j < DomainCount; j++) { - if (XplStrCaseCmp (Domains[j], he->h_aliases[i]) == 0) { - Exists = TRUE; - break; - } - } - if (!Exists) { - AddDomain (he->h_aliases[i]); - MDBAddValue (he->h_aliases[i], Config); - Added = TRUE; - } - i++; - } - } - } - - if (Added) { - MDBWrite (MSGSRV_AGENT_SMTP, MSGSRV_A_DOMAIN, Config); - } - - MDBFreeValues (Config); - - for (j = 0; j < Parents->Used; j++) { - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_PARENT_OBJECT", Parents->Value[j]); - if (MDBRead (Parents->Value[j], MSGSRV_A_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_USER_DOMAIN, Config) > 0) { - for (i = 0; i < Config->Used; i++) { - AddUserDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_USER_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - - for (j = 0; j < Parents->Used; j++) { - if (MDBRead (Parents->Value[j], MSGSRV_A_USER_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddUserDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_USER_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_RELAY_DOMAIN, Config) > 0) { - for (i = 0; i < Config->Used; i++) { - AddRelayDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_RELAY_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - - for (j = 0; j < Parents->Used; j++) { - if (MDBRead (Parents->Value[j], MSGSRV_A_RELAY_DOMAIN, Config)) { - for (i = 0; i < Config->Used; i++) { - AddRelayDomain (Config->Value[i]); - Log(LOG_INFO, "Config numeric %s Value %s", - "MSGSRV_A_RELAY_DOMAIN", Config->Value[i]); - } - } - MDBFreeValues (Config); - } - - if (MDBRead (".", MSGSRV_A_OFFICIAL_NAME, Config) > 0) { - if (strlen (Config->Value[0]) < sizeof (OfficialName)) { - strcpy (OfficialName, Config->Value[0]); - } - if (strlen (Config->Value[0]) < sizeof (Hostname)) { - strcpy (Hostname, Config->Value[0]); - } - Log(LOG_INFO, "Config numeric %s value %s", - "MSGSRV_A_OFFICIAL_NAME", Config->Value[0]); - AddDomain (Hostname); - } - MDBFreeValues (Config); - - if (MDBRead (".", MSGSRV_A_SSL_TLS, Config)) { - if (atol(Config->Value[0])) { - AllowClientSSL = TRUE; - } - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ALLOW_EXPN, Config)) { - AllowEXPN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ALLOW_EXPN", AllowEXPN); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ALLOW_VRFY, Config)) { - AllowVRFY = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ALLOW_VRFY", AllowVRFY); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_VERIFY_ADDRESS, Config)) { - CheckRCPT = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_VERIFY_ADDRESS", CheckRCPT); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_ACCEPT_ETRN, Config)) { - AcceptETRN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_ACCEPT_ETRN", AcceptETRN); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_SMTP_SEND_ETRN, Config)) { - SendETRN = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_SMTP_SEND_ETRN", SendETRN); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_RECIPIENT_LIMIT, Config)) { - MaximumRecipients = atol (Config->Value[0]); - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_RECIPIENT_LIMIT", MaximumRecipients); - if (MaximumRecipients == 0) { - MaximumRecipients = ULONG_MAX; - } - } - else { - MaximumRecipients = ULONG_MAX; - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_UBE_SMTP_AFTER_POP, Config)) { - if (Config->Value[0]) { - UBEConfig |= UBE_SMTP_AFTER_POP; - } else { - UBEConfig &= ~UBE_SMTP_AFTER_POP; - } - } - MDBFreeValues (Config); - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_UBE_REMOTE_AUTH_ONLY, Config)) { - if (Config->Value[0]) { - UBEConfig |= UBE_REMOTE_AUTH_ONLY; - } else { - UBEConfig &= ~UBE_REMOTE_AUTH_ONLY; - } - } - MDBFreeValues (Config); - - if (MDBRead (".", MSGSRV_A_POSTMASTER, Config)) { - ptr = strrchr (Config->Value[0], '\\'); - if (ptr) { - if (strlen (ptr + 1) < sizeof (Postmaster)) { - strcpy (Postmaster, ptr + 1); - } - } - else { - if (strlen (Config->Value[0]) < sizeof (Postmaster)) { - strcpy (Postmaster, Config->Value[0]); - } - - } - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_POSTMASTER", Postmaster); - } - MDBFreeValues (Config); - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_MESSAGE_LIMIT, Config)) { - MessageLimit = atol (Config->Value[0]) * 1024 * 1024; /* Convert megabytes to bytes */ - Log(LOG_INFO, "Configuration numeric %s Value %d", - "MSGSRV_A_MESSAGE_LIMIT", MessageLimit); - } - MDBFreeValues (Config); +*/ + // FIXME: Does SMTP need to know about the various domains? Or will queue fix that? + /* FIXME. This should be replaced by pulling config from the store. */ +#if 0 if (MsgReadIP (MSGSRV_AGENT_SMTP, MSGSRV_A_QUEUE_SERVER, Config)) { strcpy (NMAPServer, Config->Value[0]); Log(LOG_INFO, "Configuration string %s Value %s", "MSGSRV_A_QUEUE_SERVER", Config->Value[0]); } MDBFreeValues (Config); - - if (RelayHost[0] == '\0') { - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_RELAYHOST, Config) > 0) { - strcpy (RelayHost, Config->Value[0]); - if ((RelayHost[0] != '\0') && (RelayHost[0] != ' ')) { - UseRelayHost = TRUE; - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_RELAYHOST", Config->Value[0]); - } - else { - UseRelayHost = FALSE; - } - } - else { - UseRelayHost = FALSE; - } - MDBFreeValues (Config); - } - - if (MDBRead (MSGSRV_AGENT_SMTP, MSGSRV_A_RTS_ANTISPAM_CONFIG, Config) > 0) { - Log(LOG_INFO, "Configuration string %s Value %s", - "MSGSRV_A_RTS_ANTISPAM_CONFIG", Config->Value[0]); - if (sscanf - (Config->Value[0], "Enabled:%d Delay:%ld Threshhold:%lu", - &BlockRTSSpam, &BounceInterval, &MaxBounceCount) != 3) { - BlockRTSSpam = FALSE; - } - if ((MaxBounceCount < 1) || (BounceInterval < 1)) { - BlockRTSSpam = FALSE; - } - } - else { - BlockRTSSpam = FALSE; - } - MDBFreeValues (Config); - - MaxNullSenderRecips = ULONG_MAX; - - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_PORT, Config)>0) { - SMTPServerPort = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_SSL_PORT, Config)>0) { - SMTPServerPortSSL = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_MAX_LOAD, Config)>0) { - SMTPMaxThreadLoad = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_MAX_FLOOD_COUNT, Config)>0) { - MaxFloodCount = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_TIMEOUT, Config)>0) { - SocketTimeout = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_MAX_NULL_SENDER_RECIPS, Config)>0) { - MaxNullSenderRecips = atol (Config->Value[0]); - if (MaxNullSenderRecips == 0) { - MaxNullSenderRecips = ULONG_MAX; - } - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_MAX_MX_SERVERS, Config)>0) { - MaxMXServers = atol (Config->Value[0]); - } - MDBFreeValues(Config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_RELAY_LOCAL_MAIL, Config)>0) { - if (UseRelayHost) { - if (atol (Config->Value[0])) { - RelayLocalMail = TRUE; - } - } - else { - XplConsolePrintf ("bongosmtp: relay local mail configured without a relay host; ignoring.\r\n"); - } - } - MDBFreeValues(Config); - - MDBSetValueStructContext (NULL, Config); - if (MDBRead (MSGSRV_ROOT, MSGSRV_A_ACL, Config) > 0) { - HashCredential (MsgGetServerDN (NULL), Config->Value[0], NMAPHash); - } - - MDBDestroyEnumStruct (ES, Config); - MDBDestroyValueStruct (Parents); - MDBDestroyValueStruct (Config); +#endif LocalAddress = MsgGetHostIPAddress (); + MsgGetServerCredential(&NMAPHash); + return (TRUE); } @@ -4901,31 +4020,33 @@ int XplServiceMain (int argc, char *argv[]) Log(LOG_ERROR, "Unable to initialize memory manager, shutting down"); return (-1); } + + MsgInit(); + MsgAuthInit(); - ConnStartup (SocketTimeout, TRUE); + // FIXME: Connio socket timeout needs to be a run-time tunable. bug #9924 + // ConnStartup (SMTP.socket_timeout, TRUE); + ConnStartup(600, TRUE); - MDBInit (); - if ((SMTPDirectoryHandle = (MDBHandle) MsgInit ()) == NULL) { - Log(LOG_ERROR, "Invalid directory credentials, shutting down"); - - MemoryManagerClose (MSGSRV_AGENT_SMTP); - - exit (-1); - } - - CMInitialize(SMTPDirectoryHandle, "SMTP"); - NMAPInitialize(SMTPDirectoryHandle); + NMAPInitialize(); XplRWLockInit (&ConfigLock); - for (ccode = 1; argc && (ccode < argc); ccode++) { if (XplStrNCaseCmp (argv[ccode], "--forwarder=", 12) == 0) { - UseRelayHost = TRUE; - strcpy (RelayHost, argv[ccode] + 12); + SMTP.use_relay = TRUE; + strcpy (SMTP.relay_host, argv[ccode] + 12); } } + if (! ReadBongoConfiguration(SMTPConfig, "smtp")) { + Log(LOG_ERROR, "Unable to read SMTP configuration from the store."); + exit(-1); + } + if (! ReadBongoConfiguration(GlobalConfig, "global")) { + Log(LOG_ERROR, "Unable to read Global configration from the store."); + exit(-1); + } ReadConfiguration (); if (ServerSocketInit () < 0) { @@ -4934,23 +4055,22 @@ int XplServiceMain (int argc, char *argv[]) } XplBeginCountedThread (&ID, QueueServerStartup, STACKSIZE_Q, NULL, ccode, SMTPServerThreads); - XplBeginCountedThread (&ID, SmtpdConfigMonitor, STACKSIZE_Q, NULL, ccode, SMTPServerThreads); - if (AllowClientSSL) { + if (SMTP.allow_client_ssl) { if (!ServerSocketSSLInit()) { ConnSSLConfiguration sslconfig; - sslconfig.certificate.file = MsgGetTLSCertPath(NULL); - sslconfig.key.file = MsgGetTLSKeyPath(NULL); + sslconfig.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); + sslconfig.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); sslconfig.key.type = GNUTLS_X509_FMT_PEM; SSLContext = ConnSSLContextAlloc(&sslconfig); if (SSLContext) { XplBeginCountedThread (&ID, SMTPSSLServer, STACKSIZE_S, NULL, ccode, SMTPServerThreads); } else { - AllowClientSSL = FALSE; + SMTP.allow_client_ssl = FALSE; } } else { - AllowClientSSL = FALSE; + SMTP.allow_client_ssl = FALSE; } } diff --git a/src/agents/store/Bongo.rules b/src/agents/store/Bongo.rules index 1d9acb3..f7c148f 100644 --- a/src/agents/store/Bongo.rules +++ b/src/agents/store/Bongo.rules @@ -1,13 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongostore -bongostore_CPPFLAGS := $(AM_CPPFLAGS) \ +bongostore_CPPFLAGS = $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/agents/store \ -DCLUCENE_BONGO_API=$(CLUCENE_BONGO_API) \ $(SQLITE_CFLAGS) \ $(CLUCENE_CXXFLAGS) -bongostore_SOURCES := \ +bongostore_SOURCES = \ src/agents/store/alarmdb.c \ src/agents/store/alarmdb.h \ src/agents/store/auth.c \ @@ -28,6 +28,7 @@ bongostore_SOURCES := \ src/agents/store/lock.h \ src/agents/store/mail.c \ src/agents/store/mail.h \ + src/agents/store/maildir.c \ src/agents/store/mail-parser.c \ src/agents/store/mail-parser.h \ src/agents/store/main.cpp \ @@ -53,9 +54,7 @@ bongostore_LDADD = \ libbongo-json.la \ libbongocal.la \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongostreamio.la \ diff --git a/src/agents/store/alarmdb.c b/src/agents/store/alarmdb.c index 57f9623..de90cf9 100644 --- a/src/agents/store/alarmdb.c +++ b/src/agents/store/alarmdb.c @@ -163,9 +163,9 @@ AlarmDBOpen(BongoMemStack *memstack) create = access(path, 0); - if (!(handle = MemMalloc(sizeof(struct _AlarmDBHandle))) || - memset(handle, 0, sizeof(struct _AlarmDBHandle)), 0 || - SQLITE_OK != sqlite3_open(path, &handle->db)) + if (!(handle = MemMalloc(sizeof(struct _AlarmDBHandle))) || + (memset(handle, 0, sizeof(struct _AlarmDBHandle)), 0) || + (SQLITE_OK != sqlite3_open(path, &handle->db))) { printf("bongostore: Failed to open alarm store \"%s\".\r\n", path); goto fail; diff --git a/src/agents/store/auth.c b/src/agents/store/auth.c index 64bf55c..01ff16a 100644 --- a/src/agents/store/auth.c +++ b/src/agents/store/auth.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "stored.h" diff --git a/src/agents/store/calendar.c b/src/agents/store/calendar.c index f8e75a9..d7b5b51 100644 --- a/src/agents/store/calendar.c +++ b/src/agents/store/calendar.c @@ -47,7 +47,7 @@ StoreProcessIncomingEvent(StoreClient *client, /* FIXME */ - if (GetJson(client, info, &node) != BONGO_JSON_OK) { + if (GetJson(client, info, &node, NULL) != BONGO_JSON_OK) { goto parse_error; } @@ -236,7 +236,7 @@ StoreSetAlarm(StoreClient *client, /* load the event, and compute occurrences */ - if (BONGO_JSON_OK != GetJson(client, docinfo, &node) || + if (BONGO_JSON_OK != GetJson(client, docinfo, &node, NULL) || BONGO_JSON_OBJECT != node->type) { ccode = ConnWriteStr(client->conn, MSG4226BADEVENT); diff --git a/src/agents/store/command.c b/src/agents/store/command.c index 344200c..f2a6601 100644 --- a/src/agents/store/command.c +++ b/src/agents/store/command.c @@ -135,12 +135,6 @@ StoreSetupCommands() BongoHashtablePutNoReplace(CommandTable, "CONVERSATIONS", (void *) STORE_COMMAND_CONVERSATIONS) || - BongoHashtablePutNoReplace(CommandTable, "LISTCONVERSATION", - (void *) STORE_COMMAND_CONVERSATION) || - BongoHashtablePutNoReplace(CommandTable, "LISTCONVERSATIONS", - (void *) STORE_COMMAND_CONVERSATIONS) || - - /* index commands */ BongoHashtablePutNoReplace(CommandTable, "ISEARCH", (void *) STORE_COMMAND_ISEARCH) || @@ -826,7 +820,7 @@ ParseHeaderList(StoreClient *client, return ccode; } - +/* FIXME: Unused, deprecated? static CCode ParseConversationSource(StoreClient *client, char *token, @@ -835,7 +829,7 @@ ParseConversationSource(StoreClient *client, GetConversationSourceMask(token, outflags); return TOKEN_OK; } - +*/ static CCode ParseStoreName(StoreClient *client, @@ -2047,7 +2041,7 @@ ShowDocumentBody(StoreClient *client, DStoreDocInfo *info, if (STORE_IS_FOLDER(info->type)) { return ConnWriteStr(client->conn, MSG3015BADDOCTYPE); } else { - FindPathToDocFile(client, info->collection, path, sizeof(path)); + FindPathToDocument(client, info->collection, info->guid, path, sizeof(path)); fh = fopen(path, "rb"); if (!fh) { return ConnWriteStr(client->conn, MSG4224CANTREAD); @@ -2055,16 +2049,16 @@ ShowDocumentBody(StoreClient *client, DStoreDocInfo *info, if (requestStart < 0) { start = 0; - length = info->bodylen; + length = info->length; } else { - if (requestStart < info->bodylen) { + if (requestStart < info->length) { start = requestStart; - length = info->bodylen - start; + length = info->length - start; if ((requestLength > -1) && ((unsigned long)requestLength < length)) { length = requestLength; } } else { - start = info->bodylen; + start = info->length; length = 0; } } @@ -2074,7 +2068,8 @@ ShowDocumentBody(StoreClient *client, DStoreDocInfo *info, if (-1 == ccode) { goto finish; } - if (0 != XplFSeek64(fh, info->start + info->headerlen + start, SEEK_SET)) { + + if (0 != XplFSeek64(fh, start, SEEK_SET)) { ccode = ConnWriteStr(client->conn, MSG4224CANTREAD); goto finish; } @@ -2125,7 +2120,7 @@ ShowInternalProperty(StoreClient *client, len = snprintf(buf, 64, "%lu", (unsigned long) info->flags); return ConnWriteF(client->conn, "2001 nmap.flags %d\r\n%s\r\n", len, buf); case STORE_PROP_LENGTH: - len = snprintf(buf, 64, "%lld", info->bodylen); + len = snprintf(buf, 64, "%lld", info->length); return ConnWriteF(client->conn, "2001 nmap.length %d\r\n%s\r\n", len, buf); case STORE_PROP_TYPE: len = snprintf(buf, 64, "%d", info->type); @@ -2415,7 +2410,7 @@ ShowDocumentInfo(StoreClient *client, DStoreDocInfo *info, "2001 " GUID_FMT " %d %d %08x %d %lld %s\r\n", info->guid, info->type, info->flags, info->imapuid ? info->imapuid : (uint32_t) info->guid, - info->timeCreatedUTC, info->bodylen, + info->timeCreatedUTC, info->length, buffer); for (i = 0; i < propcount && ccode >= 0; i++) { @@ -2493,17 +2488,10 @@ ShowGuidsDocumentsWithMessage(StoreClient *client, uint64_t *guids, return ccode; } - static CCode StoreListCollections(StoreClient *client, DStoreDocInfo *coll) { - /* FIXME: instead of using the db, it might be better just to look - at the dat files to get the guids? */ - - uint64_t *glist; - int glist_size = 32; - int n = 0; CCode ccode = 0; DStoreStmt *stmt = NULL; @@ -2511,62 +2499,33 @@ StoreListCollections(StoreClient *client, DStoreDocInfo *coll) if (ccode) { return ccode; } - - glist = MemMalloc(glist_size * sizeof(uint64_t)); - if (!glist) { - return ConnWriteStr(client->conn, MSG5001NOMEMORY); + stmt = DStoreListCollections(client->handle, coll->filename, -1, -1); + if (!stmt) { + ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); + goto abort; } - glist[n++] = coll->guid; - - while (n) { - uint64_t guid; + + while (-1 != ccode) { DStoreDocInfo info; int dcode; - guid = glist[--n]; - - stmt = DStoreListColl(client->handle, guid, -1, -1); - if (!stmt) { - ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); - goto abort; - } - - while (-1 != ccode) { - dcode = DStoreInfoStmtStep(client->handle, stmt, &info); - if (1 == dcode && STORE_IS_FOLDER(info.type)) { + dcode = DStoreInfoStmtStep(client->handle, stmt, &info); + if (1 == dcode) { + if (coll->guid != info.guid) ccode = ConnWriteF(client->conn, "2001 " GUID_FMT " %d %d %s\r\n", info.guid, info.type, info.flags, info.filename); - glist[n++] = info.guid; - if (n >= glist_size) { - /* grow glist */ - uint64_t *tmp; - glist_size *= 2; - tmp = MemRealloc(glist, glist_size * sizeof(uint64_t)); - if (!tmp) { - ccode = ConnWriteStr(client->conn, MSG5001NOMEMORY); - goto abort; - } - glist = tmp; - } - - } else if (0 == dcode) { - break; - } else if (-1 == dcode) { - ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); - } + } else if (0 == dcode) { + break; + } else if (-1 == dcode) { + ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); } - - DStoreStmtEnd(client->handle, stmt); } - - MemFree(glist); - + + DStoreStmtEnd(client->handle, stmt); + return ConnWriteStr(client->conn, MSG1000OK); abort: - if (glist) { - MemFree(glist); - } if (stmt) { DStoreStmtEnd(client->handle, stmt); } @@ -2574,7 +2533,6 @@ abort: return ccode; } - CCode StoreCommandALARMS(StoreClient *client, uint64_t start, uint64_t end) { @@ -2869,7 +2827,8 @@ StoreCommandCOPY(StoreClient *client, uint64_t guid, DStoreDocInfo *collection) NLockStruct *lock = NULL; FILE *src = NULL; FILE *dest = NULL; - char path[XPL_MAX_PATH + 1]; + char srcpath[XPL_MAX_PATH + 1]; + char dstpath[XPL_MAX_PATH + 1]; struct stat sb; size_t start; size_t end; @@ -2898,59 +2857,51 @@ StoreCommandCOPY(StoreClient *client, uint64_t guid, DStoreDocInfo *collection) return ccode; } - FindPathToDocFile(client, info.collection, path, sizeof(path)); - src = fopen(path, "r"); + FindPathToDocument(client, info.collection, info.guid, srcpath, sizeof(srcpath)); + src = fopen(srcpath, "r"); if (!src) { ccode = ConnWriteStr(client->conn, MSG4224CANTREADMBOX); goto finish; } + fclose(src); - FindPathToDocFile(client, collection->guid, path, sizeof(path)); - if (stat(path, &sb)) { + MaildirTempDocument(client, collection->guid, dstpath, sizeof(dstpath)); + + if (link(srcpath, dstpath) != 0) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto finish; } - dest = fopen(path, "a"); - if (!dest) { - ccode = ConnWriteStr(client->conn, ENOSPC == errno ? MSG5220QUOTAERR - : MSG4228CANTWRITEMBOX); - goto finish; - } + // TODO: how to detect MSG5220QUOTAERR ? + + start = 0; + end = info.length; - start = info.start + info.headerlen; - end = info.start + info.headerlen + info.bodylen; - - info.start = sb.st_size; + // FIXME: need to correct all this meta-data info.guid = 0; info.imapuid = 0; info.collection = collection->guid; snprintf(info.filename, sizeof(info.filename), "%s/", collection->filename); - info.headerlen = WriteDocumentHeaders(client, dest, NULL, info.timeCreatedUTC); - if (info.headerlen < 0) { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - - if (BongoFileAppendBytes(src, dest, start, end) || - fflush(dest)) - { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - - /* info.timeCreatedUTC = time(NULL); */ - if (DStoreSetDocInfo(client->handle, &info)) { ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); goto finish; } - errmsg = StoreProcessDocument(client, &info, collection, path, NULL, 0); + errmsg = StoreProcessDocument(client, &info, collection, dstpath, NULL, 0); if (errmsg) { ccode = ConnWriteStr(client->conn, errmsg); goto finish; } + + // swap dest to src, and find new dest - move temp file into correct position + srcpath[0] = '\0'; + strncpy(srcpath, dstpath, sizeof(srcpath)); + FindPathToDocument(client, collection->guid, info.guid, dstpath, sizeof(dstpath)); + if (link(srcpath, dstpath) != 0) { + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto finish; + } + unlink(srcpath); if (0 != DStoreCommitTransaction(client->handle)) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); @@ -2965,12 +2916,6 @@ StoreCommandCOPY(StoreClient *client, uint64_t guid, DStoreDocInfo *collection) info.guid, info.version); finish: - if (src) { - fclose(src); - } - if (dest) { - fclose(dest); - } if (lock) { StoreReleaseExclusiveLock(client, lock); StoreReleaseSharedLock(client, lock); @@ -3017,6 +2962,7 @@ StoreCommandDELETE(StoreClient *client, uint64_t guid) NLockStruct *lock = NULL; BOOL updateConversation; IndexHandle *index = NULL; + char path[XPL_MAX_PATH]; switch (DStoreGetDocInfoGuid(client->handle, guid, &info)) { case 1: @@ -3084,17 +3030,18 @@ StoreCommandDELETE(StoreClient *client, uint64_t guid) ccode = ConnWriteStr(client->conn, MSG5007INDEXLIBERR); goto finish; } + + FindPathToDocument(client, info.collection, info.guid, path, sizeof(path)); + if (unlink(path) != 0) { + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto finish; + } if (DStoreCommitTransaction(client->handle)) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto finish; } - if (0 == rand() % 20) { - /* compact collections to preserve disk space */ - client->flags |= STORE_CLIENT_FLAG_NEEDS_COMPACTING; - } - IndexRemoveDocument(index, guid); ++client->stats.deletions; @@ -3102,7 +3049,7 @@ StoreCommandDELETE(StoreClient *client, uint64_t guid) info.guid, info.imapuid, 0); - ccode = ConnWriteStr(client->conn, MSG1000OK);; + ccode = ConnWriteStr(client->conn, MSG1000OK); finish: if (index) { @@ -3134,12 +3081,13 @@ StoreCommandDELIVER(StoreClient *client, char *sender, char *authSender, if (bytes <= 0) { return ConnWriteStr(client->conn, MSG3017INTARGRANGE); } - msgfile = XplOpenTemp(MsgGetWorkDir(NULL), "w+b", tmpFile); + msgfile = XplOpenTemp(MsgGetDir(MSGAPI_DIR_WORK, NULL, 0), "w+b", tmpFile); if (!msgfile) { return ConnWriteStr(client->conn, MSG5202TMPWRITEERR); } ccode = ConnReadToFile(client->conn, msgfile, bytes); if (-1 == ccode) { + unlink(tmpFile); fclose (msgfile); return ConnWriteStr(client->conn, MSG5202TMPWRITEERR); } @@ -3436,7 +3384,7 @@ StoreCommandFLAG(StoreClient *client, uint64_t guid, uint32_t change, int mode) ccode = ConnWriteStr(client->conn, MSG4120INDEXLOCKED); goto finish; } - if (IndexDocument(index, client, &info) != 0) { + if (IndexDocument(index, client, &info, NULL) != 0) { ccode = ConnWriteStr(client->conn, MSG5007INDEXLIBERR); goto finish; } @@ -3819,7 +3767,7 @@ StoreCommandMFLAG(StoreClient *client, uint32_t change, int mode) } } - if (IndexDocument(index, client, &info) != 0) { + if (IndexDocument(index, client, &info, NULL) != 0) { ccode = ConnWriteStr(client->conn, MSG5007INDEXLIBERR); goto finish; } @@ -3946,6 +3894,8 @@ StoreCommandMOVE(StoreClient *client, uint64_t guid, uint32_t oldimapuid; NLockStruct *srclock = NULL; NLockStruct *dstlock = NULL; + char src_path[XPL_MAX_PATH]; + char dst_path[XPL_MAX_PATH]; switch (DStoreGetDocInfoGuid(client->handle, guid, &info)) { case -1: @@ -4014,64 +3964,25 @@ StoreCommandMOVE(StoreClient *client, uint64_t guid, } if (newcoll->guid != info.collection) { - char path[XPL_MAX_PATH + 1]; struct stat sb; size_t total; size_t count; char buffer[CONN_BUFSIZE]; - FindPathToDocFile(client, info.collection, path, sizeof(path)); - if (!(oldfile = fopen(path, "r")) || - XplFSeek64(oldfile, info.start + info.headerlen, SEEK_SET)) - { - ccode = ConnWriteStr(client->conn, MSG4224CANTREAD); - goto abort; - } + FindPathToDocument(client, info.collection, info.guid, src_path, sizeof(src_path)); + MaildirTempDocument(client, newcoll->guid, dst_path, sizeof(dst_path)); + // FindPathToTempDocument(client, newcoll->guid, dst_path, sizeof(dst_path)); - FindPathToDocFile(client, newcoll->guid, path, sizeof(path)); - if (stat(path, &sb) || - !(newfile = fopen(path, "a"))) - { - ccode = ConnWriteStr(client->conn, MSG4224CANTWRITE); - goto abort; - } - - info.start = sb.st_size; - info.headerlen = WriteDocumentHeaders(client, newfile, NULL, - info.timeCreatedUTC); - if (info.headerlen < 0) { + if (link(src_path, dst_path) != 0) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto abort; } - for (total = info.bodylen; - total; - total -= count) - { - count = sizeof(buffer) < total ? sizeof(buffer) : total; - - count = fread(buffer, sizeof(char), count, oldfile); - if (!count || - ferror(oldfile) || - count != fwrite(buffer, sizeof(char), count, newfile)) - { - ccode = ConnWriteStr(client->conn, MSG4224CANTWRITE); - goto abort; - } - } - - (void) fclose(oldfile); - oldfile = NULL; - if (fclose(newfile)) { - ccode = ConnWriteStr(client->conn, MSG4224CANTWRITE); + if (unlink(src_path) != 0) { + // FIXME: try to remove the new link we just created? + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto abort; } - newfile = NULL; - - if (0 == rand() % 25) { - /* compact collections to preserve disk space */ - client->flags |= STORE_CLIENT_FLAG_NEEDS_COMPACTING; - } } info.collection = newcoll->guid; @@ -4094,7 +4005,21 @@ StoreCommandMOVE(StoreClient *client, uint64_t guid, } } } - + + src_path[0] = '\0'; + strncpy(src_path, dst_path, sizeof(src_path)); + FindPathToDocument(client, info.collection, info.guid, dst_path, sizeof(dst_path)); + + if (link(src_path, dst_path) != 0) { + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto abort; + } + if (unlink(src_path) != 0) { + // FIXME: try to remove the new link we just created? + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto abort; + } + if (DStoreCommitTransaction(client->handle)) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto abort; @@ -4117,15 +4042,7 @@ abort: DStoreAbortTransaction(client->handle); -finish: - - if (oldfile) { - fclose(oldfile); - } - if (newfile) { - fclose(newfile); - } - +finish: if (srclock) { StoreReleaseExclusiveLock(client, srclock); StoreReleaseSharedLock(client, srclock); @@ -4354,6 +4271,8 @@ StoreCommandREAD(StoreClient *client, if (STORE_IS_FOLDER(info.type)) { ccode = StoreShowFolder(client, info.collection, 0); + } else if (STORE_IS_DBONLY(info.type)) { + ccode = ConnWriteStr(client->conn, MSG3016DOCTYPEUNREADABLE); } else { ccode = ShowDocumentBody(client, &info, requestStart, requestLength); } @@ -4399,7 +4318,7 @@ StoreCommandREINDEX(StoreClient *client, uint64_t guid) continue; } - IndexDocument(index, client, &info); + IndexDocument(index, client, &info, NULL); } ccode = ConnWriteStr(client->conn, MSG1000OK); @@ -4510,7 +4429,7 @@ StoreCommandRENAME(StoreClient *client, DStoreDocInfo *collection, case -4: /* io error */ default: ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - break; + goto finish; } /* we want to keep most of the docinfo from the old collection, but need to @@ -4658,17 +4577,15 @@ RemoveCollections(StoreClient *client, uint64_t guid) } trans = 0; - /* third pass: remove .dat files. - if unlink() ever fails, we waste some - disk space, but the store will still be consistent. - */ - + /* third pass: remove filesystem data */ for (i = 0; i < subcolls.len; i++) { char path[XPL_MAX_PATH+1]; guid = BongoArrayIndex(&subcolls, uint64_t, i); - - FindPathToDocFile(client, guid, path, sizeof(path)); - unlink(path); + if (MaildirRemove(client->store, guid) != 0) { + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto finish; + } } /* fourth pass: remove docs from the index */ @@ -4750,40 +4667,41 @@ StoreCommandRESET(StoreClient *client) CCode StoreCommandSTORE(StoreClient *client, char *user) { - MDBValueStruct *vs; - struct sockaddr_in serv; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - if (!user) { UnselectStore(client); return ConnWriteStr(client->conn, MSG1000OK); } if (StoreAgent.installMode || !strncmp(user, "_system", 7)) { - if (SelectStore(client, user)) { - return ConnWriteStr(client->conn, MSG4224BADSTORE); - } else { - return ConnWriteStr(client->conn, MSG1000OK); + int ret = 0; + ret = SelectStore(client, user); + switch (ret) { + case 0: + return ConnWriteStr(client->conn, MSG1000OK); + break; + case -2: + return ConnWriteStr(client->conn, MSG4225BADVERSION); + case -1: + default: + return ConnWriteStr(client->conn, MSG4224BADSTORE); + break; } } - vs = MDBCreateValueStruct(StoreAgent.handle.directory, NULL); - if (!vs) { - return ConnWriteStr(client->conn, MSG5001NOMEMORY); - } - - if (!MsgFindObject(user, dn, NULL, &serv, vs)) { + if (0 != MsgAuthFindUser(user)) { XplConsolePrintf("Couldn't find user object for %s\r\n", user); - MDBDestroyValueStruct(vs); /* the previous nmap returned some sort of user locked message? */ return ConnWriteStr(client->conn, MSG4100STORENOTFOUND); } - MDBDestroyValueStruct(vs); - if (serv.sin_addr.s_addr != MsgGetHostIPAddress()) { - /* non-local store */ + // FIXME: Below is a check that the user resides in this store. + // For Bongo 1.0, we're assuming a single store? +#if 0 + if (serv.sin_addr.s_addr != MsgGetHostIPAddress()) { + // non-local store return ConnWriteStr(client->conn, MSG4100STORENOTFOUND); } +#endif if (SelectStore(client, user)) { return ConnWriteStr(client->conn, MSG4224BADSTORE); @@ -4938,10 +4856,10 @@ StoreCommandWRITE(StoreClient *client, NLockStruct *cLock = NULL; int replace = 0; /* are we in replace mode? */ char path[XPL_MAX_PATH + 1]; + char tmppath[XPL_MAX_PATH + 1]; struct stat sb; FILE *fh = NULL; int commit = 0; - int written = 0; /* did we write to the file? */ if (StoreAgent.flags & STORE_DISK_SPACE_LOW) { return ConnWriteStr(client->conn, MSG5221SPACELOW); @@ -4974,17 +4892,18 @@ StoreCommandWRITE(StoreClient *client, break; default: if (!collection) { - /* REPLACE mode requires existing document */ + // REPLACE mode requires existing document ccode = ConnWriteStr(client->conn, MSG4220NOGUID); goto finish; } break; } info.guid = guid; - } else { - /* Rely on the database to enforce uniqueness in the filename */ + } + if (collection) { + // Rely on the database to enforce uniqueness in the filename snprintf(info.filename, sizeof(info.filename), "%s/%s", - collection->filename, filename ? filename : ""); + collection->filename, filename ? filename : ""); } if (!collection) { @@ -5014,13 +4933,11 @@ StoreCommandWRITE(StoreClient *client, goto finish; } - FindPathToDocFile(client, info.collection, path, sizeof(path)); - if (stat(path, &sb)) { - ccode = ConnWriteStr(client->conn, MSG4224NOMBOX); - goto finish; - } + // open a temporary file to write to + // FindPathToTempDocument(client, info.collection, tmppath, sizeof(tmppath)); + MaildirTempDocument(client, info.collection, tmppath, sizeof(tmppath)); - fh = fopen(path, "a+"); + fh = fopen(tmppath, "w"); if (!fh) { if (ENOSPC == errno) { ccode = ConnWriteStr(client->conn, MSG5220QUOTAERR); @@ -5030,55 +4947,21 @@ StoreCommandWRITE(StoreClient *client, goto finish; } - info.start += info.headerlen; - - info.headerlen = WriteDocumentHeaders(client, fh, NULL, - info.timeCreatedUTC); - - if (info.headerlen < 0) { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - - if (-1 != startoffset) { - if (BongoFileAppendBytes(fh, fh, info.start, info.start + startoffset)) { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - } - if (-1 == (ccode = ConnWrite(client->conn, "2002 Send document.\r\n", 21)) || -1 == (ccode = ConnFlush(client->conn))) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); } if (length >= 0) { - ccode = written = ConnReadToFile(client->conn, fh, length); + ccode = ConnReadToFile(client->conn, fh, length); } else { - ccode = written = length = ConnReadToFileUntilEOS(client->conn, fh); + ccode = length = ConnReadToFileUntilEOS(client->conn, fh); } if (-1 == ccode) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto finish; } - if (-1 != startoffset) { - if (BongoFileAppendBytes(fh, fh, - info.start + endoffset, info.start + info.bodylen)) - { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - info.bodylen -= (endoffset - startoffset); - } else { - info.bodylen = 0; - } - - if (4 != fwrite("\r\n\r\n", sizeof(char), 4, fh)) { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - goto finish; - } - ccode = fclose(fh); fh = NULL; if (ccode) { @@ -5086,9 +4969,9 @@ StoreCommandWRITE(StoreClient *client, goto finish; } - info.bodylen += length; + // create new metadata and index new mail + info.length = length; info.timeCreatedUTC = timeCreatedUTC ? timeCreatedUTC : (uint64_t) time(NULL); - info.start = sb.st_size; info.version++; info.flags |= addflags; @@ -5107,6 +4990,15 @@ StoreCommandWRITE(StoreClient *client, ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); goto finish; } + + FindPathToDocument(client, info.collection, info.guid, path, sizeof(path)); + if (replace && (unlink(path) != 0)) { + // can't get rid of existing mail file. + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + goto finish; + } + link(tmppath, path); // FIXME : error checking + unlink(tmppath); // and again :) errmsg = StoreProcessDocument(client, &info, collection, path, NULL, linkGuid); if (errmsg) { @@ -5114,15 +5006,6 @@ StoreCommandWRITE(StoreClient *client, goto finish; } - if (replace && !collection->data.collection.needsCompaction) { - ++collection->data.collection.needsCompaction; - (void) DStoreSetDocInfo(client->handle, collection); - - if (0 == rand() % 25) { - client->flags |= STORE_CLIENT_FLAG_NEEDS_COMPACTING; - } - } - if (replace) { /* Clear an existing mime report */ DStoreClearMimeReport(client->handle, info.guid); @@ -5131,12 +5014,13 @@ StoreCommandWRITE(StoreClient *client, if (0 != DStoreCommitTransaction(client->handle)) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto finish; - } + } if (replace) { ++client->stats.updates; StoreWatcherEvent(client, cLock, STORE_WATCH_EVENT_MODIFIED, info.guid, info.imapuid, 0); + } else { ++client->stats.insertions; StoreWatcherEvent(client, cLock, STORE_WATCH_EVENT_NEW, @@ -5159,11 +5043,7 @@ finish: if (!commit) { DStoreAbortTransaction(client->handle); - if (written && 0 != XplTruncate(path, sb.st_size)) { - XplConsolePrintf("Couldn't truncate store file: %s.\r\n", - strerror(errno)); - } - + unlink(tmppath); } if (cLock) { @@ -5198,13 +5078,6 @@ WriteHelper(StoreClient *client, const char *errmsg; int i; - info->start = ftell(fh); - - info->headerlen = WriteDocumentHeaders(client, fh, NULL, info->timeCreatedUTC); - if (info->headerlen < 0) { - return ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - } - if (-1 == (ccode = ConnWrite(client->conn, "2002 Send document.\r\n", 21)) || -1 == (ccode = ConnFlush(client->conn))) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); @@ -5219,7 +5092,7 @@ WriteHelper(StoreClient *client, return ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); } - info->bodylen = length; + info->length = length; if (4 != fwrite("\r\n\r\n", sizeof(char), 4, fh)) { return ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); @@ -5298,7 +5171,8 @@ StoreCommandMWRITE(StoreClient *client, CCode ccode; NLockStruct *cLock = NULL; FILE *fh = NULL; - char path[XPL_MAX_PATH + 1]; + char tmppath[XPL_MAX_PATH]; + char path[XPL_MAX_PATH]; struct stat sb; DStoreDocInfo info; IndexHandle *index = NULL; @@ -5320,29 +5194,8 @@ StoreCommandMWRITE(StoreClient *client, return ConnWriteStr(client->conn, MSG4120INDEXLOCKED); } - ccode = StoreGetCollectionLock(client, &cLock, collection->guid); - if (ccode) { - goto finish; - } - - FindPathToDocFile(client, collection->guid, path, sizeof(path)); - if (stat(path, &sb)) { - ccode = ConnWriteStr(client->conn, MSG4224NOMBOX); - goto finish; - } - - fh = fopen(path, "a"); - if (!fh) { - if (ENOSPC == errno) { - ccode = ConnWriteStr(client->conn, MSG5220QUOTAERR); - } else { - ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); - } - goto finish; - } - while (ccode >= 0) { - char *tokens[8]; + char *tokens[8]; int length; char *filename = NULL; uint64_t guid = 0; @@ -5427,6 +5280,24 @@ StoreCommandMWRITE(StoreClient *client, info.timeCreatedUTC = timeCreated ? timeCreated : (uint64_t) time(NULL); + ccode = StoreGetCollectionLock(client, &cLock, collection->guid); + if (ccode) { + goto finish; + } + + // FindPathToTempDocument(client, collection->guid, tmppath, sizeof(tmppath)); + MaildirTempDocument(client, collection->guid, tmppath, sizeof(tmppath)); + + fh = fopen(path, "w"); + if (!fh) { + if (ENOSPC == errno) { + ccode = ConnWriteStr(client->conn, MSG5220QUOTAERR); + } else { + ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); + } + goto finish; + } + ccode = WriteHelper(client, index, collection, &info, fh, path, @@ -5434,16 +5305,22 @@ StoreCommandMWRITE(StoreClient *client, flags, linkguid, props, propcount); + fclose(fh); + fh = NULL; + if (ccode) { goto finish; } - BongoArrayAppendValue(&guidlist, info.guid); + FindPathToDocument(client, collection->guid, info.guid, path, sizeof(path)); + if (link(tmppath, path) != 0) { + goto finish; + } + unlink(tmppath); // FIXME: some sort of check? + BongoArrayAppendValue(&guidlist, info.guid); } - ccode = fclose(fh); - fh = NULL; if (ccode) { ccode = ConnWriteStr(client->conn, MSG4228CANTWRITEMBOX); goto finish; diff --git a/src/agents/store/config.c b/src/agents/store/config.c index fcbd2dc..e638440 100644 --- a/src/agents/store/config.c +++ b/src/agents/store/config.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -37,12 +36,6 @@ BOOL StoreAgentReadConfiguration(BOOL *recover) { - unsigned long used; - - BOOL result = TRUE; - MDBValueStruct *vs; - MDBValueStruct *stores; - tzset(); StoreAgent.startupTime = time(NULL); @@ -55,134 +48,36 @@ StoreAgentReadConfiguration(BOOL *recover) // this is apparently a hack. Perhaps this should be configurable? StoreAgent.server.maxClients = 1024; - if (StoreAgent.installMode) { - // we want to setup a minimal config, just so the store can bootstrap - strcpy(StoreAgent.store.rootDir, XPL_DEFAULT_MAIL_DIR); - strcpy(StoreAgent.store.systemDir, XPL_DEFAULT_STORE_SYSTEM_DIR); - strcpy(StoreAgent.store.spoolDir, XPL_DEFAULT_SPOOL_DIR); - MsgMakePath(StoreAgent.store.rootDir); - MsgMakePath(StoreAgent.store.systemDir); - MsgMakePath(StoreAgent.store.spoolDir); + // paths etc. now fixed in code - if we want to configure these, we need a new system :) + strcpy(StoreAgent.store.rootDir, XPL_DEFAULT_MAIL_DIR); + strcpy(StoreAgent.store.systemDir, XPL_DEFAULT_STORE_SYSTEM_DIR); + strcpy(StoreAgent.store.spoolDir, XPL_DEFAULT_SPOOL_DIR); + MsgMakePath(StoreAgent.store.rootDir); + MsgMakePath(StoreAgent.store.systemDir); + MsgMakePath(StoreAgent.store.spoolDir); - // which hosts do we trust? - StoreAgent.trustedHosts.count = 2; - StoreAgent.trustedHosts.hosts = MemRealloc(StoreAgent.trustedHosts.hosts, sizeof(unsigned long) * 2); - if (!StoreAgent.trustedHosts.hosts) { - StoreAgent.trustedHosts.count = 0; - } else { - StoreAgent.trustedHosts.hosts[0] = inet_addr("127.0.0.1"); - StoreAgent.trustedHosts.hosts[1] = MsgGetHostIPAddress(); // do we need this address too? - } - - return (TRUE); - } - // otherwise, we continue on to load the full config - - vs = MDBCreateValueStruct(StoreAgent.handle.directory, NULL); - if (vs && MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, vs)) { - gethostname(StoreAgent.server.host, sizeof(StoreAgent.server.host)); - - HashCredential(MsgGetServerDN(NULL), vs->Value[0], StoreAgent.server.hash); - - MDBFreeValues(vs); - } else { - return(FALSE); - } - - if (recover) { - if (MDBRead(StoreAgent.server.dn, MSGSRV_A_SERVER_STATUS, vs) > 0) { - if (XplStrCaseCmp(vs->Value[0], "Shutdown") != 0) { - *recover = TRUE; - } - } - - MDBFreeValues(vs); - } - - MDBSetValueStructContext(StoreAgent.server.dn, vs); - - /* trusted hosts */ - StoreAgent.trustedHosts.count = - MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_STORE_TRUSTED_HOSTS, vs); - - StoreAgent.trustedHosts.hosts = MemRealloc(StoreAgent.trustedHosts.hosts, - StoreAgent.trustedHosts.count * sizeof(unsigned long)); + // which hosts do we trust? SECURITY: This bypasses auth! + StoreAgent.trustedHosts.count = 0; +#if 0 + StoreAgent.trustedHosts.count = 2; + StoreAgent.trustedHosts.hosts = + MemRealloc(StoreAgent.trustedHosts.hosts, sizeof(unsigned long) * 2); if (!StoreAgent.trustedHosts.hosts) { StoreAgent.trustedHosts.count = 0; - } - if (StoreAgent.trustedHosts.count) { - int count = 0; - -#if defined(NETWARE) || defined(LIBC) - StoreAgent.trustedHosts.hosts[count++] = inet_addr("127.0.0.1"); - StoreAgent.trustedHosts.hosts[count++] = MsgGetHostIPAddress(); -#endif - for (used = 0; used < vs->Used; used++) { - StoreAgent.trustedHosts.hosts[count++] = inet_addr(vs->Value[used]); - } - } - MDBFreeValues(vs); - /* end trusted hosts */ - - if (MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_MESSAGE_STORE, vs) > 0) { - LoggerEvent(StoreAgent.handle.logging, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_MESSAGE_STORE", vs->Value[0], 0, 0, NULL, 0); - - MsgCleanPath(vs->Value[0]); - - strcpy(StoreAgent.store.rootDir, vs->Value[0]); - MsgMakePath(StoreAgent.store.rootDir); - - MDBFreeValues(vs); } else { - result = FALSE; - strcpy(StoreAgent.store.rootDir, XPL_DEFAULT_MAIL_DIR); + StoreAgent.trustedHosts.hosts[0] = inet_addr("127.0.0.1"); + StoreAgent.trustedHosts.hosts[1] = MsgGetHostIPAddress(); // do we need this address too? + } +#endif + + gethostname(StoreAgent.server.host, sizeof(StoreAgent.server.host)); + if (!MsgGetServerCredential(StoreAgent.server.hash)) + // can't proceed without the server hash.. + return(FALSE); + + if (recover && MsgGetRecoveryFlag("store")) { + *recover = TRUE; } - MsgMakePath(StoreAgent.store.rootDir); - - /* Create Store Paths if they don't exist */ - if (MDBReadDN(StoreAgent.server.dn, MSGSRV_A_CONTEXT, vs) > 0) { - stores = MDBCreateValueStruct(StoreAgent.handle.directory, NULL); - if (stores) { - for (used = 0; used < vs->Used; used++) { - if (MDBRead(vs->Value[used], MSGSRV_A_MESSAGE_STORE, stores) > 0) { - MsgCleanPath(stores->Value[0]); - MsgMakePath(stores->Value[0]); - MDBFreeValues(stores); - } - } - - MDBDestroyValueStruct(stores); - } else { - result = FALSE; - } - - MDBFreeValues(vs); - } - - strcpy(StoreAgent.store.systemDir, XPL_DEFAULT_STORE_SYSTEM_DIR); - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_STORE_SYSTEM_DIRECTORY, vs) > 0) { - LoggerEvent(StoreAgent.handle.logging, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_STORE_SYSTEM_DIRECTORY", vs->Value[0], 0, 0, NULL, 0); - - MsgCleanPath(vs->Value[0]); - strcpy(StoreAgent.store.systemDir, vs->Value[0]); - MsgMakePath(StoreAgent.store.systemDir); - - MDBFreeValues(vs); - } - - strcpy(StoreAgent.store.spoolDir, XPL_DEFAULT_SPOOL_DIR); - if (MDBRead(MSGSRV_AGENT_QUEUE, MSGSRV_A_SPOOL_DIRECTORY, vs) > 0) { - LoggerEvent(StoreAgent.handle.logging, LOGGER_SUBSYSTEM_CONFIGURATION, LOGGER_EVENT_CONFIGURATION_STRING, LOG_INFO, 0, "MSGSRV_A_SPOOL_DIRECTORY", vs->Value[0], 0, 0, NULL, 0); - - MsgCleanPath(vs->Value[0]); - strcpy(StoreAgent.store.spoolDir, vs->Value[0]); - MsgMakePath(StoreAgent.store.spoolDir); - - MDBFreeValues(vs); - } - - MDBDestroyValueStruct(vs); - - return(result); + return(TRUE); } diff --git a/src/agents/store/cookie.c b/src/agents/store/cookie.c index 6e87499..9c59cc9 100644 --- a/src/agents/store/cookie.c +++ b/src/agents/store/cookie.c @@ -23,121 +23,17 @@ #include #include #include +#include #include "stored.h" #include "messages.h" -typedef struct { - char token[32]; - uint64_t expirationDate; -} Cookie; - - -static void -GetCookiesPath(StoreClient *client, const char *user, char *path, size_t len) -{ - const char *root; - int n; - - root = MsgFindUserStore(user, StoreAgent.store.rootDir); - n = snprintf(path, len, "%s/%s/cookies", root, user); -} - - -static int -AddCookie(StoreClient *client, Cookie *cookie) -{ - char path[XPL_MAX_PATH+1]; - FILE *f; - long len; - - GetCookiesPath(client, client->principal.name, path, sizeof(path)); - - f = fopen(path, "a"); - if (!f) { - return -1; - } - - len = ftell(f); - - if (sizeof(Cookie) != fwrite(cookie, 1, sizeof(Cookie), f) || - fclose(f)) - { - fclose(f); - truncate(path, len); - return -1; - } - - return 0; -} - - -/* returns: 1 if cookie found, 0 if not found, -1 on error */ - -static int -FindCookie(StoreClient *client, const char *user, const char *token) -{ - char path[XPL_MAX_PATH+1]; - FILE *f; - Cookie cookie; - int result = 0; - uint64_t now; - int expired = 0; - - now = BongoCalTimeAsUint64(BongoCalTimeNow(NULL)); - - GetCookiesPath(client, user, path, sizeof(path)); - - f = fopen(path, "r"); - if (!f) { - return 0; - } - - while (sizeof(Cookie) == fread(&cookie, 1, sizeof(Cookie), f)) { - if (cookie.expirationDate < now) { - ++expired; - continue; - } - if (!strncmp(cookie.token, token, sizeof(cookie.token))) { - result = 1; - break; - } - } - - if (ferror(f)) { - result = -1; - } - - if (expired > 8) { - /* FIXME: purge expired cookies from the file */ - } - - (void) fclose(f); - - return result; -} - - CCode StoreCommandCOOKIENEW(StoreClient *client, uint64_t timeout) { - Cookie cookie; + MsgAuthCookie cookie; NLockStruct *lock = NULL; CCode ccode = 0; - unsigned char credential[XPLHASH_MD5_LENGTH]; - xpl_hash_context context; - - cookie.expirationDate = timeout; - - XplHashNew(&context, XPLHASH_MD5); - - snprintf(cookie.token, sizeof(cookie.token), "%x%x", - (unsigned int) XplGetThreadID(), - (unsigned int) time(NULL)); - XplHashWrite(&context, cookie.token, strlen(cookie.token)); - XplRandomData(cookie.token, 8); - XplHashWrite(&context, cookie.token, strlen(cookie.token)); - XplHashFinal(&context, XPLHASH_LOWERCASE, cookie.token, XPLHASH_MD5_LENGTH); assert(STORE_PRINCIPAL_USER == client->principal.type); @@ -150,10 +46,10 @@ StoreCommandCOOKIENEW(StoreClient *client, uint64_t timeout) return ConnWriteStr(client->conn, MSG4120USERLOCKED); } - if (AddCookie(client, &cookie)) { - ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); + if (MsgAuthCreateCookie(client->principal.name, &cookie, timeout)) { + ccode = ConnWriteF(client->conn, "1000 %.32s\r\n", cookie.token); } else { - ccode = ConnWriteF(client->conn, "1000 %.32s\r\n", cookie.token); + ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); } PurgeNLockRelease(lock); @@ -167,10 +63,7 @@ CCode StoreCommandCOOKIEDELETE(StoreClient *client, const char *token) { CCode ccode = 0; - char path[XPL_MAX_PATH+1]; - FILE *f; NLockStruct *lock = NULL; - Cookie cookie; assert(STORE_PRINCIPAL_USER == client->principal.type); @@ -184,52 +77,20 @@ StoreCommandCOOKIEDELETE(StoreClient *client, const char *token) return ConnWriteStr(client->conn, MSG4120USERLOCKED); } - GetCookiesPath(client, client->principal.name, path, sizeof(path)); - - if (!token) { - if (unlink(path)) { - printf("Couldn't unlink cookie file %s\r\n", path); - ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); - } else { - ccode = ConnWriteStr(client->conn, MSG1000OK); - } - goto finish; - } - - f = fopen(path, "r+"); - if (!f) { + if (MsgAuthDeleteCookie(client->principal.name, token)) { + ccode = ConnWriteStr(client->conn, MSG1000OK); + } else { ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); - goto finish; } - while (sizeof(Cookie) == fread(&cookie, 1, sizeof(Cookie), f)) { - if (!strncmp(cookie.token, token, sizeof(cookie.token))) { - /* FIXME: should (atomically) re-generate the cookie file instead of - overwriting the delete cookie with zeroes */ - memset(&cookie, 0, sizeof(Cookie)); - if (fseek(f, -sizeof(Cookie), SEEK_CUR) || - sizeof(Cookie) != fwrite(&cookie, 1, sizeof(Cookie), f)) - { - ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); - goto finish; - } - } - } - - if (ferror(f)) { - goto finish; - } - - ccode = ConnWriteStr(client->conn, MSG1000OK); - -finish: PurgeNLockRelease(lock); ReadNLockRelease(lock); return ccode; } - +#if 0 +// this looks like multiple-store code CCode TunnelAuthCookie(StoreClient *client, struct sockaddr_in *serv, char *user, char *token, int nouser) @@ -266,40 +127,36 @@ TunnelAuthCookie(StoreClient *client, return ccode; } - +#endif CCode StoreCommandAUTHCOOKIE(StoreClient *client, char *user, char *token, int nouser) { CCode ccode; NLockStruct *lock = NULL; - MDBValueStruct *vs; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - struct sockaddr_in serv; +// struct sockaddr_in serv; if (StoreAgent.installMode) { // don't allow cookie logins in installation mode. FIXME: better error message? return ConnWriteStr(client->conn, MSG3242BADAUTH); } - vs = MDBCreateValueStruct(StoreAgent.handle.directory, NULL); - if (!vs) { - return ConnWriteStr(client->conn, MSG5001NOMEMORY); - } - - if (!MsgFindObject(user, dn, NULL, &serv, vs)) { + if (0 != MsgAuthFindUser(user)) { XplConsolePrintf("Couldn't find user object for %s\r\n", user); ccode = ConnWriteStr(client->conn, MSG3242BADAUTH); XplDelay(2000); goto finish; } + // FIXME: This checks for a non-local store. For Bongo 1.0, we assume a single store. +#if 0 if (serv.sin_addr.s_addr != MsgGetHostIPAddress()) { /* non-local store, need to verify against user's server */ ccode = TunnelAuthCookie(client, &serv, user, token, nouser); goto finish; } +#endif if (NLOCK_ACQUIRED != ReadNLockAcquire(&lock, NULL, user, STORE_ROOT_GUID, 2000)) { @@ -310,7 +167,7 @@ StoreCommandAUTHCOOKIE(StoreClient *client, char *user, char *token, int nouser) return ConnWriteStr(client->conn, MSG4120USERLOCKED); } - switch (FindCookie(client, user, token)) { + switch (MsgAuthFindCookie(user, token)) { case 0: XplDelay(2000); ccode = ConnWriteStr(client->conn, MSG3242BADAUTH); @@ -328,7 +185,6 @@ finish: PurgeNLockRelease(lock); ReadNLockRelease(lock); } - MDBDestroyValueStruct(vs); return ccode; } diff --git a/src/agents/store/db.c b/src/agents/store/db.c index 7ef3f54..247b01c 100644 --- a/src/agents/store/db.c +++ b/src/agents/store/db.c @@ -36,6 +36,7 @@ docs table: filename - for collection: path w/o trailing slash for document: full path + '/' + document name (see stored.h) collection - the guid of the containing collection + type - the store type of the collection/document info - contains DStoreDocInfo struct @@ -104,6 +105,8 @@ struct _DStoreHandle { DStoreStmt getGuidColl; DStoreStmt listColl; DStoreStmt listCollRange; + DStoreStmt listCollections; + DStoreStmt listCollectionsRange; DStoreStmt listUnindexed; DStoreStmt listUnindexedColl; DStoreStmt setIndexed; @@ -157,10 +160,6 @@ struct _DStoreHandle { DStoreStmt setMime; DStoreStmt clearMime; - DStoreStmt listJournal; - DStoreStmt addJournalEntry; - DStoreStmt delJournalEntry; - DStoreStmt getVersion; DStoreStmt abrt; /* rollback transaction */ @@ -229,7 +228,7 @@ DStoreCreateDB(DStoreHandle *handle) " conversation INTEGER, " " filename TEXT DEFAULT NULL, " " collection INTEGER DEFAULT 0, " - + " type INTEGER DEFAULT 1, " " info BLOB NOT NULL," " subject TEXT DEFAULT NULL," " senders TEXT DEFAULT NULL," @@ -243,6 +242,7 @@ DStoreCreateDB(DStoreHandle *handle) ");" "CREATE UNIQUE INDEX filename_idx ON docs (filename);" "CREATE INDEX docs_idx ON docs (guid);" + "CREATE INDEX docs_type ON docs (type);" "CREATE TABLE props (guid INTEGER, " " name TEXT NOT NULL, " @@ -403,7 +403,7 @@ DStoreCreateDB(DStoreHandle *handle) return 0; fail: - printf("DStoreCreateDB error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "DStoreCreateDB error: %s", sqlite3_errmsg(handle->db)); DStoreAbortTransaction(handle); DStoreClose(handle); @@ -414,7 +414,12 @@ fail: /* ensure the database schema has been updated to the proper version returns: 0 on success, -1 on error */ - +/* FIXME: We were doing this check every time we opened the database. + * That's not great, though. Admins should be able to control if/when + * user data is upgraded, since it's a risky operation. + * As a control, we check the version of the DB when we first STORE, + * calling DStoreCheckDBSchema() + */ static int UpgradeDB(DStoreHandle *handle) { @@ -426,18 +431,18 @@ UpgradeDB(DStoreHandle *handle) #define CURRENT_VERSION 2 if (DStoreBeginTransaction(handle)) { - printf("UpgradeDB error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); return -1; } stmt = SqlPrepare(handle, "PRAGMA user_version;", &handle->stmts.getVersion); if (!stmt) { - printf("UpgradeDB error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); goto fail; } if (1 != DStoreStmtStep(handle, stmt)) { - printf("UpgradeDB error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); DStoreStmtEnd(handle, stmt); goto fail; } @@ -457,7 +462,7 @@ UpgradeDB(DStoreHandle *handle) , NULL, NULL, NULL); if (SQLITE_OK != dcode) { - printf("error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "Couldn't add mime_cache table: %s\n", sqlite3_errmsg(handle->db)); goto fail; } case 1: @@ -465,13 +470,13 @@ UpgradeDB(DStoreHandle *handle) "ALTER TABLE docs ADD COLUMN stamp TEXT DEFAULT NULL;", NULL, NULL, NULL); if (SQLITE_OK != dcode) { - printf("error: %s\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "Couldn't update docs table: %s\n", sqlite3_errmsg(handle->db)); goto fail; } case 2: break; default: - printf("Illegal database version %d", CURRENT_VERSION); + Log(LOG_ERROR, "Illegal database version %d found", CURRENT_VERSION); goto fail; } @@ -484,18 +489,52 @@ UpgradeDB(DStoreHandle *handle) DStoreReset(handle); - printf("Upgraded store to version %d.\n", CURRENT_VERSION); + Log(LOG_INFO, "Upgraded store to version %d", CURRENT_VERSION); return 0; fail: DStoreAbortTransaction(handle); if (-1 != version) { - printf("Unable to upgrade store from version %d to version %d.\n", + Log(LOG_ERROR, "Unable to upgrade store from version %d to version %d.", version, CURRENT_VERSION); } return -1; } +int +DStoreCheckDBSchema(DStoreHandle *handle) +{ + DStoreStmt *stmt; + int version = 0; + int retcode = -1; + + if (DStoreBeginTransaction(handle)) { + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); + return -1; + } + + stmt = SqlPrepare(handle, "PRAGMA user_version;", &handle->stmts.getVersion); + if (!stmt) { + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); + goto fail; + } + + if (1 != DStoreStmtStep(handle, stmt)) { + Log(LOG_ERROR, "UpgradeDB error: %s", sqlite3_errmsg(handle->db)); + DStoreStmtEnd(handle, stmt); + goto fail; + } + version = sqlite3_column_int(stmt->stmt, 0); + DStoreStmtEnd(handle, stmt); + + if (CURRENT_VERSION == version) { + retcode = 0; + } + +fail: + DStoreAbortTransaction(handle); + return retcode; +} static void test_info_flags(sqlite3_context *ctx, int argc, sqlite3_value **argv); @@ -515,12 +554,11 @@ DStoreOpen(char *basepath, BongoMemStack *memstack, int locktimeoutms) create = access(path, 0); - if (!(handle = MemMalloc(sizeof(struct _DStoreHandle))) || - memset(handle, 0, sizeof(struct _DStoreHandle)), 0 || - SQLITE_OK != sqlite3_open(path, &handle->db)) + if (!(handle = MemMalloc(sizeof(struct _DStoreHandle))) || + (memset(handle, 0, sizeof(struct _DStoreHandle)), 0) || + (SQLITE_OK != sqlite3_open(path, &handle->db))) { - XplConsolePrintf("NMAP: Failed to open dstore \"%s\".\r\n", - path); + Log(LOG_ERROR, "Failed to open dstore \"%s\"", path); goto fail; } @@ -529,11 +567,7 @@ DStoreOpen(char *basepath, BongoMemStack *memstack, int locktimeoutms) handle->lockTimeoutMs = locktimeoutms; if (create && DStoreCreateDB(handle)) { - printf("Couldn't open db"); - goto fail; - } - - if (UpgradeDB(handle)) { + Log(LOG_ERROR, "Couldn't open dstore db"); goto fail; } @@ -569,7 +603,7 @@ DStoreClose(DStoreHandle *handle) { DStoreReset(handle); if (SQLITE_BUSY == sqlite3_close(handle->db)) { - XplConsolePrintf ("Store: couldn't close dstore database!\r\n"); + Log (LOG_ERROR, "Couldn't close dstore database"); } MemFree(handle); @@ -615,12 +649,12 @@ SqlPrepare(DStoreHandle *handle, const char *statement, DStoreStmt *stmt) XplDelay(STMT_SLEEP_MS); continue; default: - XplConsolePrintf("SQL Prepare statement \"%s\" failed; %s\r\n", + Log(LOG_INFO, "SQL Prepare statement \"%s\" failed; %s", statement, sqlite3_errmsg(handle->db)); return NULL; } } - XplConsolePrintf("Sql Prepare failed because db is busy.\r\n"); + Log(LOG_ERROR, "Sql Prepare failed because db is busy.\r\n"); return NULL; } @@ -681,11 +715,11 @@ DStoreStmtStep(DStoreHandle *handle, XplDelay(STMT_SLEEP_MS); continue; default: - XplConsolePrintf("Sql: %s\r\n", sqlite3_errmsg(handle->db)); + Log(LOG_INFO, "Sql: %s", sqlite3_errmsg(handle->db)); return -1; } } - XplConsolePrintf("Sql Busy.\r\n"); + Log(LOG_ERROR, "Sql Busy."); return -1; } @@ -700,7 +734,7 @@ DStoreStmtExecute(DStoreHandle *handle, DStoreStmt *_stmt) if (SQLITE_DONE == result) { return 0; } else { - XplConsolePrintf("Sql: %s\r\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "Sql: %s", sqlite3_errmsg(handle->db)); return -1; } } @@ -709,7 +743,7 @@ DStoreStmtExecute(DStoreHandle *handle, DStoreStmt *_stmt) void DStoreStmtError(DStoreHandle *handle, DStoreStmt *stmt) { - XplConsolePrintf("Sql: %s\r\n", sqlite3_errmsg(handle->db)); + Log(LOG_ERROR, "Sql: %s\r\n", sqlite3_errmsg(handle->db)); } @@ -867,12 +901,12 @@ DStoreCancelTransactions(DStoreHandle *handle) #define DOCINFO_COLS " docs.guid, docs.info, " \ " docs.subject, docs.senders, docs.msgid, docs.parentmsgid, " \ " docs.conversation, docs.listid," \ - " docs.uid, docs.summary, docs.location, docs.stamp " + " docs.uid, docs.summary, docs.location, docs.stamp, docs.type " #define CONVINFO_COLS " docs.guid, docs.info, conversations.subject " #define CONVINFO_COLSAS " docs.guid as guid, docs.info as info, conversations.subject as subject" #define EVENTINFO_COLS " events.guid, docs.info, " \ " 0, 0, 0, 0, 0, 0, " \ - " docs.uid, docs.summary, docs.location, docs.stamp " + " docs.uid, docs.summary, docs.location, docs.stamp, docs.type " /* returns: 1 on success 0 if no row available, @@ -894,7 +928,7 @@ retry: return result; } if (DOCINFO_SIZE != sqlite3_column_bytes(stmt->stmt, 1)) { - XplConsolePrintf("Store DB error: Incompatible docs table.\r\n"); + Log(LOG_ERROR, "Store DB error: Incompatible docs table."); return -1; } data = sqlite3_column_blob(stmt->stmt, 1); @@ -918,6 +952,8 @@ retry: } \ } + info->type = sqlite3_column_int64(stmt->stmt, 12); + switch (info->type) { case STORE_DOCTYPE_CONVERSATION: GET_COL(2, info->data.conversation.subject); @@ -1105,9 +1141,9 @@ DStoreSetDocInfo(DStoreHandle *handle, DStoreDocInfo *info) "(guid, filename, collection, info, " " conversation, " " subject, senders, msgid, parentmsgid, listid, " - " uid, summary, location, stamp) " + " uid, summary, location, stamp, type) " "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, " - " ?11, ?12, ?13, ?14);", + " ?11, ?12, ?13, ?14, ?15);", &handle->stmts.setInfo); } else { newDoc = TRUE; @@ -1116,9 +1152,9 @@ DStoreSetDocInfo(DStoreHandle *handle, DStoreDocInfo *info) "(filename, collection, info, " " conversation, " " subject, senders, msgid, parentmsgid, listid, " - " uid, summary, location, stamp) " + " uid, summary, location, stamp, type) " "VALUES (?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, " - " ?11, ?12, ?13, ?14);", + " ?11, ?12, ?13, ?14, ?15);", &handle->stmts.addInfo); } if (!stmt) { @@ -1127,6 +1163,7 @@ DStoreSetDocInfo(DStoreHandle *handle, DStoreDocInfo *info) if ((info->guid && sqlite3_bind_int64(stmt->stmt, 1, info->guid)) || DStoreBindStr(stmt->stmt, 2, filename) || sqlite3_bind_int64(stmt->stmt, 3, info->collection) || + sqlite3_bind_int64(stmt->stmt, 15, info->type) || sqlite3_bind_blob(stmt->stmt, 4, info, DOCINFO_SIZE, SQLITE_STATIC) || sqlite3_bind_int64(stmt->stmt, 5, info->conversation)) { @@ -1314,6 +1351,40 @@ DStoreListColl(DStoreHandle *handle, uint64_t collection, int start, int end) return stmt; } +DStoreStmt * +DStoreListCollections(DStoreHandle *handle, char *root, int start, int end) +{ + DStoreStmt *stmt; + int rootlen; + + if (root == NULL) root = "/"; + rootlen = strlen(root); + +#define DS_LIST_COLL_QUERY "SELECT" DOCINFO_COLS "FROM docs WHERE type = 4096 AND substr(filename, 0, ?) = ?" + + if (start != -1) { + stmt = SqlPrepare(handle, + DS_LIST_COLL_QUERY " LIMIT ?, ?;", + &handle->stmts.listCollectionsRange); + } else { + stmt = SqlPrepare(handle, + DS_LIST_COLL_QUERY ";", + &handle->stmts.listCollections); + } + + if (!stmt || + sqlite3_bind_int64(stmt->stmt, 1, rootlen) || + DStoreBindStr(stmt->stmt, 2, root)) { + DStoreStmtError(handle, stmt); + return NULL; + } + if (start != -1) { + sqlite3_bind_int64(stmt->stmt, 3, start); + sqlite3_bind_int64(stmt->stmt, 4, end); + } + return stmt; +} + DStoreStmt * DStoreGuidList(DStoreHandle *handle, uint64_t *guids, int numGuids) @@ -1600,15 +1671,15 @@ DStoreSetProperty(DStoreHandle *handle, int DStoreSetPropertySimple(DStoreHandle *handle, uint64_t guid, - char *name, - char *value) + const char *name, + const char *value) { StorePropInfo prop; prop.type = STORE_PROP_EXTERNAL; - prop.name = name; - prop.value = value; + prop.name = (char *)name; + prop.value = (char *)value; prop.valueLen = strlen(value); return DStoreSetProperty(handle, guid, &prop); @@ -1887,7 +1958,7 @@ test_headers(sqlite3_context *ctx, int argc, sqlite3_value **argv) p = subject; break; default: - printf("test_headers(): Bad header type.\n"); + Log(LOG_ERROR, "test_headers(): Bad header type."); continue; } @@ -2638,84 +2709,6 @@ cleanup: return dcode; } - -int -DStoreAddJournalEntry(DStoreHandle *handle, uint64_t collection, char *filename) -{ - DStoreStmt *stmt; - int result; - - stmt = SqlPrepare(handle, - "INSERT into journal (collection, filename) " - "VALUES (?, ?);", - &handle->stmts.addJournalEntry); - if (!stmt || - sqlite3_bind_int64(stmt->stmt, 1, collection) || - DStoreBindStr(stmt->stmt, 2, filename)) - { - return -1; - } - result = DStoreStmtExecute(handle, stmt); - - DStoreStmtEnd(handle, stmt); - - return result; -} - - -int -DStoreRemoveJournalEntry(DStoreHandle *handle, uint64_t collection) -{ - DStoreStmt *stmt; - int result; - - stmt = SqlPrepare(handle, "DELETE FROM journal WHERE collection=?;", - &handle->stmts.delJournalEntry); - if (!stmt || - sqlite3_bind_int64(stmt->stmt, 1, collection)) - { - return -1; - } - result = DStoreStmtExecute(handle, stmt); - DStoreStmtEnd(handle, stmt); - - return result; -} - - -DStoreStmt * -DStoreListJournal(DStoreHandle *handle) -{ - DStoreStmt *stmt; - - stmt = SqlPrepare(handle, "SELECT collection, filename FROM journal;", - &handle->stmts.listJournal); - - if (!stmt) { - DStoreStmtError(handle, stmt); - return NULL; - } - return stmt; -} - - -int -DStoreJournalStmtStep(DStoreHandle *handle, DStoreStmt *stmt, - uint64_t *outGuid, const char **outFilename) -{ - int result; - - if (1 != (result = DStoreStmtStep(handle, stmt))) { - return result; - } - - *outGuid = sqlite3_column_int64(stmt->stmt, 0); - *outFilename = sqlite3_column_text(stmt->stmt, 1); - - return 1; -} - - /** mime cache **/ diff --git a/src/agents/store/db.h b/src/agents/store/db.h index 3ff7f5d..b2ab9e4 100644 --- a/src/agents/store/db.h +++ b/src/agents/store/db.h @@ -26,6 +26,8 @@ typedef int InfoStmtFilter(DStoreDocInfo *info, void *userdata); DStoreHandle *DStoreOpen(char *basepath, BongoMemStack *memstack, int locktimeoutms); void DStoreClose(DStoreHandle *handle); +int DStoreCheckDBSchema(DStoreHandle *handle); + BongoMemStack *DStoreGetMemStack(DStoreHandle *handle); void DStoreSetMemStack(DStoreHandle *handle, BongoMemStack *memstack); @@ -98,6 +100,9 @@ int DStoreDeleteCollectionContents(DStoreHandle *handle, uint64_t guid); DStoreStmt *DStoreListColl(DStoreHandle *handle, uint64_t collection, int start, int end); +DStoreStmt *DStoreListCollections(DStoreHandle *handle, char *root, int start, int end); + + DStoreStmt *DStoreListUnindexed(DStoreHandle *handle, int value, uint64_t collection); DStoreStmt *DStoreGuidList(DStoreHandle *handle, uint64_t *guids, int numGuids); @@ -161,8 +166,8 @@ int DStoreSetProperty(DStoreHandle *handle, int DStoreSetPropertySimple(DStoreHandle *handle, uint64_t guid, - char *name, - char *value); + const char *name, + const char *value); /* Conversations table */ DStoreStmt *DStoreListConversations(DStoreHandle *handle, diff --git a/src/agents/store/filters/contact-filter.cpp b/src/agents/store/filters/contact-filter.cpp index c13da72..af5b45c 100644 --- a/src/agents/store/filters/contact-filter.cpp +++ b/src/agents/store/filters/contact-filter.cpp @@ -42,12 +42,13 @@ AddObject(StoreClient *client, int FilterContact(StoreClient *client, DStoreDocInfo *info, - LuceneIndex *index) + LuceneIndex *index, + char *path) { BongoJsonNode *node; BongoJsonObject *obj; - if (GetJson(client, info, &node) != BONGO_JSON_OK || node->type != BONGO_JSON_OBJECT) { + if (GetJson(client, info, &node, path) != BONGO_JSON_OK || node->type != BONGO_JSON_OBJECT) { return -1; } diff --git a/src/agents/store/filters/event-filter.cpp b/src/agents/store/filters/event-filter.cpp index 0930fae..9b3a9ac 100644 --- a/src/agents/store/filters/event-filter.cpp +++ b/src/agents/store/filters/event-filter.cpp @@ -17,13 +17,14 @@ AddObject(StoreClient *client, int FilterEvent(StoreClient *client, DStoreDocInfo *info, - LuceneIndex *index) + LuceneIndex *index, + char *path) { BongoJsonNode *node; BongoJsonObject *obj; BongoCalObject *cal; - if (GetJson(client, info, &node) != BONGO_JSON_OK || node->type != BONGO_JSON_OBJECT) { + if (GetJson(client, info, &node, path) != BONGO_JSON_OK || node->type != BONGO_JSON_OBJECT) { return -1; } diff --git a/src/agents/store/filters/filter.cpp b/src/agents/store/filters/filter.cpp index a3f64f8..de3b9f1 100644 --- a/src/agents/store/filters/filter.cpp +++ b/src/agents/store/filters/filter.cpp @@ -26,14 +26,14 @@ utf8towcs(wchar_t *result, const char *str, int len) int -FilterDocument(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index) +FilterDocument(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *path) { if (info->type == STORE_DOCTYPE_MAIL) { - return FilterMail(client, info, index); + return FilterMail(client, info, index, path); } else if (info->type == STORE_DOCTYPE_AB) { - return FilterContact(client, info, index); + return FilterContact(client, info, index, path); } else if (info->type == STORE_DOCTYPE_EVENT) { - return FilterEvent(client, info, index); + return FilterEvent(client, info, index, path); } return 0; diff --git a/src/agents/store/filters/filter.h b/src/agents/store/filters/filter.h index c8bbf7d..d1b625e 100644 --- a/src/agents/store/filters/filter.h +++ b/src/agents/store/filters/filter.h @@ -4,7 +4,7 @@ #include "stored.h" #include "lucene-index.h" -int FilterDocument(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index); +int FilterDocument(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *path); int FilterAddSummaryInfo(Document *doc, DStoreDocInfo *info); int FilterAddText(Document *doc, @@ -31,9 +31,9 @@ int FilterAddJsonString(Document *doc, const char *childName, bool includeInEverything = true); -int FilterMail(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index); -int FilterContact(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index); -int FilterEvent(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index); +int FilterMail(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *path); +int FilterContact(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *path); +int FilterEvent(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *path); #endif diff --git a/src/agents/store/filters/mail-filter.cpp b/src/agents/store/filters/mail-filter.cpp index 323b8cc..d2ff23a 100644 --- a/src/agents/store/filters/mail-filter.cpp +++ b/src/agents/store/filters/mail-filter.cpp @@ -21,7 +21,7 @@ AddTextPart(Document *doc, jstreams::BongoStreamInputStream *istream = new jstreams::BongoStreamInputStream (fh, - info->start + info->headerlen + part->start, + part->start, part->len, part->encoding[0] != '-' ? (char*)part->encoding : NULL, part->charset[0] != '-' ? (char*)part->charset : NULL); @@ -72,12 +72,12 @@ AddParts(Document *doc, unsigned char buffer[XPL_MAX_RFC822_LINE]; int ccode; - if (0 != XplFSeek64(fh, info->start + info->headerlen, SEEK_SET)) { + if (0 != XplFSeek64(fh, 0, SEEK_SET)) { ccode = ConnWriteStr(client->conn, MSG4224CANTWRITE); goto finish; } - report = MimeParse(fh, info->bodylen, buffer, sizeof(buffer)); + report = MimeParse(fh, info->length, buffer, sizeof(buffer)); if (report) { for (unsigned long i = 0; i < report->lineCount; i++) { MimeResponseLine *part = &report->line[i]; @@ -181,7 +181,7 @@ AddMailPropertyInfo(StoreClient *client, Document *doc, DStoreDocInfo *info) int -FilterMail(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index) +FilterMail(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index, char *filepath) { FILE *fh; char path[XPL_MAX_PATH + 1]; @@ -190,7 +190,11 @@ FilterMail(StoreClient *client, DStoreDocInfo *info, LuceneIndex *index) FilterAddKeyword(doc, _T("type"), "mail", false); - FindPathToDocFile(client, info->collection, path, sizeof(path)); + if (filepath) { + strncpy(path, filepath, XPL_MAX_PATH); + } else { + FindPathToDocument(client, info->collection, info->guid, path, sizeof(path)); + } fh = fopen(path, "rb"); if (!fh) { diff --git a/src/agents/store/index.cpp b/src/agents/store/index.cpp index 9f39888..dbf1732 100644 --- a/src/agents/store/index.cpp +++ b/src/agents/store/index.cpp @@ -119,13 +119,13 @@ IndexRemoveDocument(IndexHandle *handle, uint64_t guid) } int -IndexDocument(IndexHandle *handle, StoreClient *client, DStoreDocInfo *info) +IndexDocument(IndexHandle *handle, StoreClient *client, DStoreDocInfo *info, char *path) { if (IndexRemoveDocument(handle, info->guid)) { return 1; } - return FilterDocument(client, info, handle->index); + return FilterDocument(client, info, handle->index, path); } int diff --git a/src/agents/store/index.h b/src/agents/store/index.h index d623a62..4e68607 100644 --- a/src/agents/store/index.h +++ b/src/agents/store/index.h @@ -33,7 +33,7 @@ IndexHandle *IndexOpen(StoreClient *client); void IndexClose(IndexHandle *handle); void IndexOptimize(IndexHandle *handle); -int IndexDocument(IndexHandle *handle, StoreClient *client, DStoreDocInfo *doc); +int IndexDocument(IndexHandle *handle, StoreClient *client, DStoreDocInfo *doc, char *path); int IndexRemoveDocument(IndexHandle *handle, uint64_t guid); diff --git a/src/agents/store/lock.c b/src/agents/store/lock.c index 773a2f7..028e723 100644 --- a/src/agents/store/lock.c +++ b/src/agents/store/lock.c @@ -355,13 +355,13 @@ ReadNMAPLockAcquire(NLockStruct **lockHandle, unsigned long *hashHandle, unsigne } #if defined(DEBUG) - XplConsolePrintf("NMAP: ReadNMAPLockAcquire() called with an existing lock from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "ReadNMAPLockAcquire() called with an existing lock from %s:%lu", file, line); #endif return(NLOCK_HANDLE_HAS_LOCK); } #if defined(DEBUG) - XplConsolePrintf("NMAP: ReadNMAPLockAcquire() called with a NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "ReadNMAPLockAcquire() called with a NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_HANDLE_NOT_PROVIDED); @@ -390,7 +390,7 @@ ReadNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long if ((lockHandle->wLock == 0) && (lockHandle->eLock == 0)) { ; } else { - XplConsolePrintf("NMAP: ReadNMAPLockRelease() called with values RLock = %lu WLock = %lu and ELock = %lu from %s:%lu\r\n", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); + Log(LOG_DEBUG, "ReadNMAPLockRelease() called with values RLock = %lu WLock = %lu and ELock = %lu from %s:%lu", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); } #endif @@ -447,14 +447,14 @@ ReadNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long XplSignalLocalSemaphore(NLockHeadArray[lockHandle->slot].lock); #if defined(DEBUG) - XplConsolePrintf("NMAP: ReadNMAPLockRelease() called with no readers from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "ReadNMAPLockRelease() called with no readers from %s:%lu", file, line); #endif return(NLOCK_INVALID); } #if defined(DEBUG) - XplConsolePrintf("NMAP: ReadNMAPLockRelease() called with an NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "ReadNMAPLockRelease() called with an NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_INVALID); @@ -513,7 +513,7 @@ WriteNMAPLockAcquire(NLockStruct *lockHandle, long timeout, unsigned char *file, } #if defined(DEBUG) - XplConsolePrintf("NMAP: WriteNMAPLockAcquire() called with an NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "WriteNMAPLockAcquire() called with an NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_INVALID); @@ -533,7 +533,7 @@ WriteNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long if ((lockHandle->rLock > 0) && (lockHandle->eLock == 0) && (lockHandle->wLock == 1)) { ; } else { - XplConsolePrintf("NMAP: WriteNMAPLockRelease() called with unexpected values RLock:%lu WLock: %lu ELock: %lu from %s:%lu\r\n", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); + Log(LOG_DEBUG, "WriteNMAPLockRelease() called with unexpected values RLock:%lu WLock: %lu ELock: %lu from %s:%lu", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); } #endif @@ -543,7 +543,7 @@ WriteNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long } #if defined(DEBUG) - XplConsolePrintf("NMAP: WriteNMAPLockRelease() with a NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "WriteNMAPLockRelease() with a NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_INVALID); @@ -604,7 +604,7 @@ PurgeNMAPLockAcquire(NLockStruct *lockHandle, long timeout, unsigned char *file, } #if defined(DEBUG) - XplConsolePrintf("NMAP: PurgeNMAPLockAcquire() called with an NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "PurgeNMAPLockAcquire() called with an NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_INVALID); @@ -625,7 +625,7 @@ PurgeNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long if ((lockHandle->eLock == 1) && (lockHandle->wLock == 0) && (lockHandle->rLock == 1)) { ; } else { - XplConsolePrintf("NMAP: PurgeNMAPLockAcquire() called with unexpected values RLock:%lu WLock: %lu ELock: %lu from %s:%lu\r\n", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); + Log(LOG_DEBUG, "PurgeNMAPLockAcquire() called with unexpected values RLock:%lu WLock: %lu ELock: %lu from %s:%lu", lockHandle->rLock, lockHandle->wLock, lockHandle->eLock, file, line); } #endif @@ -635,7 +635,7 @@ PurgeNMAPLockRelease(NLockStruct *lockHandle, unsigned char *file, unsigned long } #if defined(DEBUG) - XplConsolePrintf("NMAP: PurgeNMAPLockAcquire() called with a NULL lock handle from %s:%lu\r\n", file, line); + Log(LOG_DEBUG, "PurgeNMAPLockAcquire() called with a NULL lock handle from %s:%lu", file, line); #endif return(NLOCK_INVALID); diff --git a/src/agents/store/mail-parser.c b/src/agents/store/mail-parser.c index 185df30..65eafd5 100644 --- a/src/agents/store/mail-parser.c +++ b/src/agents/store/mail-parser.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -272,17 +271,17 @@ DecodeWord(char *buf, int len, char **prevtext) } if (BongoStreamAddCodec(stream, encoding, FALSE)) { - printf ("Don't understand encoding %s\n", encoding); + Log(LOG_ERROR, "Mail parser doesn't understand encoding %s", encoding); goto done; } if (BongoStreamAddCodec(stream, charset, FALSE)) { - printf("Don't understand charset %s\n", charset); + Log(LOG_ERROR, "Mail parser doesn't understand charset %s", charset); goto done; } if (BongoStreamAddCodec(stream, "UTF-8", TRUE)) { - printf("Couldn't add UTF-8 encoder\n"); + Log(LOG_ERROR, "Mail parser couldn't convert to UTF-8"); goto done; } @@ -1095,7 +1094,7 @@ MailParseHeaders(MailParser *parser) parser->p = q + 1; if (-1 == ParseHeader(parser, header)) { - printf("didn't understand header: %d: %s", header, q + 1); + Log(LOG_ERROR, "Parsing headers, didn't understand this: %d: %s", header, q + 1); if (parser->p != parser->line) { /* nevertheless, we've got to soldier on */ NEXTLINE(0); diff --git a/src/agents/store/mail.c b/src/agents/store/mail.c index 86afd2c..e16f70d 100644 --- a/src/agents/store/mail.c +++ b/src/agents/store/mail.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -124,9 +123,7 @@ IncomingParticipantCb(void *datap, MailHeaderName name, MailAddress *address) return; } -#if 0 - printf("got %s %s <%s>\n", type, address->displayName, address->address); -#endif + Log(LOG_DEBUG, "IPCB got %s %s <%s>\n", type, address->displayName, address->address); } static void @@ -246,18 +243,15 @@ StoreProcessIncomingMail(StoreClient *client, IncomingParseData data = {0, }; DStoreDocInfo oldConversation; BOOL haveOldConversation; - BOOL isNewConversation; FILE *fh; fh = fopen(path, "rb"); if (!fh) { return MSG4224CANTREADMBOX; - } - - fseek(fh, info->start + info->headerlen, SEEK_SET); + } - data.headerStartOffset = info->start + info->headerlen; + data.headerStartOffset = 0; data.handle = client->handle; data.info = info; diff --git a/src/agents/store/maildir.c b/src/agents/store/maildir.c new file mode 100644 index 0000000..93f8244 --- /dev/null +++ b/src/agents/store/maildir.c @@ -0,0 +1,176 @@ +// Bongo copyright applies +// (C) Alex Hudson 2007 + +/** \file + * Various utility functions for dealing with maildir storage + */ + +#include +#include + +// mkdir () +#include +#include +#include + +// readdir () +#include +#include + +// mkstemp () +#include + +#include "stored.h" + +/** + * Find the path to a directory representing the maildir for a collection on disk + * \param client Calling store client + * \param collection UID of the collection we're looking for + * \param dest The path is written to this buffer + * \param size Size of the path buffer allocating + * \return Nothing + */ +void +FindPathToCollection(StoreClient *client, uint64_t collection, char *dest, size_t size) +{ + snprintf(dest, size, "%s" GUID_FMT, client->store, collection); + dest[size-1] = '\0'; +} + +/** + * Find the path to a file representing the file in a maildir for a document on disk + * \param client Calling store client + * \param collection UID of the collection we're looking for + * \param document UID of the document we want + * \param dest The path is written to this buffer + * \param size Size of the path buffer allocating + * \return Nothing + */ +void +FindPathToDocument(StoreClient *client, uint64_t collection, uint64_t document, +char *dest, size_t size) +{ + snprintf(dest, size, "%s" GUID_FMT "/cur/" GUID_FMT, client->store, collection, document); + dest[size-1] = '\0'; +} + +/** + * Create a new maildir. If it already exists, we don't error + * \param store_path Path to the file store to contain the collection we want to create + * \param collection UID of the collection we want to represent + * \return 0 on success, <0 otherwise + */ +int +MaildirNew(const char *store_path, uint64_t collection) +{ + const char *dirs[] = { "/", "/cur", "/new", "/tmp", NULL }; + char rootpath[XPL_MAX_PATH]; + char subdir[XPL_MAX_PATH + 5]; + int i; + + snprintf(rootpath, XPL_MAX_PATH, "%s" GUID_FMT, store_path, collection); + + for (i = 0; dirs[i] != NULL; i++) { + int res = 0; + strncpy(subdir, rootpath, XPL_MAX_PATH); + strncat(subdir, dirs[i], 5); + res = mkdir(subdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP); + if ((res != 0) && (errno != EEXIST)) { + return -4; + } + chmod(subdir, S_IRUSR | S_IWUSR | S_IXUSR); + } + return 0; +} + +/** + * Remove an existing maildir + * \param store_path Path to the file store containing the maildir we want to remove + * \param collection UID of the collection we want to remove + * \return 0 on success, some error otherwise + */ +int +MaildirRemove(const char *store_path, uint64_t collection) +{ + const char *dirs[] = { "/cur", "/new", "/tmp", NULL }; + char rootpath[XPL_MAX_PATH+1]; + int i; + + for (i = 0; dirs[i] != NULL; i++) { + DIR *dir; + struct dirent *content; + + snprintf(rootpath, XPL_MAX_PATH, "%s" GUID_FMT "%s", store_path, collection, dirs[i]); + dir = opendir(rootpath); + if (dir) { + char filename[XPL_MAX_PATH+1]; + + while ((content = readdir(dir)) != NULL) { + char *c = content->d_name; + if ((c[0] == '.') && ((c[1] == '.') || (c[1] == '\0'))){ + continue; + } + snprintf(filename, XPL_MAX_PATH, "%s/%s", rootpath, content->d_name); + if (unlink(filename) == -1) { + // can't remove one of the contents + closedir(dir); + return errno; + } + } + closedir(dir); + } + if (rmdir(rootpath) != 0) return errno; + } + + snprintf(rootpath, XPL_MAX_PATH, "%s" GUID_FMT, store_path, collection); + if (rmdir(rootpath) != 0) return errno; + + return 0; +} + +/** + * Create a temporary file in a maildir + * \param client Store client + * \param collection UID of the collection we want to put the document in + * \param dest Buffer to contain the file path to the temp document + * \param size Size of the buffer allocated in dest + * \return 0 on success, -1 on error + */ +int +MaildirTempDocument(StoreClient *client, uint64_t collection, char *dest, size_t size) +{ + int fd; + + snprintf(dest, size, "%s" GUID_FMT "/tmp/XXXXXXXX", client->store, collection); + dest[size-1] = '\0'; + fd = mkstemp(dest); + if (fd != -1) { + close(fd); + unlink(dest); + return 0; + } + return -1; +} + +/** + * Move a temporary file into it's final position based on allocation UID + * \param client Store client + * \param collection UID of the collection we want to put the document in + * \param path File path to the temporary document + * \param uid Allocated uid of the document + * \return 0 on success, -1 otherwise + */ +int +MaildirDeliverTempDocument(StoreClient *client, uint64_t collection, const char *path, uint64_t uid) +{ + char newpath[XPL_MAX_PATH+1]; + + FindPathToDocument(client, collection, uid, &newpath, XPL_MAX_PATH); + + if (link(path, newpath) != 0) { + // look at errno. EEXIST suggests we already delivered it; maybe ignore that? + return -1; + } + unlink(path); // don't really care if this fails? + return 0; +} diff --git a/src/agents/store/messages.h b/src/agents/store/messages.h index d4b0351..13bcfdd 100644 --- a/src/agents/store/messages.h +++ b/src/agents/store/messages.h @@ -56,6 +56,7 @@ #define MSG3015NOTCOLL "3015 Not a collection\r\n" #define MSG3015BADCOLLTYPE "3015 Not a collection type\n" #define MSG3016DOCTYPESYNTAX "3016 Invalid document type.\r\n" +#define MSG3016DOCTYPEUNREADABLE "3016 Cannot read this document type.\r\n" #define MSG3017BADINTARG "3017 Integer expected\r\n" #define MSG3017INTARGRANGE "3017 Integer outside allowed range.\r\n" #define MSG3018BADPATH "3018 Bad path\r\n" @@ -123,6 +124,7 @@ #define MSG4224NOUSER "4224 User does not exist\r\n" #define MSG4224NOCOLLECTION "4224 Collection doesn't exist\r\n" #define MSG4224NODOCUMENT "4224 Document doesn't exist\r\n" +#define MSG4225BADVERSION "4225 Store database version is inconsistent\r\n" #define MSG4226MBOXEXISTS "4226 Mailbox already exists\r\n" #define MSG4226CALEXISTS "4226 Calendar already exists\r\n" #define MSG4226BADEMAIL "4226 Unable to parse email\r\n" diff --git a/src/agents/store/mime.c b/src/agents/store/mime.c index 119f931..218c4c8 100644 --- a/src/agents/store/mime.c +++ b/src/agents/store/mime.c @@ -21,9 +21,6 @@ #include #include -// #include -// #include -// #include #include #include "stored.h" @@ -839,7 +836,7 @@ MimeGetHelper(StoreClient *client, DStoreDocInfo *info, MimeReport **outReport) int result = 1; char buffer[CONN_BUFSIZE]; - FindPathToDocFile(client, info->collection, path, sizeof(path)); + FindPathToDocument(client, info->collection, info->guid, path, sizeof(path)); fh = fopen(path, "rb"); if (!fh) { @@ -847,12 +844,7 @@ MimeGetHelper(StoreClient *client, DStoreDocInfo *info, MimeReport **outReport) goto finish; } - if (0 != XplFSeek64(fh, info->start + info->headerlen, SEEK_SET)) { - result = -4; - goto finish; - } - - *outReport = MimeParse(fh, info->bodylen, buffer, sizeof(buffer)); + *outReport = MimeParse(fh, info->length, buffer, sizeof(buffer)); if (!*outReport) { result = -5; goto finish; diff --git a/src/agents/store/search.c b/src/agents/store/search.c index 82218e0..6436765 100644 --- a/src/agents/store/search.c +++ b/src/agents/store/search.c @@ -58,7 +58,7 @@ SearchDocument(StoreClient *client, DStoreDocInfo *info, case STORE_SEARCH_TEXT: /* TEXT checks both HEADERS and BODY */ case STORE_SEARCH_HEADERS: { - if (XplFSeek64(f, info->start + info->headerlen, SEEK_SET)) { + if (XplFSeek64(f, 0, SEEK_SET)) { ccode = ConnWriteStr(client->conn, MSG4224CANTREAD); break; } @@ -90,7 +90,7 @@ SearchDocument(StoreClient *client, DStoreDocInfo *info, continue; } - if (XplFSeek64(f, info->start + info->headerlen + line->start, SEEK_SET)) { + if (XplFSeek64(f, line->start, SEEK_SET)) { ccode = ConnWriteStr(client->conn, MSG4224CANTREAD); break; } @@ -144,7 +144,7 @@ SearchDocument(StoreClient *client, DStoreDocInfo *info, break; } - if (XplFSeek64(f, info->start + info->headerlen, SEEK_SET)) { + if (XplFSeek64(f, 0, SEEK_SET)) { ccode = ConnWriteStr(client->conn, MSG4224CANTREAD); break; } @@ -189,28 +189,27 @@ StoreCommandSEARCH(StoreClient *client, uint64_t guid, StoreSearchInfo *query) return ConnWriteStr(client->conn, MSG5005DBLIBERR); } - if (STORE_IS_FOLDER(info.type)) { - FindPathToDocFile(client, guid, path, sizeof(path)); - } else { - FindPathToDocFile(client, info.collection, path, sizeof(path)); - } - - f = fopen(path, "rb"); - if (!f) { - return ConnWriteStr(client->conn, MSG4224CANTREAD); - } - + // we're searching a document if (!STORE_IS_FOLDER(info.type)) { + FindPathToDocument(client, info.collection, info.guid, path, sizeof(path)); + + f = fopen(path, "rb"); + if (!f) { + return ConnWriteStr(client->conn, MSG4224CANTREAD); + } + ccode = SearchDocument(client, &info, query, f); if (-1 != ccode) { ccode = ConnWriteStr(client->conn, MSG1000OK); } - goto finish; + fclose(f); + return ccode; } - + + // we're searching a collection stmt = DStoreListColl(client->handle, guid, -1, -1); if (!stmt) { - ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR); + return ConnWriteStr(client->conn, MSG5005DBLIBERR); goto finish; } @@ -229,13 +228,9 @@ StoreCommandSEARCH(StoreClient *client, uint64_t guid, StoreSearchInfo *query) break; } } - + finish: - (void) fclose(f); - if (stmt) { - DStoreStmtEnd(client->handle, stmt); - } - + if (stmt) DStoreStmtEnd(client->handle, stmt); return ccode; } diff --git a/src/agents/store/store.c b/src/agents/store/store.c index 4206172..e9881b3 100644 --- a/src/agents/store/store.c +++ b/src/agents/store/store.c @@ -44,16 +44,6 @@ IsOwnStoreSelected(StoreClient *client) (!strcmp(client->principal.name, client->storeName))); } - -void -FindPathToDocFile(StoreClient *client, uint64_t collection, - char *dest, size_t size) -{ - snprintf(dest, size, "%s" GUID_FMT ".dat", client->store, collection); - dest[size-1] = '\0'; -} - - /* Creates a new collection, including any ancestors required. Also touches the file for this collection (but doesn't truncate it, since this function is also used by the RENAME command (which is a bit of an abstraction violation)) @@ -74,7 +64,7 @@ StoreCreateCollection(StoreClient *client, char *name, uint64_t guid, DStoreDocInfo info; char path[XPL_MAX_PATH + 1]; char *p; - FILE *f; + int res; int namelen = strlen(name); /* validate collection name */ @@ -136,12 +126,8 @@ StoreCreateCollection(StoreClient *client, char *name, uint64_t guid, } info.collection = info.guid; - FindPathToDocFile(client, info.guid, path, sizeof(path)); - f = fopen(path, "ab"); - if (!f) { - return -4; - } - fclose(f); + res = MaildirNew(client->store, info.guid); + if (res != 0) return res; } while (p); if (outGuid) { @@ -211,7 +197,7 @@ StoreCreateDocument(StoreClient *client, return -2; } - FindPathToDocFile(client, info.guid, path, sizeof(path)); + FindPathToDocument(client, info.collection, info.guid, path, sizeof(path)); f = fopen(path, "ab"); if (!f) { return -4; @@ -223,43 +209,6 @@ StoreCreateDocument(StoreClient *client, return 0; } - -int -WriteDocumentHeaders(StoreClient *client, - FILE *fh, - const char *folder, - time_t tod) -{ - static char magicbuffer[18] = "0100 \r\n"; - - if (sizeof(magicbuffer) != - fwrite(magicbuffer, sizeof(unsigned char), sizeof(magicbuffer), fh)) - { - return -1; - } - - return sizeof(magicbuffer); -} - - -static int -CreateDatFile(char *path, int n, size_t len, char *name) -{ - FILE *file; - - strncpy(path + n, name, len - n); - path[XPL_MAX_PATH] = 0; - - file = fopen(path, "ab"); - if (!file) { - return -1; - } - fclose(file); - - return 0; -} - - /* find the user's store path, creating it if necessary path must be a buffer of size XPL_MAX_PATH + 1 or greater returns 0 on success, -1 o/w @@ -268,50 +217,38 @@ CreateDatFile(char *path, int n, size_t len, char *name) int SetupStore(const char *user, const char **storeRoot, char *path, size_t len) { - const char *root; - int n; - struct stat sb; + int n; + struct stat sb; + BOOL make_store = FALSE; - if (! StoreAgent.installMode) { - // MsgFindUserStore makes MDB calls and thus can't be used in installmode. - root = MsgFindUserStore(user, StoreAgent.store.rootDir); - } else { - root = StoreAgent.store.rootDir; - } - n = snprintf(path, len, "%s/%s/", root, user); - path[len] = 0; - path[n-1] = 0; + n = snprintf(path, len, "%s/%s/", StoreAgent.store.rootDir, user); + path[len] = 0; + path[n-1] = 0; - if (stat(path, &sb)) { - if (XplMakeDir(path)) { - XplConsolePrintf("Error creating store: %s.\r\n", strerror(errno)); - return -1; - } - } - path[n-1] = '/'; + if (stat(path, &sb)) { + if (XplMakeDir(path)) { + Log(LOG_ERROR, "Error creating store directory: %s.", strerror(errno)); + return -1; + } + make_store = TRUE; + } + + path[n-1] = '/'; - if (CreateDatFile(path, n, len, "0000000000000002.dat") || - CreateDatFile(path, n, len, "0000000000000003.dat") || - CreateDatFile(path, n, len, "0000000000000004.dat") || - CreateDatFile(path, n, len, "0000000000000005.dat") || - CreateDatFile(path, n, len, "0000000000000006.dat") || - CreateDatFile(path, n, len, "0000000000000007.dat") || - CreateDatFile(path, n, len, "0000000000000008.dat") || - CreateDatFile(path, n, len, "0000000000000009.dat") || - CreateDatFile(path, n, len, "000000000000000a.dat") || - CreateDatFile(path, n, len, "000000000000000b.dat") || - CreateDatFile(path, n, len, "000000000000000c.dat") || - CreateDatFile(path, n, len, "000000000000000d.dat")) - { - XplConsolePrintf("Error creating store: %s.\r\n", strerror(errno)); - return -1; - } + if (make_store) { + uint64_t i; + for (i = 0x2; i < 0xe; i++) { + if (MaildirNew(path, i)) { + Log(LOG_ERROR, "Error creating store: %s.", strerror(errno)); + return -1; + } + } + } + path[n] = 0; - path[n] = 0; + *storeRoot = NULL; - *storeRoot = root; - - return 0; + return 0; } @@ -347,7 +284,7 @@ StoreProcessDocument(StoreClient *client, result = MSG5005DBLIBERR; goto finish; } - printf("processed mail with message-id %s\r\n", info->data.mail.messageId); + Log(LOG_INFO, "Processed mail with message-id %s", info->data.mail.messageId); break; case STORE_DOCTYPE_EVENT: result = StoreProcessIncomingEvent(client, info, linkGuid); @@ -368,7 +305,7 @@ StoreProcessDocument(StoreClient *client, goto finish; } } - if (IndexDocument(indexer, client, info) != 0) { + if (IndexDocument(indexer, client, info, path) != 0) { result = MSG5007INDEXLIBERR; } if (freeindexer) { @@ -539,7 +476,7 @@ CopyMessageToMailbox(StoreClient *client, goto StoreIOError; } - info.bodylen = endoff - startoff - sizeof(info); + info.length = endoff - startoff - sizeof(info); if (sizeof(info) != fwrite(&info, sizeof(char), sizeof(info), mboxfile) || fseek(mboxfile, 0, SEEK_END)) { @@ -550,254 +487,13 @@ CopyMessageToMailbox(StoreClient *client, StoreIOError: - XplConsolePrintf ("Couldn't deliver to incoming file: %s\r\n", strerror(errno)); + Log (LOG_ERROR, "Couldn't deliver mail to incoming file: %s", strerror(errno)); if (ENOSPC == errno) { return DELIVER_QUOTA_EXCEEDED; } return DELIVER_TRY_LATER; } - -/* returns: 0 success - -1 failure, store is intact - -2 failure, and journal check is required -*/ - -int -StoreCompactCollection(StoreClient *client, uint64_t collection) -{ - FILE *fh = NULL; - FILE *newfh = NULL; - int newfd = -1; - int trans = 0; - char path[XPL_MAX_PATH+1]; - char newpath[XPL_MAX_PATH+1]; - char savepath[XPL_MAX_PATH+1]; - char *p; - NLockStruct *lock; - DStoreStmt *stmt = NULL; - int result = -1; - - newpath[0] = 0; - - printf("Compacting collection " GUID_FMT "\r\n", collection); - - if (StoreGetExclusiveLockQuiet(client, &lock, collection, 2000)) { - return -1; - } - - FindPathToDocFile(client, collection, path, sizeof(path)); - fh = fopen(path, "rb"); - if (!fh) { - goto finish; - } - - strncpy(newpath, path, sizeof(newpath)); - p = strrchr(newpath, '/'); - strcpy(p + 1, "tmp.XXXXXX"); - newfd = mkstemp(newpath); - if (-1 == newfd) { - goto finish; - } - newfh = fdopen(newfd, "wb"); - if (!newfh) { - close (newfd); - goto finish; - } - - /* save the current .dat file a as a backup: */ - - strncpy(savepath, path, sizeof(savepath)); - p = strrchr(savepath, '.'); - if (!p || strcmp(".dat", p)) { - goto finish; - } - strcpy(p, ".bak"); - - if (DStoreAddJournalEntry(client->handle, collection, savepath)) { - goto finish; - } - - if (rename(path, savepath)) { - DStoreRemoveJournalEntry(client->handle, collection); - goto finish; - } - - /* the store is in an unusable state now (temporarily, we hope) */ - result = -2; - - /* write the compacted version of the .dat file into a temp file: */ - - if (DStoreBeginTransaction(client->handle)) { - goto finish; - } - trans = 1; - - if (DStoreResetTempDocsTable(client->handle)) { - goto finish; - } - - stmt = DStoreListColl(client->handle, collection, -1, -1); - if (!stmt) { - goto finish; - } - - while (1) { - DStoreDocInfo info; - int dcode; - size_t total; - size_t count; - char buffer[CONN_BUFSIZE]; - - dcode = DStoreInfoStmtStep(client->handle, stmt, &info); - if (0 == dcode) { - break; - } else if (-1 == dcode) { - goto finish; - } - - if (STORE_IS_FOLDER(info.type)) { - continue; - } - - if (XplFSeek64(fh, info.start + info.headerlen, SEEK_SET)) { - goto finish; - } - info.start = ftell(newfh); - - info.headerlen = WriteDocumentHeaders(client, newfh, NULL, - info.timeCreatedUTC); - if (info.headerlen < 0) { - goto finish; - } - - for (total = info.bodylen; - total; - total -= count) - { - count = sizeof(buffer) < total ? sizeof(buffer) : total; - - count = fread(buffer, sizeof(char), count, fh); - if (!count || - ferror(fh) || - count != fwrite(buffer, sizeof(char), count, newfh)) - { - goto finish; - } - } - - if (DStoreAddTempDocsInfo(client->handle, &info)) { - goto finish; - } - } - - if (DStoreMergeTempDocsTable(client->handle)) { - goto finish; - } - - if (fclose(newfh)) { - goto finish; - } - newfh = NULL; - - if (fclose(fh)) { - goto finish; - } - fh = NULL; - - /* now move the compacted file into the correct place */ - - if (DStoreRemoveJournalEntry(client->handle, collection)) { - goto finish; - } - - if (rename(newpath, path)) { - goto finish; - } - newpath[0] = 0; - - if (DStoreCommitTransaction(client->handle)) { - goto finish; - } - trans = 0; - - unlink(savepath); - - /* success */ - result = 0; - -finish: - if (stmt) { - DStoreStmtEnd(client->handle, stmt); - } - - if (trans) { - DStoreAbortTransaction(client->handle); - } - - if (newfh) { - fclose(newfh); - } - if (fh) { - fclose(fh); - } - - if (-2 == result) { - if (rename(savepath, path)) { - /* Something has gone wrong, and the collection is now in an inconsistent - state, despite our efforts to restore the backup file. To prevent - corrupted access, we are going to return without releasing our lock - on the collection. FIXME - do something more graceful... - */ - printf("Collection " GUID_FMT " requires maintenance " - "after failed compaction.\r\n", collection); - - return -2; - } else { - /* Compaction failed, but at least we've returned to the original - state (except we're going to leave a harmless journal entry) */ - result = -1; - } - } - - if (newpath[0]) { - unlink(newpath); - } - - StoreReleaseExclusiveLock(client, lock); - StoreReleaseSharedLock(client, lock); - - return result; -} - - -static void -CompactAllCollections(StoreClient *client) -{ - DIR *dir; - struct dirent *dirent; - - dir = opendir(client->store); - if (!dir) { - return; - } - - while ((dirent = readdir(dir))) { - uint64_t guid; - char *endp; - - guid = HexToUInt64(dirent->d_name, &endp); - if (endp != dirent->d_name + 16 || strcmp(".dat", endp)) { - continue; - } - - StoreCompactCollection(client, guid); - } - - closedir(dir); -} - - /* deliver message to a mailbox msgfile must be an open file whose file pointer set to the start of the file. @@ -808,6 +504,8 @@ CompactAllCollections(StoreClient *client) /* FIXME: If something goes wrong while writing to the incoming file, the store won't be able to recover (bug 175411) */ +/* FIXME: this should deliver to a maildir or something */ + NMAPDeliveryCode DeliverMessageToMailbox(StoreClient *client, char *sender, char *authSender, char *recipient, char *mbox, @@ -890,6 +588,8 @@ finish: -1 - failure (corrupt file, or incompatible version) */ +/* FIXME: this should support a maildir */ + int ImportIncomingMail(StoreClient *client) { @@ -964,7 +664,7 @@ ImportIncomingMail(StoreClient *client) int dcode = 0; DStoreDocInfo collinfo; NLockStruct *collLock; - char path[XPL_MAX_PATH+1]; + char tmppath[XPL_MAX_PATH+1]; FILE *destfile = NULL; char buffer[CONN_BUFSIZE]; size_t count; @@ -988,7 +688,7 @@ ImportIncomingMail(StoreClient *client) info.collection = STORE_MAIL_INBOX_GUID; } } else if (-1 == dcode) { - printf ("couldn't write to collection %s due to db error.\n", + Log (LOG_ERROR, "Couldn't write to collection %s due to db error.", info.filename); goto finish; } @@ -1004,27 +704,16 @@ ImportIncomingMail(StoreClient *client) goto finish; } - FindPathToDocFile(client, info.collection, path, sizeof(path)); + MaildirTempDocument(client, info.collection, tmppath, sizeof(tmppath)); - destfile = fopen(path, "ab"); + destfile = fopen(tmppath, "w"); if (!destfile) { goto finish; } - info.start = ftell(destfile); - if (-1 == info.start) { - goto finish; - } - info.timeCreatedUTC = (uint64_t) time(NULL); - - info.headerlen = WriteDocumentHeaders(client, destfile, NULL, - info.timeCreatedUTC); - if (info.headerlen < 0) { - goto finish; - } - for (len = info.bodylen; len; len -= count) { + for (len = info.length; len; len -= count) { count = len < sizeof(buffer) ? len : sizeof(buffer); count = fread(buffer, sizeof(char), count, msgfile); if (!count) { @@ -1043,8 +732,14 @@ ImportIncomingMail(StoreClient *client) if (DStoreSetDocInfo(client->handle, &info)) { goto finish; } + + if (MaildirDeliverTempDocument(client, info.collection, tmppath, info.guid) != 0) + goto finish; + + // Mail is no longer in the temporary file + FindPathToDocument(client, info.collection, info.guid, tmppath, sizeof(tmppath)); - if (StoreProcessDocument(client, &info, &collinfo, path, index, 0)) { + if (StoreProcessDocument(client, &info, &collinfo, tmppath, index, 0)) { /* we were unable to process this message for some reason, so let's save it to the side and skip over it */ @@ -1065,7 +760,7 @@ ImportIncomingMail(StoreClient *client) } if (fseek(msgfile, offset, SEEK_SET) || - BongoFileCopyBytes(msgfile, failfile, sizeof(info) + info.bodylen) || + BongoFileCopyBytes(msgfile, failfile, sizeof(info) + info.length) || fseek(msgfile, newoffset, SEEK_SET)) { fclose(failfile); @@ -1076,7 +771,7 @@ ImportIncomingMail(StoreClient *client) goto finish; } - printf("Unparsable message saved in %s\n", failedPath); + Log(LOG_ERROR, "Unparsable message saved in %s", failedPath); } else { /* success! */ collinfo.imapuid = info.guid; @@ -1178,7 +873,7 @@ cleanup: StoreReleaseSharedLock(client, incLock); if (result < 0) { - printf("Unable to import mail for store %s: result %d\r\n", + Log(LOG_ERROR, "Unable to import mail for store %s: result %d", client->store, result); } @@ -1189,10 +884,7 @@ cleanup: CCode SelectUser(StoreClient *client, char *user, char *password, int nouser) { - MDBValueStruct *vs = NULL; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; CCode ccode = -1; - struct sockaddr_in serv; char buf[INET_ADDRSTRLEN+1]; if (StoreAgent.installMode) { @@ -1202,13 +894,7 @@ SelectUser(StoreClient *client, char *user, char *password, int nouser) goto finish; } - vs = MDBCreateValueStruct(StoreAgent.handle.directory, NULL); - if (!vs) { - return ConnWriteStr(client->conn, MSG5001NOMEMORY); - } - - if (!MsgFindObject(user, dn, NULL, &serv, vs)) { - XplConsolePrintf("Couldn't find user object for %s\r\n", user); + if (0 != MsgAuthFindUser(user)) { if (IS_MANAGER(client)) { ccode = ConnWriteStr(client->conn, MSG4224NOUSER); } else { @@ -1218,18 +904,14 @@ SelectUser(StoreClient *client, char *user, char *password, int nouser) goto finish; } - if (password && !MDBVerifyPassword(dn, password, vs)) { + if (password && MsgAuthVerifyPassword(user, password) != 0) { ccode = ConnWriteStr(client->conn, MSG3242BADAUTH); XplDelay(2000); goto finish; } - if (NULL == inet_ntop(serv.sin_family, &serv.sin_addr, buf, sizeof(buf))) { - ccode = ConnWriteStr(client->conn, MSG5004INTERNALERR); - goto finish; - } - -success: + // FIXME: I think we're supposed to refer to the correct store IP? + strncpy(buf, "127.0.0.1", INET_ADDRSTRLEN); ccode = ConnWriteF(client->conn, "1000 %s\r\n", buf); if (nouser) { @@ -1244,92 +926,9 @@ success: client->flags |= STORE_CLIENT_FLAG_IDENTITY; finish: - if (vs) { - MDBDestroyValueStruct(vs); - } return ccode; } - -static int -CheckJournal(DStoreHandle *handle) -{ - DStoreStmt *stmt; - uint64_t collection; - const char *filename; - int dcode; - int result = -1; - struct stat sb; - char *p; - char path[XPL_MAX_PATH + 1]; - - if (DStoreBeginTransaction(handle)) { - return -1; - } - - while (1) { - stmt = DStoreListJournal(handle); - if (!stmt) { - goto finish; - } - - dcode = DStoreJournalStmtStep(handle, stmt, &collection, &filename); - switch (dcode) { - case 0: - if (!DStoreCommitTransaction(handle)) { - result = 0; - } - goto finish; - case -1: - default: - goto finish; - case 1: - if (stat(filename, &sb)) { - if (ENOENT != errno) { - goto finish; - } - } else { - strncpy(path, filename, sizeof(path)); - p = strrchr(path, '.'); - if (!p || strcmp(".bak", p)) { - printf ("Don't know how to restore backup file %s\n", filename); - goto finish; - } - strcpy(p, ".dat"); - - if (rename(filename, path)) { - printf ("Couldn't restore backup file %s to %s\n", - filename, path); - goto finish; - } - } - - /* a bit awkward: we have to close the journal table cursor - in order to delete the current entry */ - DStoreStmtEnd(handle, stmt); - stmt = NULL; - - if (DStoreRemoveJournalEntry(handle, collection)) { - printf ("Couldn't update journal after restoring file %s\n", - filename); - goto finish; - } - } - } - -finish: - if (stmt) { - DStoreStmtEnd(handle, stmt); - } - - if (result) { - DStoreAbortTransaction(handle); - } - - return result; -} - - /* opens the store for the given user */ /* returns: -1 on error */ @@ -1356,12 +955,18 @@ SelectStore(StoreClient *client, char *user) if (!dbhandle) { return -1; } + if (DStoreCheckDBSchema(dbhandle) != 0) { + // store is either out-of-date or too new for us. + return -2; + } } +#if 0 if (CheckJournal(dbhandle)) { DStoreClose(dbhandle); return -1; } +#endif /* close the old store */ UnselectStore(client); @@ -1386,16 +991,6 @@ SelectStore(StoreClient *client, char *user) void UnselectStore(StoreClient *client) { - if (client->flags & STORE_CLIENT_FLAG_NEEDS_COMPACTING) { - CompactAllCollections(client); - client->flags &= ~STORE_CLIENT_FLAG_NEEDS_COMPACTING; - } - -/* - printf ("Stats: %d insertions, %d updates, %d deletions\n", - client->stats.insertions, client->stats.updates, client->stats.deletions); -*/ - if (client->storeName && client->stats.insertions + client->stats.updates + client->stats.deletions > (rand() % 50)) @@ -1404,7 +999,7 @@ UnselectStore(StoreClient *client) index = IndexOpen(client); if (index) { - printf("Optimizing index for store %s\n", client->storeName); + Log(LOG_DEBUG, "Optimizing index for store %s", client->storeName); IndexOptimize(index); IndexClose(index); } @@ -1428,7 +1023,7 @@ UnselectStore(StoreClient *client) { } /* block b/c we need this lock no matter what to free the client */ if (StoreWatcherRemove(client, lock)) { - printf("Internal error removing client watch"); + Log(LOG_ERROR, "Internal error removing client watch"); } StoreReleaseExclusiveLock(client, lock); @@ -1554,41 +1149,40 @@ SetParentCollectionIMAPUID(StoreClient *client, } BongoJsonResult -GetJson(StoreClient *client, DStoreDocInfo *info, BongoJsonNode **node) +GetJson(StoreClient *client, DStoreDocInfo *info, BongoJsonNode **node, char *filepath) { BongoJsonResult ret = BONGO_JSON_UNKNOWN_ERROR; char path[XPL_MAX_PATH + 1]; FILE *fh; char *buf; - FindPathToDocFile(client, info->collection, path, sizeof(path)); + if (filepath) { + strncpy(path, filepath, XPL_MAX_PATH); + } else { + FindPathToDocument(client, info->collection, info->guid, path, sizeof(path)); + } fh = fopen(path, "rb"); if (!fh) { - printf("bongostore: Couldn't open file for doc " GUID_FMT "\n", info->guid); + Log(LOG_ERROR, "Couldn't open file for doc " GUID_FMT, info->guid); goto finish; } - if (0 != XplFSeek64(fh, info->start + info->headerlen, SEEK_SET)) { - printf("bongostore: Couldn't seek to doc " GUID_FMT "\n", info->guid); - goto finish; - } - /* FIXME: would be nice (and easy) to get a streaming API for * bongojson */ - buf = MemMalloc(info->bodylen + 1); + buf = MemMalloc(info->length + 1); - if (fread(buf, 1, info->bodylen, fh) == info->bodylen) { - buf[info->bodylen] = '\0'; + if (fread(buf, 1, info->length, fh) == info->length) { + buf[info->length] = '\0'; } else { - printf("bongostore: Couldn't read doc " GUID_FMT "\n", info->guid); + Log(LOG_ERROR, "Couldn't read doc " GUID_FMT, info->guid); goto finish; } ret = BongoJsonParseString(buf, node); if (ret != BONGO_JSON_OK) { - printf("bongostore: Couldn't parse json object %s\n", buf); + Log(LOG_ERROR, "Couldn't parse json object %s", buf); } finish : diff --git a/src/agents/store/stored.c b/src/agents/store/stored.c index 5119bc9..5b90819 100644 --- a/src/agents/store/stored.c +++ b/src/agents/store/stored.c @@ -23,10 +23,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -113,23 +111,14 @@ ProcessEntry(void *clientp, static int StoreSocketInit() { - MDBValueStruct *vs; unsigned short port = BONGO_STORE_DEFAULT_PORT; - if (! StoreAgent.installMode) { - vs = MDBCreateValueStruct(StoreAgent.handle.directory, StoreAgent.server.dn); - if (vs) { - if (MDBRead(MSGSRV_AGENT_STORE, MSGSRV_A_PORT, vs) > 0) { - port = atol(vs->Value[0]); - MDBFreeValues(vs); - } - MDBDestroyValueStruct(vs); - } - } + // FIXME: previously, the port was configurable. However - we don't currently + // have a way of communicating that to Store Agents StoreAgent.nmapConn = ConnAlloc(FALSE); if (!StoreAgent.nmapConn) { - XplConsolePrintf(AGENT_NAME ": Could not allocate connection\n"); + Log(LOG_FATAL, "Could not allocate server socket"); return -1; } @@ -144,14 +133,13 @@ StoreSocketInit() StoreAgent.nmapConn->socket = ConnServerSocket(StoreAgent.nmapConn, 2048); if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongostore: Could not drop to unprivileged user '%s'\n", - MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); return -1; } if (StoreAgent.nmapConn->socket == -1) { int ret = StoreAgent.nmapConn->socket; - XplConsolePrintf("bongostore: Could not bind to port %d\n", port); + Log(LOG_ERROR, "Could not bind to port %d", port); ConnFree(StoreAgent.nmapConn); return ret; } @@ -176,25 +164,18 @@ StoreServer(void *ignored) ProcessEntry, &StoreAgent.memPool); -#if VERBOSE - /* Shutting down */ - XplConsolePrintf(AGENT_NAME ": Shutting down.\r\n"); -#endif + Log(LOG_INFO, "Shutting down."); if (StoreAgent.nmapConn) { ConnClose(StoreAgent.nmapConn, 1); StoreAgent.nmapConn = NULL; } - // StoreAgentManagementShutdown(); - BongoThreadPoolShutdown(StoreAgent.threadPool); CONN_TRACE_SHUTDOWN(); BongoAgentShutdown(&StoreAgent.agent); -#if VERBOSE - XplConsolePrintf(AGENT_NAME ": Shutdown complete\r\n"); -#endif + Log(LOG_INFO, "Shutdown complete"); } #if defined(NETWARE) || defined(LIBC) || defined(WIN32) @@ -227,9 +208,10 @@ _XplServiceMain(int argc, char *argv[]) #ifdef WIN32 XplThreadID id; #endif + LogStart(); + if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf("bongostore: Could not drop to unprivileged user '%s'\n", - MsgGetUnprivilegedUser()); + Log(LOG_ERROR, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); return -1; } @@ -243,30 +225,18 @@ _XplServiceMain(int argc, char *argv[]) } /* Initialize the Bongo libraries */ - startupOpts = BA_STARTUP_CONNIO; + startupOpts = BA_STARTUP_CONNIO | BA_STARTUP_MSGLIB | BA_STARTUP_MSGAUTH; ccode = BongoAgentInit(&StoreAgent.agent, AGENT_NAME, AGENT_DN, (30 * 60), startupOpts); if (ccode == -1) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); + Log(LOG_FATAL, "Couldn't initialize Bongo libraries"); return -1; } - if (! StoreAgent.installMode) { - if (!(StoreAgent.handle.directory = (MDBHandle)MsgInit())) { - XplBell(); - XplConsolePrintf("NMAPD: Invalid directory credentials; exiting!\r\n"); - XplBell(); - MemoryManagerClose(MSGSRV_AGENT_STORE); - return -1; - } - - MsgGetServerDN(StoreAgent.server.dn); - cal_success = BongoCalInit(MsgGetDBFDir(NULL)); - } else { - cal_success = BongoCalInit(XPL_DEFAULT_DBF_DIR); - } + MsgInit(); + cal_success = BongoCalInit(MsgGetDir(MSGAPI_DIR_DBF, NULL, 0)); if (! cal_success) { - XplConsolePrintf(AGENT_NAME ": Couldn't initialize calendaring library. Exiting.\r\n"); + Log(LOG_FATAL, "Couldn't initialize calendaring library"); return -1; } @@ -275,15 +245,13 @@ _XplServiceMain(int argc, char *argv[]) /* Create and bind the server connection */ if (StoreSocketInit() < 0) { - XplConsolePrintf(AGENT_NAME ": Exiting.\n"); + Log(LOG_FATAL, "Couldn't initialize server socket"); return -1; } /* Drop privs */ if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - XplConsolePrintf(AGENT_NAME ": Could not drop to unprivileged user '%s'\r\n" - AGENT_NAME ": exiting.\n", - MsgGetUnprivilegedUser()); + Log(LOG_FATAL, "Could not drop to unprivileged user '%s'", MsgGetUnprivilegedUser()); return -1; } @@ -298,8 +266,7 @@ _XplServiceMain(int argc, char *argv[]) if (!StoreAgent.threadPool) { BongoAgentShutdown(&StoreAgent.agent); - XplConsolePrintf(AGENT_NAME ": Unable to create thread pool.\r\n" - AGENT_NAME ": Exiting.\r\n"); + Log(LOG_FATAL, "Unable to create thread pool"); return -1; } @@ -307,12 +274,12 @@ _XplServiceMain(int argc, char *argv[]) /* setup the store guts: */ if (StoreSetupCommands()) { - XplConsolePrintf(AGENT_NAME ": Exiting.\r\n"); + Log(LOG_FATAL, "Couldn't setup Store internals"); return -1; } if (DBPoolInit()) { - XplConsolePrintf(AGENT_NAME ": Unable to create db pool. Exiting.\r\n"); + Log(LOG_FATAL, "Unable to create db pool"); return -1; } @@ -323,12 +290,12 @@ _XplServiceMain(int argc, char *argv[]) XplSignalHandler(SignalHandler); - // GenericAgentManagementStart(); - /* Start the server thread */ + MsgSetRecoveryFlag("store"); XplStartMainThread(AGENT_NAME, &id, StoreServer, 8192, NULL, ccode); XplUnloadApp(XplGetThreadID()); + MsgClearRecoveryFlag("store"); return 0; } diff --git a/src/agents/store/stored.h b/src/agents/store/stored.h index 96bce43..7637a39 100644 --- a/src/agents/store/stored.h +++ b/src/agents/store/stored.h @@ -28,8 +28,6 @@ XPL_BEGIN_C_LINKAGE #include #include -#include -#include #include #include #include @@ -38,7 +36,8 @@ XPL_BEGIN_C_LINKAGE #include #include -#define PRODUCT_SHORT_NAME "stored.nlm" +#define LOGGERNAME "store" +#include /** Store stuff: **/ @@ -50,6 +49,7 @@ XPL_BEGIN_C_LINKAGE #define STORE_INVALID_GUID 0 #define STORE_ROOT_GUID 1 #define STORE_IS_FOLDER(doctype) (doctype & STORE_DOCTYPE_FOLDER) +#define STORE_IS_DBONLY(doctype) ((doctype == STORE_DOCTYPE_CONVERSATION) || (doctype == STORE_DOCTYPE_CALENDAR)) #define STORE_IS_CONVERSATION(doctype) (doctype == STORE_DOCTYPE_CONVERSATION) typedef enum { @@ -65,9 +65,7 @@ typedef enum { typedef struct _DStoreDocInfo { uint32_t flags; int32_t type; - int64_t start; - int32_t headerlen; - int64_t bodylen; /* doclen = headerlen + bodylen */ + int64_t length; // size of the document uint32_t timeCreatedUTC; /* for imap */ uint32_t timeModifiedUTC; /* FIXME: remove this */ @@ -328,8 +326,6 @@ struct StoreGlobals { XplRWLock configLock; struct { - MDBHandle directory; - void *logging; } handle; @@ -351,7 +347,6 @@ struct StoreGlobals { unsigned long ipAddress; unsigned long bytesPerBlock; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; unsigned char host[MAXEMAILNAMESIZE + 1]; unsigned char hash[NMAP_HASH_SIZE]; } server; @@ -403,8 +398,11 @@ void UnselectUser(StoreClient *client); void UnselectStore(StoreClient *client); void DeleteStore(StoreClient *client); -void FindPathToDocFile(StoreClient *client, uint64_t collection, +void FindPathToCollection(StoreClient *client, uint64_t collection, char *dest, size_t size); +void FindPathToDocument(StoreClient *client, uint64_t collection, + uint64_t document, char *dest, size_t size); + CCode WriteDocumentHeaders(StoreClient *client, FILE *fh, const char *folder, time_t tod); @@ -427,9 +425,7 @@ int SetParentCollectionIMAPUID(StoreClient *client, DStoreDocInfo *parent, DStoreDocInfo *doc); -int StoreCompactCollection(StoreClient *client, uint64_t collection); - -BongoJsonResult GetJson(StoreClient *client, DStoreDocInfo *doc, BongoJsonNode **node); +BongoJsonResult GetJson(StoreClient *client, DStoreDocInfo *doc, BongoJsonNode **node, char *path); int StoreWatcherAdd(StoreClient *client, NLockStruct *cLock); int StoreWatcherRemove(StoreClient *client, NLockStruct *cLock); @@ -517,10 +513,6 @@ int MimeGetGuid(StoreClient *client, uint64_t guid, MimeReport **outReport); /** config.c **/ BOOL StoreAgentReadConfiguration(BOOL *recover); -/** management.c **/ -int StoreAgentManagementStart(void); -void StoreAgentManagementShutdown(void); - /* hardcoded guids: */ #define STORE_ROOT_GUID 1 diff --git a/src/agents/store/tests/Bongo.rules b/src/agents/store/tests/Bongo.rules index 36b9b17..fd04d56 100644 --- a/src/agents/store/tests/Bongo.rules +++ b/src/agents/store/tests/Bongo.rules @@ -1,17 +1,15 @@ # -*- Makefile -*- TESTS += checktest-store check_PROGRAMS += checktest-store -checktest_store_SOURCES := \ +checktest_store_SOURCES = \ src/agents/store/tests/checktest.c -checktest_store_CPPFLAGS := $(AM_CPPFLAGS) \ +checktest_store_CPPFLAGS = $(AM_CPPFLAGS) \ $(CHECK_CFLAGS) -checktest_store_LDADD := $(CHECK_LIBS) \ +checktest_store_LDADD = $(CHECK_LIBS) \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ @@ -24,17 +22,15 @@ checktest_store_LDADD := $(CHECK_LIBS) \ noinst_PROGRAMS += mkauthhash -mkauthhash_SOURCES := \ +mkauthhash_SOURCES = \ src/agents/store/tests/mkauthhash.c -mkauthhash_store_CPPFLAGS := $(AM_CPPFLAGS) \ +mkauthhash_store_CPPFLAGS = $(AM_CPPFLAGS) \ $(SQLITE_CFLAGS) mkauthhash_LDADD = \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/agents/store/tests/mkauthhash.c b/src/agents/store/tests/mkauthhash.c index d3eb787..919a81b 100644 --- a/src/agents/store/tests/mkauthhash.c +++ b/src/agents/store/tests/mkauthhash.c @@ -29,61 +29,14 @@ main (int argc, char** argv) { XplConsolePrintf("Good job, you passed the salt %s\n", argv[1]); } { + xpl_hash_context ctx; + unsigned char message[XPLHASH_MD5_LENGTH]; unsigned char access[NMAP_HASH_SIZE]; // from libs/nmap/nmap.c - MDBHandle directoryHandle; // ditto - MDBValueStruct *v; - unsigned char message[XPLHASH_MD5_LENGTH]; - xpl_hash_context ctx; - int i; - BOOL ccode; - // Initialize used libraries - if ( !MemoryManagerOpen("mkauthhash.c")) { - XplConsolePrintf("MemoryManagerOpen failed\n"); - return 1; - } else if (debugging) { - XplConsolePrintf("MemoryManagerOpen succeeded\n"); - } - if (!MDBInit()) { - XplConsolePrintf("MDBInit failed\n"); - return 2; - } else if (debugging) { - XplConsolePrintf("MDBInit suceeded\n"); - } - directoryHandle = (MDBHandle) MsgInit(); - if ( !directoryHandle ) { - XplConsolePrintf("MsgInit failed\n"); - return 3; - } else if (debugging) { - XplConsolePrintf("MsgInit succeeded\n"); - } - // compute the contents of the access field - v = MDBCreateValueStruct(directoryHandle, NULL); - if ( !v ) { - XplConsolePrintf("MDBCreateValueStruct failed\n"); - return 4; - } else if (debugging) { - XplConsolePrintf("Successfully created a MDB value struct\n"); - } - if (debugging) { - XplConsolePrintf("Retrieving the acl property:\n" - "\tMSGSRV_ROOT=<%s>\n\tMSGSRV_A_ACL=<%s>\n", MSGSRV_ROOT, MSGSRV_A_ACL); - } - MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, v); - if ( !v->Used ) { - XplConsolePrintf("Couldn't retrieve the acl property\n"); - return 5; - } else if (debugging) { - XplConsolePrintf("Retrieved the ACL property, %i bytes\n", strlen(v->Value[0]) ); - } - ccode = HashCredential(MsgGetServerDN(NULL), v->Value[0], access); - if (!ccode) { - XplConsolePrintf("HashCredential failed\n"); - return 6; - } else if (debugging) { - XplConsolePrintf("HashCredential result stored in access\n"); - } - MDBDestroyValueStruct(v); + if (!MsgGetServerCredential(access)) { + XplConsolePrintf("HashCredential failed\n"); + return 6; + } // mix access with salt XplHashNew(&ctx, XPLHASH_MD5); diff --git a/src/apps/admin/Bongo.rules b/src/apps/admin/Bongo.rules index e2c1960..479db4f 100644 --- a/src/apps/admin/Bongo.rules +++ b/src/apps/admin/Bongo.rules @@ -1,6 +1,6 @@ # -*- Makefile -*- -pkgpythonadmintooldir := $(pkgpythondir)/admintool -pkgpythonadmintool_PYTHON := \ +pkgpythonadmintooldir = $(pkgpythondir)/admintool +pkgpythonadmintool_PYTHON = \ src/apps/admin/bongo/admintool/__init__.py \ src/apps/admin/bongo/admintool/AgentCommands.py \ src/apps/admin/bongo/admintool/DemoCommands.py \ diff --git a/src/apps/admin/bongo/admintool/SetupCommands.py b/src/apps/admin/bongo/admintool/SetupCommands.py index 6813ec6..08e9c56 100644 --- a/src/apps/admin/bongo/admintool/SetupCommands.py +++ b/src/apps/admin/bongo/admintool/SetupCommands.py @@ -115,13 +115,16 @@ class SetupCredentialCommand(Command): mdb = MdbUtil.GetSetupMdb(options) passwd = Util.GeneratePassword(32) + credential = Util.GeneratePassword(4096) omask = os.umask(0077) eclients = os.path.join(Xpl.DEFAULT_DBF_DIR, "eclients.dat") + credfile = os.path.join(Xpl.DEFAULT_DBF_DIR, "credential.dat") try: os.remove(eclients) + os.remove(credfile) except os.error: pass @@ -129,14 +132,18 @@ class SetupCredentialCommand(Command): fd.write(passwd) fd.write("\0") fd.close() + + fd = open(credfile, "w") + fd.write(credential) + fd.write("\0") + fd.close() os.umask(omask) mdb.SetPassword(msgapi.GetConfigProperty(msgapi.MESSAGING_SERVER), passwd) - passwd = Util.GeneratePassword(4096) mdb.SetAttribute(msgapi.GetConfigProperty(msgapi.BONGO_SERVICES), - msgapi.A_ACL, [passwd]) + msgapi.A_ACL, [credential]) class SetupSslCommand(Command): log = logging.getLogger("bongo.admintool") diff --git a/src/apps/admin/bongoadmin.c b/src/apps/admin/bongoadmin.c index c90c735..c06dbf1 100644 --- a/src/apps/admin/bongoadmin.c +++ b/src/apps/admin/bongoadmin.c @@ -20,7 +20,6 @@ #include #include #include -#include enum BongoAdminActions { BONGO_ADMIN_ADD, diff --git a/src/apps/backup/Bongo.rules b/src/apps/backup/Bongo.rules index 218f2e6..711e1ff 100644 --- a/src/apps/backup/Bongo.rules +++ b/src/apps/backup/Bongo.rules @@ -1,17 +1,16 @@ # -*- Makefile -*- sbin_PROGRAMS += bongo-backup -bongo_backup_SOURCES := \ +bongo_backup_SOURCES = \ src/apps/backup/backup.h \ src/apps/backup/backup.c -bongo_backup_CPPFLAGS := $(AM_CPPFLAGS) \ +bongo_backup_CPPFLAGS = $(AM_CPPFLAGS) \ $(SQLITE_CFLAGS) -bongo_backup_LDADD := \ +bongo_backup_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/apps/backup/backup.c b/src/apps/backup/backup.c index a079b37..5ae4518 100644 --- a/src/apps/backup/backup.c +++ b/src/apps/backup/backup.c @@ -57,7 +57,7 @@ OpenDatabase(char *db_filename, sqlite3 **db, int create_if_absent) FILE *db_file; /* check to see if database file already exists */ - if (db_file = fopen(db_filename, "r")) { + if ((db_file = fopen(db_filename, "r"))) { if (fclose(db_file)) { if (BongoBackup.verbose) { XplConsolePrintf(_("Couldn't close file (%s)\n"), db_filename); @@ -396,7 +396,7 @@ SelectHistoricEvent(sqlite3 *db, char *guid, unsigned long date, int *event) } int -InsertHistory(sqlite3 *db, char *guid, int event, unsigned long date) +InsertHistory(sqlite3 *db, const char *guid, int event, unsigned long date) { int id = 0; char *qstr = "INSERT INTO history (history_id, guid, event, event_date) VALUES (NULL, '%s', %d, %d);"; @@ -498,7 +498,7 @@ GetConnection(char *user) /* (USER will create the account if it doesn't already exist) */ sprintf(cmd, "VRFY %s ADDR\r\n", user); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == (int)strlen(cmd)) { while (1) { code = NMAPReadAnswer(nmap, buf, sizeof(buf), TRUE); @@ -588,7 +588,6 @@ DocumentBackup(char* user_name, char* document_guid, FILE *data_file, sqlite3 *d char buf[1024]; char cmd[1024]; int code; - int qc; int history_id = 0; int last_event = DOCSTATE_UNDEFINED; @@ -613,7 +612,7 @@ DocumentBackup(char* user_name, char* document_guid, FILE *data_file, sqlite3 *d /* get all properties for this document */ sprintf((char *) cmd, "DPGET %s\r\n", document_guid); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) != strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) != (int)strlen(cmd)) { if (BongoBackup.verbose) { XplConsolePrintf(_("NMAP connection error (DPGET)\n")); } @@ -727,7 +726,7 @@ DocumentBackup(char* user_name, char* document_guid, FILE *data_file, sqlite3 *d if (document_update) { sprintf(cmd, "DREAD %s\r\n", document_guid); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) != strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) != (int)strlen(cmd)) { if (BongoBackup.verbose) { XplConsolePrintf(_("NMAP connection error (DREAD)\n")); } @@ -796,12 +795,11 @@ UserBackup(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap1, Con int code; char *document_guid; - char *tmp_db_name[256]; + char tmp_db_name[256]; sqlite3 *tmp_db; sqlite3_stmt *tmp_stmt_insert; sqlite3_stmt *tmp_stmt_select; - char *tmp_guid; sqlite3_stmt *stmt_all_docs; /* get list of user's documents */ @@ -817,7 +815,7 @@ UserBackup(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap1, Con during backup. This should help keep the backup database optimal and so that it doesn't have to manage any unnecessary data. */ - sprintf(tmp_db_name, "/tmp/bongobackup-%d.db", BongoBackup.backup_date); + sprintf(tmp_db_name, "/tmp/bongobackup-%lu.db", BongoBackup.backup_date); sqlite3_open(tmp_db_name, &tmp_db); sqlite3_exec(tmp_db, "CREATE TABLE document (document_id INTEGER PRIMARY KEY AUTOINCREMENT, guid VARCHAR(47));", NULL, NULL, NULL); sqlite3_prepare(tmp_db, "INSERT INTO document (guid) VALUES (?);", -1, &tmp_stmt_insert, 0); @@ -863,11 +861,11 @@ UserBackup(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap1, Con sqlite3_bind_int(stmt_all_docs, 2, BongoBackup.backup_date); while (sqlite3_step(stmt_all_docs) == SQLITE_ROW) { - tmp_guid = sqlite3_column_text(stmt_all_docs, 0); + const char *tmp_guid = sqlite3_column_text(stmt_all_docs, 0); sqlite3_bind_text(tmp_stmt_select, 1, tmp_guid, -1, SQLITE_STATIC); if (sqlite3_step(tmp_stmt_select) == SQLITE_OK) { - InsertHistory(db, DOCSTATE_DELETED, tmp_guid, BongoBackup.backup_date); + InsertHistory(db, tmp_guid, DOCSTATE_DELETED, BongoBackup.backup_date); } sqlite3_reset(stmt_all_docs); @@ -888,7 +886,6 @@ BackupDocument(char* user_name, char* document_guid) { int result = 1; - FILE *db_file; FILE *data_file; sqlite3 *db; Connection *nmap; @@ -897,11 +894,11 @@ BackupDocument(char* user_name, char* document_guid) sprintf(data_filename, "%s/%s%s", BongoBackup.store_path, user_name, DATA_EXT); - if (data_file = fopen(data_filename, "a")) { + if ((data_file = fopen(data_filename, "a"))) { sprintf(db_filename, "%s/%s%s", BongoBackup.store_path, user_name, DB_EXT); if (OpenDatabase(db_filename, &db, 1)) { - if (nmap = GetConnection(user_name)) { + if ((nmap = GetConnection(user_name))) { if (DocumentBackup(user_name, document_guid, data_file, db, nmap) < 0) { result = 0; } @@ -936,7 +933,6 @@ BackupUser(char* user_name) { int result = 1; - FILE *db_file; FILE *data_file; sqlite3 *db; Connection *nmap1; @@ -945,14 +941,14 @@ BackupUser(char* user_name) char data_filename[1024]; /* Try getting a connection first (just in case the user doesn't exist) */ - if (nmap1 = GetConnection(user_name)) { + if ((nmap1 = GetConnection(user_name))) { sprintf(data_filename, "%s/%s%s", BongoBackup.store_path, user_name, DATA_EXT); - if (data_file = fopen(data_filename, "a")) { + if ((data_file = fopen(data_filename, "a"))) { sprintf(db_filename, "%s/%s%s", BongoBackup.store_path, user_name, DB_EXT); if (OpenDatabase(db_filename, &db, 1)) { - if (nmap2 = GetConnection(user_name)) { + if ((nmap2 = GetConnection(user_name))) { result = UserBackup(user_name, data_file, db, nmap1, nmap2); ReleaseConnection(nmap2); } else { @@ -1003,14 +999,11 @@ DocumentRestore(char* user_name, char* document_guid, FILE *data_file, sqlite3 * int document_position; sqlite3_stmt *stmt; - char *prop_name; - char *prop_val; - int prop_length; document_resource[0] = '\0'; document_type = 0; document_length = 0; - qc = SelectDocumentInfo(db, document_guid, BongoBackup.backup_date, &document_resource, &document_type, &document_length); + qc = SelectDocumentInfo(db, document_guid, BongoBackup.backup_date, document_resource, &document_type, &document_length); if (qc > 0) { document_position = 0; @@ -1021,7 +1014,7 @@ DocumentRestore(char* user_name, char* document_guid, FILE *data_file, sqlite3 * /* resoure is non-folder */ sprintf(cmd, "DSTOR %s %d %d G%s\r\n", document_resource, document_type, document_length, document_guid); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == (int)strlen(cmd)) { while ((code = NMAPReadAnswer(nmap, buf, sizeof(buf), TRUE)) != 1000) { if (code == 2002) { if (!fseek(data_file, document_position, SEEK_SET)) { @@ -1058,7 +1051,7 @@ DocumentRestore(char* user_name, char* document_guid, FILE *data_file, sqlite3 * /* resource is a folder */ sprintf(cmd, "DCREA %s %d %s\r\n", document_resource, document_type, document_guid); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == (int)strlen(cmd)) { if ((code = NMAPReadAnswer(nmap, buf, sizeof(buf), TRUE)) != 1000) { if (BongoBackup.verbose) { XplConsolePrintf(_("Unrecognized NMAP response (DCREA): %s\n"), buf); @@ -1083,16 +1076,16 @@ DocumentRestore(char* user_name, char* document_guid, FILE *data_file, sqlite3 * sqlite3_bind_text(stmt, 3, document_guid, -1, SQLITE_STATIC); while ((qc = sqlite3_step(stmt)) == SQLITE_ROW) { - prop_name = sqlite3_column_text(stmt, 1); - prop_val = sqlite3_column_text(stmt, 2); - prop_length = strlen(prop_val); + const char *prop_name = sqlite3_column_text(stmt, 1); + const char *prop_val = sqlite3_column_text(stmt, 2); + int prop_length = strlen(prop_val); if (strcmp(prop_name, "nmap.resource") && strcmp(prop_name, "nmap.type") && strcmp(prop_name, "nmap.length") && strcmp(prop_name, "nmap.guid")) { sprintf(cmd, "DPSET %s %d\r\n", prop_name, prop_length); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == (int)strlen(cmd)) { while ((code = NMAPReadAnswer(nmap, buf, sizeof(buf), TRUE)) != 1000) { if (code == 2002) { if (ConnWrite(nmap, prop_val, prop_length) != prop_length) { @@ -1210,7 +1203,7 @@ UserRestore(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap) /* DPGET for named properties not currently implemented in NMAP */ sprintf(cmd, "DPGET %s nmap.modified\r\n", document_guid); - if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == strlen(cmd)) { + if (NMAPSendCommand(nmap, cmd, strlen(cmd)) == (int)strlen(cmd)) { if ((code = NMAPReadAnswer(nmap, buf, sizeof(buf), TRUE)) == 2001) { if ((property_name = strchr(buf, ' ')) == '\0') { if (BongoBackup.verbose) { @@ -1285,8 +1278,8 @@ RestoreDocument(char* user_name, char* document_guid) if (OpenDatabase(db_filename, &db, 0)) { sprintf(data_filename, "%s/%s%s", BongoBackup.store_path, user_name, DATA_EXT); - if (data_file = fopen(data_filename, "r")) { - if (nmap = GetConnection(user_name)) { + if ((data_file = fopen(data_filename, "r"))) { + if ((nmap = GetConnection(user_name))) { if (DocumentRestore(user_name, document_guid, data_file, db, nmap) < 0) { result = 0; } @@ -1331,8 +1324,8 @@ RestoreUser(char* user_name) if (OpenDatabase(db_filename, &db, 0)) { sprintf(data_filename, "%s/%s%s", BongoBackup.store_path, user_name, DATA_EXT); - if (data_file = fopen(data_filename, "r")) { - if (nmap = GetConnection(user_name)) { + if ((data_file = fopen(data_filename, "r"))) { + if ((nmap = GetConnection(user_name))) { result = UserRestore(user_name, data_file, db, nmap); ReleaseConnection(nmap); } else { @@ -1376,8 +1369,6 @@ RestoreUser(char* user_name) int SearchStore(char **strings, char **users, char **types, unsigned long before, unsigned long after, char **guids) { - int rval = 1; - if (!users) { /* full user search */ } else { @@ -1415,15 +1406,11 @@ main(int argc, char *argv[]) int j; Connection *nmap; char buf[1024]; - char cmd[1024]; int code; int no_err = 1; int command = 0; - int count_docs = 0; - int temp_count = 0; - int next_arg = 0; char *arg_ptr = NULL; struct stat stat_buf; @@ -1553,7 +1540,7 @@ main(int argc, char *argv[]) XplConsolePrintf(_("Backing up data\n")); if (ConnStartup((300), FALSE)) { - if (nmap = GetConnection(NULL)) { + if ((nmap = GetConnection(NULL))) { if (next_backup_arg < 1) { /* full backup */ NMAPSendCommand(nmap, "ULIST\r\n", 7); @@ -1610,7 +1597,7 @@ main(int argc, char *argv[]) if (ConnStartup((300), FALSE)) { if (next_backup_arg < 1) { /* full restore */ - if (store_dir = opendir(BongoBackup.store_path)) { + if ((store_dir = opendir(BongoBackup.store_path))) { while (no_err && (d_ent = readdir(store_dir))) { if ((d_ptr = strchr(d_ent->d_name, '.')) != '\0') { *d_ptr++ = '\0'; diff --git a/src/apps/backup/backup.h b/src/apps/backup/backup.h index 09aeaf0..3a66af0 100644 --- a/src/apps/backup/backup.h +++ b/src/apps/backup/backup.h @@ -48,4 +48,27 @@ typedef struct { int next_guid; } BackupArg; -#endif \ No newline at end of file +int OpenDatabase(char *db_filename, sqlite3 **db, int create_if_absent); +int CloseDatabase(sqlite3 *db); +int SelectPropertyValue(sqlite3 *db, char *guid, char *property, unsigned long date, char **value); +int SelectDocumentAttributes(sqlite3 *db, char *guid, unsigned long date, int *len, int *pos); +int SelectDocumentInfo(sqlite3 *db, char *guid, unsigned long date, char *resource, int *type, int *length); +int SelectHistoricEvent(sqlite3 *db, char *guid, unsigned long date, int *event); +int InsertHistory(sqlite3 *db, const char *guid, int event, unsigned long date); +int InsertProperty(sqlite3 *db, int history, char *property, char *value); +int InsertDocument(sqlite3 *db, int history, int length, int position); +Connection *GetConnection(char *user); +void ReleaseConnection(Connection *nmap); +int DocumentBackup(char* user_name, char* document_guid, FILE *data_file, sqlite3 *db, Connection *nmap); +int UserBackup(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap1, Connection *nmap2); +int BackupDocument(char* user_name, char* document_guid); +int BackupUser(char* user_name); +int DocumentRestore(char* user_name, char* document_guid, FILE *data_file, sqlite3 *db, Connection *nmap); +int UserRestore(char* user_name, FILE *data_file, sqlite3 *db, Connection *nmap); +int RestoreDocument(char* user_name, char* document_guid); +int RestoreUser(char* user_name); +int SearchStore(char **strings, char **users, char **types, unsigned long before, unsigned long after, char **guids); +int RollbackStore(unsigned long date); + + +#endif diff --git a/src/apps/config/Bongo.rules b/src/apps/config/Bongo.rules index 32a3b70..8c43762 100644 --- a/src/apps/config/Bongo.rules +++ b/src/apps/config/Bongo.rules @@ -1,20 +1,29 @@ # -*- Makefile -*- sbin_PROGRAMS += bongo-config -conf_defaults = \ - src/apps/config/config/manager \ - src/apps/config/config/antivirus \ - src/apps/config/config/antispam +conf_defaults = \ + src/apps/config/config/global \ + src/apps/config/config/aliases/default_config \ + src/apps/config/config/antispam \ + src/apps/config/config/antivirus \ + src/apps/config/config/imap \ + src/apps/config/config/mailproxy \ + src/apps/config/config/manager \ + src/apps/config/config/pop3 \ + src/apps/config/config/queue \ + src/apps/config/config/smtp \ + src/apps/config/hawkeye/history -bongo_config_SOURCES := \ +bongo_config_SOURCES = \ $(conf_defaults) \ + src/apps/config/config.c \ src/apps/config/config.h \ - src/apps/config/config.c + src/apps/config/store.c -bongo_config_CPPFLAGS := $(AM_CPPFLAGS) \ +bongo_config_CPPFLAGS = $(AM_CPPFLAGS) \ $(GNUTLS_CFLAGS) -bongo_config_LDADD := \ +bongo_config_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ libbongoconnio.la \ @@ -27,11 +36,11 @@ bongo_config_LDADD := \ confdir = $(pkgdatadir)/conf -conf_DATA := \ +conf_DATA = \ src/apps/config/default.set src/apps/config/default.set: $(conf_defaults) - @(cd $(top_srcdir)/src/apps/config && tardir=config && $(am__tar)) > $@ + (cd $(top_srcdir)/src/apps/config && tar chof - --exclude .svn config hawkeye) > $@ src/apps/config/all: bongo-config src/apps/config/clean: clean diff --git a/src/apps/config/config.c b/src/apps/config/config.c index f547c83..253616b 100644 --- a/src/apps/config/config.c +++ b/src/apps/config/config.c @@ -9,12 +9,13 @@ #include #include #include + #include + #include #include #include #include -#include #include #include #include "config.h" @@ -33,9 +34,12 @@ usage(void) { " -v, --verbose verbose output\n" " -s, --silent non-interactive mode\n\n" "Commands:\n" + " user add add a user to the systen\n" + " user list list the users on the system\n" + " user password set the password of a user\n" " install do the initial Bongo install\n" " crypto regenerate data needed for encryption\n" - " checkversion see if a newer Bongo is available\n" + " checkversion see if a newer Bongo is available\n" " tzcache regenerate cached timezone information\n" ""; @@ -43,154 +47,167 @@ usage(void) { } void -RunAsBongoUser() { - if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { - printf(_("bongo-config: Could not drop to unpriviliged user '%s'\n"), MsgGetUnprivilegedUser()); +RunAsBongoUser() +{ + if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { + printf(_("bongo-config: Could not drop to unprivileged user '%s'\n"), MsgGetUnprivilegedUser()); exit(-1); } } -BOOL -NMAPSimpleCommand(StoreClient *client, char *command) { - CCode ccode; - - NMAPSendCommandF(client->conn, command); - ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); - if (1000 == ccode) - return TRUE; - - return FALSE; -} - -BOOL -SetAdminRights(StoreClient *client, char *document) { - CCode ccode; - char *rights = "grant user:admin all;"; - - ccode = NMAPRunCommandF(client->conn, client->buffer, sizeof(client->buffer), - "PROPSET %s nmap.access-control %d\r\n", document, strlen(rights)); - if (ccode == 2002) { - NMAPSendCommandF(client->conn, rights); - ccode = NMAPReadAnswer(client->conn, client->buffer, - sizeof(client->buffer), TRUE); - if (ccode == 1000) - return TRUE; - } - return FALSE; -} - -BOOL -PutOrReplaceConfig(StoreClient *client, char *collection, char *filename, char *content, long len) { - CCode ccode; - char command[1024]; - - snprintf(command, 1000, "INFO %s/%s\r\n", collection, filename); - ccode = NMAPSendCommandF(client->conn, command); - ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); - while (ccode == 2001) - ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); - - if (ccode == 1000) { - // INFO returned OK, document already exists - snprintf(command, 1000, "REPLACE %s/%s %ld\r\n", - collection, filename, len); - } else { - // INFO errored, so document doesn't exist - snprintf(command, 1000, "WRITE %s %d %ld \"F%s\"\r\n", - collection, STORE_DOCTYPE_CONFIG, len, filename); - } - - NMAPSendCommandF(client->conn, command); - ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); - - if (ccode == 2002) { - ConnWrite(client->conn, content, len); - ConnFlush(client->conn); - if (NMAPReadAnswer(client->conn, client->buffer, - sizeof(client->buffer), TRUE) == 1000) { - return TRUE; - } - XplConsolePrintf(_("ERROR: Couldn't write data\n")); - } else { - XplConsolePrintf(_("ERROR: Wouldn't accept data\n")); - } - return FALSE; -} - -BOOL -ImportSystemBackupFile(const StoreClient *client, const char *path) +void +RunAsRoot() { - FILE *config; - char header[513]; - CCode result; - - result = NMAPSimpleCommand(client, "CREATE /config\r\n"); - if ((result==1000) || (result==4226)) { - // collection can't be created and doesn't exist - XplConsolePrintf(_("ERROR: Couldn't create collection\n")); - return FALSE; + if (XplSetEffectiveUserId(0) < 0) { + XplConsolePrintf(_("bongo-config: Couldn't get back root privs.\n")); } - if (! SetAdminRights(client, "/config")) { - XplConsolePrintf(_("ERROR: Couldn't set acls on /config\n")); - return FALSE; - } - - config = fopen(path, "r"); - if (config == NULL) { - XplConsolePrintf(_("ERROR: Couldn't load default config set\n")); - return FALSE; - } - while(512 == fread(&header, sizeof(char), 512, config)) { - long filesize, blocksize, read; - char str_filesize[13], filename[101]; - char *file; - header[512] = 0; - - memcpy(&filename, &header, 100); - filename[100] = 0; - memcpy(&str_filesize, &header[124], 12); - str_filesize[12] = 0; - filesize = strtol(str_filesize, NULL, 8); - - if (! strncmp(filename, "", 100)) { - // end of tar is _two_ empty blocks... ah well :o> - break; - } - - blocksize = filesize / 512; - if (filesize % 512) blocksize++; - blocksize *= 512; - - if (blocksize > 0 && !strncmp(filename, "config/", 7)) { - char fullpath[110]; - file = MemMalloc((size_t) blocksize); - read = fread(file, sizeof(char), blocksize, config); - if (read != blocksize) { - XplConsolePrintf(" Read error!"); - } - - snprintf(fullpath, 108, "/%s", filename); - if (!PutOrReplaceConfig(client, "/config", - &filename[7], file, filesize)) { - XplConsolePrintf(_("ERROR: Couldn't write\n")); - } else { - if (! SetAdminRights(client, fullpath)) { - XplConsolePrintf(_("ERROR: rigts\n")); - } - } - MemFree(file); - } - } - - fclose(config); - return TRUE; } void -InitialStoreConfiguration() { - char path[XPL_MAX_PATH]; - int store_pid; - char *args[3]; +AddDomain(const char *str) { + BongoJsonNode *domain; + + domain = BongoJsonNodeNewString(str); + BongoArrayAppendValue(BongoJsonNodeAsArray(config.domains), domain); +} + +void +GetInstallParameters(void){ + char *tmp = NULL; + + GetInteractiveData(_("IP address to run on"), &config.ip, "127.0.0.1"); + GetInteractiveData(_("DNS name to use as main hostname:"), &config.dns, "localhost"); + + /* this is a little messy here due to the way the array works */ + if (!config.domains) { + config.domains = BongoJsonNodeNewArray(BongoArrayNew(sizeof(char *), 1)); + while (1) { + GetInteractiveData(_("Mail Domains (enter \"\" to end adding domains):"), &tmp, ""); + if (tmp[0] == '\0') { + tmp = NULL; + break; + } + + AddDomain(tmp); + tmp = NULL; + } + } +} + +void +SetStoreConfigurationModifications(StoreClient *client) { + BongoJsonNode *node; + unsigned char *aconfig = NULL; + unsigned char *default_config = NULL; + unsigned int default_config_len; + /* + * unsigned char default_config[] = "{ \"domainalias\" : \"\", \"aliases\" : { \"postmaster\" : \"admin\" }, \"username-mapping\" : 0 }"; + const unsigned int default_config_len = strlen(default_config); + + */ + + NMAPReadConfigFile("aliases/default_config", &default_config); + if (default_config == NULL) return; + default_config_len = strlen(default_config); + + /* first let's read in the queue document and store out the domains and hosted domains */ + if(NMAPReadConfigFile("queue", &aconfig)) { + if (aconfig == NULL) return; + if (BongoJsonParseString(aconfig, &node) == BONGO_JSON_OK) { + BongoJsonNode *current; + char *content; + unsigned int x; + BongoArray *domains; + + current = BongoJsonJPath(node, "o:domains/a"); + domains = BongoJsonNodeAsArray(config.domains); + /* free the old array */ + BongoArrayDestroy(BongoJsonNodeAsArray(current), TRUE); + BongoJsonNodeAsArray(current) = domains; + + content = BongoJsonNodeToString(node); + PutOrReplaceConfig(client, "/config", "queue", content, strlen(content)); + + /* add the default configuration document for each domain */ + for(x=0;xlen;x++) { + BongoJsonNode *current = BongoJsonArrayGet(domains, x); + PutOrReplaceConfig(client, "/config/aliases", BongoJsonNodeAsString(current), default_config, default_config_len); + } + BongoJsonNodeFree(node); + } + MemFree(aconfig); + aconfig = NULL; + } + + /* now store out the global file changes */ + if (NMAPReadConfigFile("global", &aconfig)) { + if (aconfig == NULL) return; + if (BongoJsonParseString(aconfig, &node) == BONGO_JSON_OK) { + char *content; + BongoJsonNode *current; + + current = BongoJsonJPath(node, "o:hostname/s"); + MemFree(BongoJsonNodeAsString(current)); + BongoJsonNodeAsString(current) = MemStrdup(config.dns); + + current = BongoJsonJPath(node, "o:hostaddr/s"); + MemFree(BongoJsonNodeAsString(current)); + BongoJsonNodeAsString(current) = MemStrdup(config.ip); + + current = BongoJsonJPath(node, "o:postmaster/s"); + MemFree(BongoJsonNodeAsString(current)); + BongoJsonNodeAsString(current) = MemStrdup("admin"); + + content = BongoJsonNodeToString(node); + PutOrReplaceConfig(client, "/config", "global", content, strlen(content)); + + BongoJsonNodeFree(node); + } + MemFree(aconfig); + aconfig = NULL; + } +} + +void +InitializeDataArea(void) +{ + MsgApiDirectory dir; + const unsigned char *unpriv_user; + uid_t uid = 0; + gid_t gid = 0; + + unpriv_user = MsgGetUnprivilegedUser(); + if (unpriv_user != NULL) + XplLookupUser(unpriv_user, &uid, &gid); + + XplConsolePrintf(_("Creating directory structure...\n")); + for (dir = MSGAPI_DIR_START; dir < MSGAPI_DIR_END; dir++) { + char path[XPL_MAX_PATH]; + if (MsgGetDir(dir, path, XPL_MAX_PATH)) { + MsgMakePath(path); + chown(path, uid, gid); + } + } + + RunAsBongoUser(); + + XplConsolePrintf(_("Initializing user database...\n")); + if (MsgAuthInit() != 0) { + XplConsolePrintf(_("ERROR: Couldn't initialise auth subsystem\n")); + exit(1); + } + if (MsgAuthInstall() != 0) { + XplConsolePrintf(_("Warning: Couldn't create user database\n")); + } + + if (!MsgSetServerCredential()) { + XplConsolePrintf(_("ERROR: Cannot create server credential\n")); + exit(2); + } +} + +void +InitialStoreConfiguration(void) { BOOL cal_success; // attempt to initialise cal lib. This creates cached data, and can be time @@ -202,7 +219,17 @@ InitialStoreConfiguration() { exit(1); } - XplConsolePrintf(_("Initializing store...\n")); + XplConsolePrintf(_("Loading initial store configuration...\n")); + LoadDefaultStoreConfiguration(); +} + +void +LoadDefaultStoreConfiguration(void) +{ + char path[XPL_MAX_PATH]; + int store_pid; + char *args[3]; + store_pid = fork(); if (store_pid == 0) { // child static char *install = "--install"; @@ -250,6 +277,7 @@ InitialStoreConfiguration() { XplConsolePrintf(_("Complete.\n")); } + SetStoreConfigurationModifications(client); nmapcleanup: NMAPQuit(client->conn); ConnFree(client->conn); @@ -272,10 +300,13 @@ GetInteractiveData(char *description, char **data, char *def) { XplConsolePrintf("%s [%s]: ", description, def); *data = (char *)MemMalloc(sizeof(char)*size); line = fgets(*data, size, stdin); - if (!line || *line == '\0') { + if (!line || *line == '\0' || *line == '\n' || *line == '\r') { MemFree(*data); - *data = def; + *data = MemStrdup(def); } + + size = strlen(line); + if (line[size-1] == '\n') line[size-1] = 0; } #define CERTSIZE 10240 @@ -305,9 +336,6 @@ GenerateCryptoData() { XplConsolePrintf(_("Couldn't create data directory!\n")); } - GetInteractiveData(_("IP address to run on"), &config.ip, "127.0.0.1"); - GetInteractiveData(_("DNS name to use:"), &config.dns, "localhost"); - // save a random seed for faster Xpl startup in future. XplConsolePrintf(_("Creating random seed...\n")); XplSaveRandomSeed(); @@ -430,30 +458,65 @@ GenerateCryptoData() { gnutls_x509_crt_deinit(certificate); gnutls_x509_privkey_deinit(key); - MemFree(config.ip); - MemFree(config.dns); - return TRUE; } void CheckVersion() { - int current_version, available_version; + int current_version, available_version; BOOL custom_version; - if (!MsgGetBuildVersion(¤t_version, &custom_version)) { - printf(_("Can't get information on current build!\n")); + XplConsolePrintf(_("Can't get information on current build!\n")); return; } else { - printf(_("Installed build: %s %s%d\n"), BONGO_BUILD_BRANCH, BONGO_BUILD_VSTR, current_version); + XplConsolePrintf(_("Installed build: %s %s%d\n"), BONGO_BUILD_BRANCH, BONGO_BUILD_VSTR, current_version); if (custom_version) - printf(_("This is modified software.\n")); + XplConsolePrintf(_("This is modified software.\n")); } if (!MsgGetAvailableVersion(&available_version)) { - printf(_("Version currently available: unable to request online information.\n")); + XplConsolePrintf(_("Version currently available: unable to request online information.\n")); } else { - printf(_("Version currently available: %s%d\n"), BONGO_BUILD_VSTR, available_version); + XplConsolePrintf(_("Version currently available: %s%d\n"), BONGO_BUILD_VSTR, available_version); + } +} + +void +UserAdd(const char *username) +{ + if (MsgAuthAddUser(username) == 0) { + XplConsolePrintf(_("Added user %s\n"), username); + } else { + XplConsolePrintf(_("Couldn't add user %s\n"), username); + } +} + +void +UserList(void) +{ + // TODO +} + +void +UserPassword(const char *username) +{ + char *password = NULL; + char *password2 = NULL; + + GetInteractiveData(_("New password for the user"), &password, ""); + GetInteractiveData(_("Confirm the password"), &password2, ""); + + if (strlen(password) == 0) { + XplConsolePrintf(_("ERROR: Can't set password to empty string.\n")); + return; + } + if (strncmp(password, password2, strlen(password))) { + XplConsolePrintf(_("ERROR: The passwords provided don't match.\n")); + return; + } + + if (MsgAuthSetPassword(username, password) != 0) { + XplConsolePrintf(_("ERROR: Couldn't set the password for the user.\n")); } } @@ -476,6 +539,9 @@ main(int argc, char *argv[]) { BongoAgent configtool; config.verbose = 0; + /* this just clears up a warning. we don't need this here */ + GlobalConfig[0].type = BONGO_JSON_NULL; + if (!MemoryManagerOpen("bongo-config")) { XplConsolePrintf("ERROR: Failed to initialize memory manager\n"); return 1; @@ -491,9 +557,15 @@ main(int argc, char *argv[]) { } else if (!strcmp(arg, "--ip")) { next_arg++; config.ip = MemStrdup(argv[next_arg]); - } else if (!strcmp(arg, "--domain")) { + } else if (!strcmp(arg, "--hostname")) { next_arg++; config.dns = MemStrdup(argv[next_arg]); + } else if (!strcmp(arg, "--domain")) { + if (!config.domains) { + config.domains = BongoJsonNodeNewArray(BongoArrayNew(sizeof(char *), 1)); + } + next_arg++; + AddDomain(argv[next_arg]); } else { printf("Unrecognized option: %s\n", argv[next_arg]); } @@ -509,6 +581,8 @@ main(int argc, char *argv[]) { command = 3; } else if (!strcmp(argv[next_arg], "tzcache")) { command = 4; + } else if (!strcmp(argv[next_arg], "user")) { + command = 5; } else { printf("Unrecognized command: %s\n", argv[next_arg]); } @@ -519,42 +593,79 @@ main(int argc, char *argv[]) { } // unusual libgcrypt options must occur before XplInit() - if (command == 2) { + if ((command == 2) || (command == 1)) { gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); } XplInit(); // we don't want to setup libraries unless we need to (e.g., to run an agent) if (command == 1) { - startup = BA_STARTUP_CONNIO; + startup = BA_STARTUP_CONNIO; if (-1 == BongoAgentInit(&configtool, "bongoconfig", "", DEFAULT_CONNECTION_TIMEOUT, startup)) { XplConsolePrintf(_("ERROR : Couldn't initialize Bongo libraries\n")); return 2; } } - // don't give away privileges if we're going to need them later. - if (command != 1) { - RunAsBongoUser(); - } - + next_arg++; switch(command) { case 1: + GetInstallParameters(); + InitializeDataArea(); // changes our user to unprivileged + GenerateCryptoData(); + RunAsRoot(); InitialStoreConfiguration(); break; case 2: + RunAsBongoUser(); GenerateCryptoData(); break; - case 3: + case 3: + RunAsBongoUser(); CheckVersion(); break; case 4: + RunAsBongoUser(); TzCache(); break; + case 5: + if (MsgAuthInit()) { + XplConsolePrintf(_("Couldn't initialise auth subsystem\n")); + return 3; + } + if ((next_arg + 1) >= argc) { + XplConsolePrintf(_("USAGE : user [add|password] \n")); + } else { + char *command = argv[next_arg++]; + char *username = argv[next_arg]; + + if (! strncmp(command, "add", 3)) { + UserAdd(username); + } else if (!strncmp(command, "password", 8)) { + UserPassword(username); + } else if (!strncmp(command, "list", 4)) { + UserList(); + } else { + XplConsolePrintf(_("ERROR: Unknown command '%s' on user\n"), command); + } + } + break; default: break; } + if (config.ip) { + MemFree(config.ip); + } + + if (config.dns) { + MemFree(config.dns); + } + + if (config.domains) { + BongoJsonNodeFree(config.domains); + } + MemoryManagerClose("bongo-config"); exit(0); } diff --git a/src/apps/config/config.h b/src/apps/config/config.h index 9d3c16f..319ee77 100644 --- a/src/apps/config/config.h +++ b/src/apps/config/config.h @@ -12,6 +12,7 @@ typedef struct { BOOL interactive; char *ip; char *dns; + BongoJsonNode *domains; } BongoConfig; typedef struct { @@ -24,17 +25,32 @@ typedef struct { /* function prototypes */ +// config.c +void GetInstallParameters(void); +void AddDomain(const char *str); +void SetStoreConfigurationModifications(StoreClient *client); +void LoadDefaultStoreConfiguration(void); +void InitializeDataArea(void); void usage(void); void RunAsBongoUser(void); -BOOL NMAPSimpleCommand(StoreClient *client, char *command); -BOOL SetAdminRights(StoreClient *client, char *document); -BOOL PutOrReplaceConfig(StoreClient *client, char *collection, char *filename, char *content, long len); +void RunAsRoot(void); void InitialStoreConfiguration(void); void GetInteractiveData(char *description, char **data, char *def); BOOL GenerateCryptoData(void); void CheckVersion(void); +void AddUser(const char *username); void TzCache(void); +void UserAdd(const char *username); +void UserList(void); +void UserPassword(const char *username); + +// store.c +BOOL ImportSystemBackupFile(StoreClient *client, const char *path); +BOOL NMAPSimpleCommand(StoreClient *client, char *command); +BOOL SetAdminRights(StoreClient *client, char *document); +BOOL PutOrReplaceConfig(StoreClient *client, char *collection, char *filename, char *content, long len); + /* compat with older gnutls */ #ifndef GNUTLS_DIG_SHA1 // older GNUTLS diff --git a/src/apps/config/config/aliases/default_config b/src/apps/config/config/aliases/default_config new file mode 100644 index 0000000..488e5f9 --- /dev/null +++ b/src/apps/config/config/aliases/default_config @@ -0,0 +1,7 @@ +{ + "domainalias" : "", + "aliases" : { + "postmaster" : "admin" + }, + "username-mapping" : 0 +} diff --git a/src/apps/config/config/antivirus b/src/apps/config/config/antivirus index dcecc49..c93bb3f 100644 --- a/src/apps/config/config/antivirus +++ b/src/apps/config/config/antivirus @@ -1,8 +1,8 @@ { - "version": 1, - "flags": 168, - "patterns": "", - "queue": 5, - "host": "127.0.0.1", - "port": 3310 + "version": 1, + "flags": 168, + "patterns": "", + "queue": 5, + "hosts": [ "127.0.0.1:3310:1" ], + "timeout": 15 } diff --git a/src/apps/config/config/global b/src/apps/config/config/global new file mode 100644 index 0000000..36c9958 --- /dev/null +++ b/src/apps/config/config/global @@ -0,0 +1,5 @@ +{ + "hostname": "localhost", + "hostaddr": "127.0.0.1", + "postmaster": "admin" +} diff --git a/src/apps/config/config/imap b/src/apps/config/config/imap new file mode 100644 index 0000000..6e506b3 --- /dev/null +++ b/src/apps/config/config/imap @@ -0,0 +1,6 @@ +{ + "version": 1, + "port": 143, + "port_ssl": 993, + "threads_max": 50 +} diff --git a/src/apps/config/config/mailproxy b/src/apps/config/config/mailproxy new file mode 100644 index 0000000..8152510 --- /dev/null +++ b/src/apps/config/config/mailproxy @@ -0,0 +1,7 @@ +{ + "version": 1, + "interval": 3600, + "queue": "localhost", + "max_threads": 10, + "max_accounts": 3 +} diff --git a/src/apps/config/config/manager b/src/apps/config/config/manager index 9508bec..de68d6c 100644 --- a/src/apps/config/config/manager +++ b/src/apps/config/config/manager @@ -1,23 +1,16 @@ -/* bongo manager config is an object. One key should be 'agents', whose value - * is an array of agent objects. Agent objects can have names, pri (priority) - * and be enabled. Priorities are roughly in terms of dependency and/or which - * order we want things to start in. Low pri == important, high pri == do this - * last. - */ - { "version": 1, "agents": [ - { "name": "bongoqueue", "pri": 3, "enabled": true }, - { "name": "bongosmtp", "pri": 3, "enabled": true }, + { "name": "bongoqueue", "pri": 1, "enabled": true }, + { "name": "bongosmtp", "pri": 10, "enabled": true }, { "name": "bongoantispam", "pri": 5, "enabled": true }, { "name": "bongoavirus", "pri": 5, "enabled": true }, { "name": "bongocollector", "pri": 7, "enabled": true }, - { "name": "bongomailprox", "pri": 7, "enabled": true }, - { "name": "bongoconnmgr", "pri": 2, "enabled": true }, - { "name": "bongopluspack", "pri": 5, "enabled": true }, - { "name": "bongorules", "pri": 2, "enabled": true }, + { "name": "bongomailprox", "pri": 7, "enabled": false }, + { "name": "bongopluspack", "pri": 5, "enabled": false }, + { "name": "bongorules", "pri": 5, "enabled": false }, { "name": "bongoimap", "pri": 10, "enabled": true }, { "name": "bongopop3", "pri": 10, "enabled": true }, - { "name": "bongocalcmd", "pri": 7, "enabled": true } + { "name": "bongocalcmd", "pri": 7, "enabled": true }, + { "name": "bongo-standalone", "pri": 10, "enabled": true } ] } diff --git a/src/apps/config/config/pop3 b/src/apps/config/config/pop3 new file mode 100644 index 0000000..7323d8d --- /dev/null +++ b/src/apps/config/config/pop3 @@ -0,0 +1,5 @@ +{ + "version": 1, + "port": 110, + "port_ssl": 995 +} diff --git a/src/apps/config/config/queue b/src/apps/config/config/queue new file mode 100644 index 0000000..824a773 --- /dev/null +++ b/src/apps/config/config/queue @@ -0,0 +1,29 @@ +{ + "version": 1, + "debug" : false, + "limitremoteprocessing" : false, + "limitremotebegweekday" : 0, + "limitremotebegweekend" : 0, + "limitremoteendweekday" : 0, + "limitremoteendweekend" : 0, + "queuetuning_concurrent" : 250, + "queuetuning_sequential" : 500, + "queuetuning_load_high" : 0, + "queuetuning_load_low" : 0, + "queuetuning_trigger" : 0, + "queuetimeout" : 345600, + "quotamessage" : "", + "port" : 8670, + "forwardundeliverable_enabled" : false, + "forwardundeliverable_to" : "", + "queueinterval" : 10, + "minimumfreespace" : 5242880, + "trustedhosts" : [], + "hosteddomains" : [], + "domains" : [], + "rtsantispamconfig_enabled" : false, + "rtsantispamconfig_delay" : 0, + "rtsantispamconfig_threshold" : 0, + "bouncereturn" : true, + "bounceccpostmaster" : false +} diff --git a/src/apps/config/config/smtp b/src/apps/config/config/smtp new file mode 100644 index 0000000..9d85bad --- /dev/null +++ b/src/apps/config/config/smtp @@ -0,0 +1,24 @@ +{ + "version": 1, + "port": 25, + "port_ssl": 465, + "allow_client_ssl": false, + "allow_expn": false, + "allow_auth": true, + "allow_vrfy": true, + "verify_address" : true, + "accept_etrn": false, + "send_etrn": false, + "maximum_recipients": 15, + "message_size_limit": 0, + "relay_local_mail": false, + "use_relay_host": false, + "relay_host": "", + "block_rts_spam": true, + "max_thread_load": 10000, + "max_flood_count": 1000, + "max_null_sender": 10, + "socket_timeout": 600, + "max_mx_servers": 20, + "require_auth": true +} diff --git a/src/apps/config/hawkeye/history b/src/apps/config/hawkeye/history new file mode 100644 index 0000000..1c1ccbe --- /dev/null +++ b/src/apps/config/hawkeye/history @@ -0,0 +1,7 @@ +{ + "0" : { "desc": "Installed Bongo.", "url": "" }, + "1" : { "desc": "", "url": "" }, + "2" : { "desc": "", "url": "" }, + "3" : { "desc": "", "url": "" }, + "4" : { "desc": "", "url": "" } +} diff --git a/src/apps/config/store.c b/src/apps/config/store.c new file mode 100644 index 0000000..156d5b0 --- /dev/null +++ b/src/apps/config/store.c @@ -0,0 +1,166 @@ +// Load / save backup sets from the Store + +#include +#include +#include +#include +#include +#include "config.h" + +#include +#define _(x) gettext(x) + +BOOL +ImportSystemBackupFile(StoreClient *client, const char *path) +{ + FILE *config; + char header[513]; + CCode result; + + config = fopen(path, "r"); + if (config == NULL) { + XplConsolePrintf(_("ERROR: Couldn't load default config set\n")); + return FALSE; + } + while(512 == fread(&header, sizeof(char), 512, config)) { + long filesize, blocksize, read; + size_t len; + char str_filesize[13], filename[101]; + char *file; + header[512] = 0; + + memcpy(&filename, &header, 100); + filename[100] = 0; + memcpy(&str_filesize, &header[124], 12); + str_filesize[12] = 0; + filesize = strtol(str_filesize, NULL, 8); + len = strlen(filename); + + if (! strncmp(filename, "", 100)) { + // end of tar is _two_ empty blocks... ah well :o> + break; + } + + blocksize = filesize / 512; + if (filesize % 512) blocksize++; + blocksize *= 512; + + /* if this is a directory we need to create a new collection */ + if (filename[len-1] == '/') { + char currentpath[110]; + char fullpath[110]; + + filename[len-1] = 0; + + snprintf(currentpath, 100, "/%s", filename); + snprintf(fullpath, 108, "CREATE %s\r\n", currentpath); + result = NMAPSimpleCommand(client, fullpath); + + if ((result==1000) || (result==4226)) { + // collection can't be created and doesn't exist + XplConsolePrintf(_("ERROR: Couldn't create collection: %s\n"), currentpath); + return FALSE; + } + if (! SetAdminRights(client, currentpath)) { + XplConsolePrintf(_("ERROR: Couldn't set acls on %s\n"), currentpath); + return FALSE; + } + continue; + } + + /* now, do everything else that isn't a directory and contains data */ + if (blocksize > 0 && filename[len-1] != '/') { + char fullpath[110]; + char *delim; + + file = MemMalloc((size_t) blocksize); + read = fread(file, sizeof(char), blocksize, config); + if (read != blocksize) { + XplConsolePrintf(" Read error!"); + } + + delim = strrchr(filename, '/'); + *delim = 0; + snprintf(fullpath, 108, "/%s", filename); + if (!PutOrReplaceConfig(client, fullpath, + delim+1, file, filesize)) { + XplConsolePrintf(_("ERROR: Couldn't write %s to store\n"), fullpath); + } else { + if (! SetAdminRights(client, fullpath)) { + XplConsolePrintf(_("ERROR: Couldn't set rights on store file %s\n"), fullpath); + } + } + MemFree(file); + } + } + + fclose(config); + return TRUE; +} + +BOOL +SetAdminRights(StoreClient *client, char *document) { + CCode ccode; + char *rights = "grant user:admin all;"; + + ccode = NMAPRunCommandF(client->conn, client->buffer, sizeof(client->buffer), + "PROPSET %s nmap.access-control %d\r\n", document, strlen(rights)); + if (ccode == 2002) { + NMAPSendCommandF(client->conn, rights); + ccode = NMAPReadAnswer(client->conn, client->buffer, + sizeof(client->buffer), TRUE); + if (ccode == 1000) + return TRUE; + } + return FALSE; +} + +BOOL +PutOrReplaceConfig(StoreClient *client, char *collection, char *filename, char *content, long len) { + CCode ccode; + char command[1024]; + + snprintf(command, 1000, "INFO %s/%s\r\n", collection, filename); + ccode = NMAPSendCommandF(client->conn, command); + ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); + while (ccode == 2001) + ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); + + if (ccode == 1000) { + // INFO returned OK, document already exists + snprintf(command, 1000, "REPLACE %s/%s %ld\r\n", + collection, filename, len); + } else { + // INFO errored, so document doesn't exist + snprintf(command, 1000, "WRITE %s %d %ld \"F%s\"\r\n", + collection, STORE_DOCTYPE_CONFIG, len, filename); + } + + NMAPSendCommandF(client->conn, command); + ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); + + if (ccode == 2002) { + ConnWrite(client->conn, content, len); + ConnFlush(client->conn); + if (NMAPReadAnswer(client->conn, client->buffer, + sizeof(client->buffer), TRUE) == 1000) { + return TRUE; + } + XplConsolePrintf(_("ERROR: Couldn't write data\n")); + } else { + XplConsolePrintf(_("ERROR: Wouldn't accept data\n")); + } + return FALSE; +} + +BOOL +NMAPSimpleCommand(StoreClient *client, char *command) { + CCode ccode; + + NMAPSendCommandF(client->conn, command); + ccode = NMAPReadAnswer(client->conn, client->buffer, sizeof(client->buffer), TRUE); + if (1000 == ccode) + return TRUE; + + return FALSE; +} diff --git a/src/apps/manager/Bongo.rules b/src/apps/manager/Bongo.rules index 261c6b7..c682f6d 100644 --- a/src/apps/manager/Bongo.rules +++ b/src/apps/manager/Bongo.rules @@ -1,13 +1,12 @@ # -*- Makefile -*- sbin_PROGRAMS += bongo-manager -bongo_manager_SOURCES := \ +bongo_manager_SOURCES = \ src/apps/manager/manager.c -bongo_manager_LDADD := \ +bongo_manager_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongoconnio.la \ libbongomemmgr.la \ libbongo-json.la \ diff --git a/src/apps/manager/manager.c b/src/apps/manager/manager.c index 2ffb988..90276c8 100644 --- a/src/apps/manager/manager.c +++ b/src/apps/manager/manager.c @@ -28,8 +28,7 @@ #define CRASH_WINDOW 10 typedef struct { - const char *program; - const char *dn; + char *program; int priority; BOOL willCallback; } BongoAgentSpec; @@ -60,9 +59,6 @@ static BOOL ChildError = FALSE; static BOOL ReloadNow = FALSE; static int HighestPriority = 0; -MDBHandle DirectoryHandle = NULL; -char ServerDN[MDB_MAX_OBJECT_CHARS + 1]; - static BongoAgent * FindAgentByPid(pid_t pid) { @@ -423,7 +419,7 @@ Lock(BOOL force) exit(1); } - remaining = snprintf(pidstr, sizeof(pidstr), "%ld\n", pid); + remaining = snprintf(pidstr, sizeof(pidstr), "%ld\n", (long int)pid); ret = 0; written = 0; @@ -571,20 +567,10 @@ ParseArgs(int argc, char **argv, static int StartSlapd(BOOL killExisting) { - int status = 0; - int err; - char buf[MDB_MAX_OBJECT_CHARS + 1]; - char url[MDB_MAX_OBJECT_CHARS + 1]; + int err = 0; - char *host = "127.0.0.1"; - int port = 0; pid_t pid = 0; - int sockfd = 0; - struct sockaddr_in serv_addr; - struct hostent* host_info; - long host_addr; - /* Get rid of an existing managed-slapd processs */ pid = ReadPid(SLAPD_LOCKFILE); @@ -600,7 +586,7 @@ StartSlapd(BOOL killExisting) return 1; } } else { - fprintf(stderr, _("bongo-manager: managed-slapd appears to be running as pid %ld\n"), pid); + fprintf(stderr, _("bongo-manager: managed-slapd appears to be running as pid %ld\n"), (long int)pid); fprintf(stderr, _("bongo-manager: if this is definitely the bongo slapd, you can run with -e to kill it\n")); return 1; } @@ -608,7 +594,7 @@ StartSlapd(BOOL killExisting) } /* read config */ - +#if 0 if (!MsgGetConfigProperty((unsigned char *) buf, (unsigned char *) MSGSRV_CONFIG_PROP_MANAGED_SLAPD_PORT)) { fprintf(stderr, _("bongo-manager: error reading managed slapd port from config file.\n")); @@ -623,7 +609,7 @@ StartSlapd(BOOL killExisting) return 1; } - snprintf(url, MDB_MAX_OBJECT_CHARS, "ldap://%s:%d", host, port); + snprintf(url, 100, "ldap://%s:%d", host, port); printf(_("bongo-manager: starting managed slapd...\n")); @@ -687,7 +673,7 @@ StartSlapd(BOOL killExisting) break; } close(sockfd); - +#endif return err; } @@ -776,11 +762,9 @@ main(int argc, char **argv) BOOL reload; BOOL slapdOnly; BOOL killExistingSlapd; - char buf[CONN_BUFSIZE]; BOOL droppedPrivs = FALSE; BOOL unlockFile = FALSE; BOOL startLdap = FALSE; - MDBHandle directory; XplInit(); @@ -880,15 +864,8 @@ get_lock: } ConnStartup(DEFAULT_CONNECTION_TIMEOUT, TRUE); - if (!MsgGetConfigProperty(ServerDN, MSGSRV_CONFIG_PROP_MESSAGING_SERVER)) { - fprintf(stderr, _("bongo-manager: Couldn't read the server DN from bongo.conf.\n")); - goto err_handler; - } - - if (MsgGetConfigProperty((unsigned char *) buf, - (unsigned char *) MSGSRV_CONFIG_PROP_MANAGED_SLAPD)) { - startLdap = atoi(buf); - } + // set startLdap here if we want to start a managed slapd instance + // startLdap = atoi(buf); if (startLdap) { int err; @@ -905,23 +882,8 @@ get_lock: } if (!slapdOnly) { - if (!MDBInit()) { - fprintf(stderr, _("bongo-manager: unable to intialize directory access.\n")); - goto err_handler; - } - - directory = MsgInit(); - if (!directory) { - fprintf(stderr, _("bongo-manager: unable to MsgInit()\n")); - goto err_handler; - } - NMAPInitialize(directory); - - DirectoryHandle = MsgGetSystemDirectoryHandle(); - if (DirectoryHandle == NULL) { - fprintf(stderr, _("bongo-manager: unable to initialize messaging library.\n")); - goto err_handler; - } + MsgInit(); + NMAPInitialize(); } signal(SIGTERM, SignalHandler); diff --git a/src/apps/sendmail/Bongo.rules b/src/apps/sendmail/Bongo.rules index 98b1288..82d03b4 100644 --- a/src/apps/sendmail/Bongo.rules +++ b/src/apps/sendmail/Bongo.rules @@ -1,14 +1,13 @@ # -*- Makefile -*- sbin_PROGRAMS += bongo-sendmail -bongo_sendmail_SOURCES := \ +bongo_sendmail_SOURCES = \ src/apps/sendmail/sendmail.h \ src/apps/sendmail/sendmail.c -bongo_sendmail_LDADD := \ +bongo_sendmail_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/apps/sendmail/sendmail.c b/src/apps/sendmail/sendmail.c index 9cbd094..b556eaa 100644 --- a/src/apps/sendmail/sendmail.c +++ b/src/apps/sendmail/sendmail.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +70,6 @@ int main (int argc, char *argv[]) { Connection *nmap; - MDBHandle directory; ssize_t size = 0; char *line = NULL; char *response; @@ -84,14 +82,8 @@ main (int argc, char *argv[]) ConnStartup((15*60), TRUE); - if (! MDBInit()) { - FatalError(1, "couldn't access MDB."); - } - directory = (MDBHandle)MsgInit(); - if (! directory) { - FatalError(1, "invalid directory credentials."); - } - NMAPInitialize(directory); + MsgInit(); + NMAPInitialize(); CONN_TRACE_INIT((char *)MsgGetWorkDir(NULL), "sendmail"); // CONN_TRACE_SET_FLAGS(CONN_TRACE_ALL); /* uncomment this line and pass '--enable-conntrace' to autogen to get the agent to trace all connections */ @@ -105,7 +97,7 @@ main (int argc, char *argv[]) } response = MemMalloc(sizeof(char) * 1000); - if (! NMAPAuthenticate(nmap, response, 1000)) { + if (! NMAPAuthenticateToQueue(nmap, response, 1000)) { FatalError(1, "cannot authenticate with NMAP."); } MemFree(response); diff --git a/src/apps/setup/Bongo.rules b/src/apps/setup/Bongo.rules index a7d6eb5..59dd1f5 100644 --- a/src/apps/setup/Bongo.rules +++ b/src/apps/setup/Bongo.rules @@ -1,13 +1,13 @@ # -*- Makefile -*- sbin_SCRIPTS += src/apps/setup/bongo-setup -schemadir := $(XPL_DEFAULT_CONF_DIR) -dist_schema_DATA := \ +schemadir = $(XPL_DEFAULT_CONF_DIR) +dist_schema_DATA = \ src/apps/setup/bongo-setup.xml \ src/apps/setup/base-schema.xml \ src/apps/setup/bongo-schema.xml -nodist_schema_DATA := \ +nodist_schema_DATA = \ src/apps/setup/bongo-setup.xml dist_noinst_DATA += src/apps/setup/bongo-setup.xml.in diff --git a/src/apps/setup/bongo-setup.py b/src/apps/setup/bongo-setup.py index da5db43..b4f1326 100755 --- a/src/apps/setup/bongo-setup.py +++ b/src/apps/setup/bongo-setup.py @@ -485,14 +485,14 @@ def ImportObjects(mdbconf, options): if mdbconf.has_key("slapdConfig"): slapdConfig = mdbconf["slapdConfig"] - log.debug("initializing slapd with the base Bongo container") - pid = slapdConfig.initSlapd(mdbconf["slapdConfigFile"]) - log.debug("starting temporary managed slapd process") pid = slapdConfig.startSlapd(mdbconf["slapdConfigFile"]) if pid is None: raise BongoError('Error starting temporary slapd process. Check syslog for information about the failure.') + log.debug("initializing slapd with the base Bongo container") + slapdConfig.initSlapd() + options.file = Input('Enter file for importing objects', default=options.file, options=options) diff --git a/src/apps/storetool/Bongo.rules b/src/apps/storetool/Bongo.rules index 06f3f83..76f8d49 100644 --- a/src/apps/storetool/Bongo.rules +++ b/src/apps/storetool/Bongo.rules @@ -1,12 +1,14 @@ # -*- Makefile -*- -pkgpythonstoretooldir := $(pkgpythondir)/storetool +pkgpythonstoretooldir = $(pkgpythondir)/storetool -pkgpythonstoretool_PYTHON := \ +pkgpythonstoretool_PYTHON = \ src/apps/storetool/bongo/storetool/__init__.py \ + src/apps/storetool/bongo/storetool/BackupCommands.py \ src/apps/storetool/bongo/storetool/CalendarCommands.py \ src/apps/storetool/bongo/storetool/ContactCommands.py \ src/apps/storetool/bongo/storetool/InteractiveCommands.py \ src/apps/storetool/bongo/storetool/MailCommands.py \ + src/apps/storetool/bongo/storetool/TestCommands.py \ src/apps/storetool/bongo/storetool/ExportMailbox.py src/apps/storetool/bongo-storetool: $(top_builddir)/src/libs/python/bongo-python-wrapper diff --git a/src/apps/storetool/bongo-storetool.py b/src/apps/storetool/bongo-storetool.py index 1233198..35880c9 100755 --- a/src/apps/storetool/bongo-storetool.py +++ b/src/apps/storetool/bongo-storetool.py @@ -4,10 +4,12 @@ import logging, os, pwd, sys from bongo.cmdparse import CommandParser, Command +from bongo.storetool import BackupCommands from bongo.storetool import CalendarCommands from bongo.storetool import ContactCommands from bongo.storetool import InteractiveCommands from bongo.storetool import MailCommands +from bongo.storetool import TestCommands parser = CommandParser() parser.add_option("", "--host", type="string", default="localhost", @@ -23,10 +25,12 @@ parser.add_option("-p", "--password", type="string", parser.add_option("-s", "--store", type="string", help="store (if different from user)") +parser.add_commands(BackupCommands, "Backup") parser.add_commands(CalendarCommands, "Calendar") parser.add_commands(ContactCommands, "Contact") parser.add_commands(InteractiveCommands) parser.add_commands(MailCommands, "Mail") +parser.add_commands(TestCommands, "Testing") if __name__ == '__main__': (command, options, args) = parser.parse_args() diff --git a/src/apps/storetool/bongo/storetool/BackupCommands.py b/src/apps/storetool/bongo/storetool/BackupCommands.py new file mode 100644 index 0000000..3d62679 --- /dev/null +++ b/src/apps/storetool/bongo/storetool/BackupCommands.py @@ -0,0 +1,290 @@ +import logging +import string +import sys + +from gettext import gettext as _ +import tarfile + +from bongo.cmdparse import Command +from bongo.BongoError import BongoError +from bongo.store.StoreClient import DocTypes, StoreClient + +# import/export store contents as tar files +# ideally we want to farm the tar format stuff itself out into a separate lib. +# Sadly, the TarFile implementation that comes with Python is mostly useless + +class PAXHeader: + def __init__(self, filename): + self.keywords = {} + self.filename = filename + + def SetKey(self, key, value): + self.keywords[key] = value + + def Keys(self): + return self.keywords + + def ToString(self): + header = tarfile.TarInfo(self.filename + ".metadata") + header.type = "x" + + content = "" + for key in self.keywords.keys(): + if self.keywords[key] != None: + content += "%d %s=%s\n" % (len(key) + len(self.keywords[key]) + 5, key, self.keywords[key]) + header.size = len(content) + + result = header.tobuf() + result += content + remainder = len(content) % 512 + if remainder != 0: + result += "\0" * (512 - remainder) + + return result + + def FromString(self, content): + for line in string.split(content, "\n"): + space = string.find(line, " ") + equals = string.find(line, "=") + key = line[space+1:equals] + value = line[equals+1:] + self.keywords[key] = value + +class StoreBackupCommand(Command): + log = logging.getLogger("Bongo.StoreTool") + user = "admin" + store = "_system" + + def __init__(self): + Command.__init__(self, "store-backup", aliases=["sb"], + summary="Create a backup of a store", + usage="%prog %cmd []") + + def GetStoreConnection(self): + return StoreClient(self.user, self.store) + + def BackupStore(self): + # create a backup file which contains all the contents of the given store + store = self.GetStoreConnection() + docstore = self.GetStoreConnection() + + try: + backup_file = open("%s.backup" % self.store, "wb") + except IOError, e: + print str(e) + return + + collection_list = [] + for collection in store.Collections(): + # write out entries for collections + tar_head = PAXHeader(collection.name) + tar_head.SetKey("BONGO.uid", collection.uid) + tar_head.SetKey("BONGO.type", "%d" % collection.type) + tar_head.SetKey("BONGO.flags", "%d" % collection.flags) + props = docstore.PropGet(collection.uid) + for key in props.keys(): + tar_head.SetKey("BONGO.%s" % key, props[key]) + backup_file.write(tar_head.ToString()) + + tar_dir = tarfile.TarInfo(collection.name) + tar_dir.size = 0 + tar_dir.type = tarfile.DIRTYPE + tar_dir.mode = 0755 + backup_file.write(tar_dir.tobuf()) + collection_list.append(collection.name) + + for collection in collection_list: + for document in store.List(collection): + # write out the documents in the collection + if document.filename[0] == '/' or document.type & DocTypes.Folder: + # this is a collection + continue + if document.type == DocTypes.Conversation or document.type == DocTypes.Calendar: + # DB-only file type, don't attempt to back this up + continue + filename = "%s/%s" % (collection, document.filename) + try: + content = docstore.Read(filename) + except IOError, e: + print str(e) + continue + + # write out meta data associated with document in a PAX extended header + headerx = PAXHeader(filename) + headerx.SetKey("BONGO.uid", document.uid) + headerx.SetKey("BONGO.imapuid", document.imapuid) + headerx.SetKey("BONGO.type", "%d" % document.type) + headerx.SetKey("BONGO.flags", "%d" % document.flags) + props = docstore.PropGet(document.uid) + for key in props.keys(): + headerx.SetKey("BONGO.%s" % key, props[key]) + backup_file.write(headerx.ToString()) + + # tar files have a 512 byte header (tar_info.tobuf()), and then the content + # content is padded to a multiple of 512 bytes + tar_info = tarfile.TarInfo(filename) + tar_info.size = len(content) + tar_info.mode = 0644 + tar_info.mtime = int(document.created) + backup_file.write(tar_info.tobuf()) + backup_file.write(content) + space = len(content) % 512 + if space != 0: + backup_file.write("\0" * (512 - space)) + + + store.Quit() + docstore.Quit() + + backup_file.write("\0" * 1024) # end of archive marker + backup_file.close() + + def Run(self, options, args): + if len(args) == 1 and args[0] == "help": + self.print_help() + self.exit() + + self.user = options.user + self.store = options.store + self.BackupStore() + +class StoreRestoreCommand(Command): + log = logging.getLogger("Bongo.StoreTool") + + def __init__(self): + Command.__init__(self, "store-restore", aliases=["sr"], + summary="Restore a backup of a user store", + usage="%prog %cmd []") + + def RestoreStore(self, store, backupfile): + # restore the contents of a backup file to the store we're set to + while True: + # read the tar header, check it's sane + header = backupfile.read(512) + if len(header) != 512: + return + + # look at the file metadata, check it's sane + try: + extheader = tarfile.TarInfo.frombuf(header) + except: + # probably the end of the file + return + + if extheader.type != "x": + print "No metadata header found (%s)" % extheader.name + continue + + metadata = PAXHeader(None) + metadata.FromString(backupfile.read(extheader.size)) + remainder = extheader.size % 512 + if remainder != 0: + backupfile.read(512 - remainder) + + header = backupfile.read(512) + if len(header) != 512: + return + + document = tarfile.TarInfo.frombuf(header) + if document.name == None: + return # done reading from archive? + + if document.size == 0: + if document.type == tarfile.DIRTYPE: + # this is a collection + self.RestoreCollection(store, document.name, metadata.Keys()) + continue + + # pull out file contents, and any padding + content = backupfile.read(document.size) + remainder = document.size % 512 + if remainder != 0: + backupfile.read(512 - remainder) + + # restore the file + self.RestoreFile(store, document.name, content, metadata.Keys()) + + def RestoreProps(self, store, guid, metadata): + del metadata["BONGO.nmap.guid"] + del metadata["BONGO.nmap.type"] + del metadata["BONGO.nmap.flags"] + del metadata["BONGO.nmap.collection"] + del metadata["BONGO.nmap.index"] + for key, value in metadata.items(): + if key[0:10] == "BONGO.nmap": + prop = key[6:] + try: + store.PropSet(guid, prop, value) + except: + print "Failed to set property %s to %s on %s" % (prop, value, guid) + + def RestoreFile(self, store, name, content, metadata): + dir_sep = name.rfind("/") + if dir_sep < 3: + return # invalid name + collection = name[0:dir_sep] + filename = name[dir_sep+1:] + file_guid = None + + if "BONGO.uid" in metadata: + file_guid = metadata["BONGO.uid"] + del metadata["BONGO.uid"] + + file_type = 0 + if "BONGO.type" in metadata: + file_type = int(metadata["BONGO.type"]) + del metadata["BONGO.type"] + + try: + new_guid = store.Write(collection, file_type, content, filename=filename, guid=file_guid) + except: + print "Failed to restore %s/%s" % (collection, filename) + return + if "BONGO.flags" in metadata: + try: + store.Flag(new_guid, flags=int(metadata["BONGO.flags"])) + del metadata["BONGO.flags"] + except: + print "Couldn't restore mail flag on %s/%s" % (collection, filename) + self.RestoreProps(store, new_guid, metadata) + + def RestoreCollection(self, store, name, metadata): + collection = name[0:-1] + try: + if "BONGO.uid" in metadata: + store.Create(collection, guid=metadata["BONGO.uid"]) + else: + store.Create(collection) + except: + print "Failed to create collection %s" % collection + self.RestoreProps(store, collection, metadata) + + def ClearStore(self, store): + collections = [collection.name for collection in store.Collections()] + collections.sort(lambda x, y: len(x)-len(y), reverse=True) + for collection in collections: + store.Remove(collection) + + def Run(self, options, args): + if len(args) == 0: + self.print_help() + self.exit() + + backup_file = "%s.backup" % options.store + if len(args) == 1: + # user specified a backup file to restore + backup_file = args[0] + + store = StoreClient(options.user, options.store) + + f = None + try: + f = open(backup_file, "r") + store.Store(options.store) + self.ClearStore(store) + self.RestoreStore(store, f) + except IOError, e: + print str(e) + if f: + f.close() + store.Quit() diff --git a/src/apps/storetool/bongo/storetool/MailCommands.py b/src/apps/storetool/bongo/storetool/MailCommands.py index 464cf82..89a8e13 100644 --- a/src/apps/storetool/bongo/storetool/MailCommands.py +++ b/src/apps/storetool/bongo/storetool/MailCommands.py @@ -38,12 +38,11 @@ class MailImportCommand(Command): fd = open(file) mailstore = mailbox.PortableUnixMailbox(fd, email.message_from_file) - elif type == "maildir": - mailstore = mailbox.Maildir(file, email.message_from_file) + elif type == "maildir": + mailstore = mailbox.Maildir(file, email.message_from_file) for msg in mailstore: - data = msg.as_string(True) - store.Write(collection, DocTypes.Mail, data) + store.Write(collection, DocTypes.Mail, msg.as_string(True)) if fd: fd.close() @@ -112,3 +111,53 @@ class MailExportCommand(Command): print str(e) finally: store.Quit() + +class MailImapCommand(Command): + log = logging.getLogger("Bongo.StoreTool") + + def __init__(self): + Command.__init__(self,"mail-importimap", aliases=["mii"], + summary="Imports mail from an IMAP server", + usage="%prog %cmd") + + self.add_option("", "--imap_username", type="string", default="", help=_("IMAP server username")) + self.add_option("", "--imap_password", type="string", default="", help=_("IMAP server password")) + self.add_option("", "--imap_folder", type="string", default="INBOX", help=_("IMAP server folder to export from, defaults to INBOX")) + self.add_option("", "--imap_server", type="string", default="", help=_("IMAP server hostname")) + self.add_option("", "--imap_port", type="int", default=143, help=_("IMAP server port, defaults to 143")) + self.add_option("-f", "--folder", type="string", default="INBOX", help=_("Folder to import into, defaults to INBOX")) + + def Run(self, options, args): + if (options.imap_username == "" or + options.imap_server == ""): + self.print_help() + self.exit() + + store = StoreClient(options.user, options.store) + try: + self.ImportMail(store, options.folder, options.imap_username, options.imap_password, options.imap_folder, options.imap_server, options.imap_port) + finally: + store.Quit() + + def ImportMail(self, store, folder, imap_username, imap_password, imap_folder, imap_server, imap_port): + import imaplib + + collection = "/mail/" + folder + store.Create(collection, existingOk=True) + + try: + M=imaplib.IMAP4(imap_server, imap_port) + M.login(imap_username, imap_password) + M.select(imap_folder) + + try: + typ, data = M.search(None, 'ALL') + for num in data[0].split(): + store.WriteImap(collection, DocTypes.Mail, M, num) + + finally: + M.close() + M.logout() + finally: + return + diff --git a/src/apps/storetool/bongo/storetool/TestCommands.py b/src/apps/storetool/bongo/storetool/TestCommands.py new file mode 100644 index 0000000..d0fadb6 --- /dev/null +++ b/src/apps/storetool/bongo/storetool/TestCommands.py @@ -0,0 +1,82 @@ +import logging +from bongo import Xpl +from bongo.cmdparse import Command +from bongo.BongoError import BongoError +from bongo.store.StoreClient import DocTypes, StoreClient + +class TestRun(Command): + log = logging.getLogger("Bongo.StoreTool") + + def __init__(self): + Command.__init__(self, "testrun", aliases=["tr"], + summary="Run a test suite against the store", + usage="%prog %cmd") + + def Err(self, message): + print "[ERR] %s" % message + + def Run(self, options, args): + try: + store = StoreClient("admin", "admin") + except: + self.Err("Couldn't connect to a store for testing.") + return + + # collection testing first + print "Looking for collections..." + try: + colls = store.Collections() + for coll in colls: + pass + except: + self.Err("Can't list collections (COLLECTIONS)") + + print "Adding collection" + try: + coll = store.Create("/testcoll", existingOk = True) + except: + self.Err("Can't add collection (CREATE)") + + print "Listing collection contents" + try: + contents = store.List("/testcoll") + for doc in contents: + pass + except: + self.Err("Can't list collection contents (LIST)") + + print "Renaming collection" + try: + store.Rename("/testcoll", "/renamed-testcoll") + except: + self.Err("Can't rename test collection (RENAME)") + + mailpath = Xpl.DEFAULT_DATA_DIR + "/demo/mail" + mail1 = "%s/%s" % (mailpath, "bongo-general-000") + mail2 = "%s/%s" % (mailpath, "bongo-general-002") + + print "Writing mail to collection..." + guid = None + try: + f = file(mail1) + guid = store.Write("/renamed-testcoll", DocTypes.Mail, f.read()) + f.close() + except: + self.Err("Can't write new doc to renamed-testcoll") + + if guid != None: + print "Removing mail from collection..." + try: + store.Delete(guid) + except: + self.Err("Can't remove document from renamed-testcoll") + + print "Removing collection" + try: + store.Remove("/renamed-testcoll") + except: + self.Err("Couldn't remove collection (REMOVE)") + + + + print "Test suite ran successfully." diff --git a/src/apps/storetool/demo/Bongo.rules b/src/apps/storetool/demo/Bongo.rules index 0143151..04b388f 100644 --- a/src/apps/storetool/demo/Bongo.rules +++ b/src/apps/storetool/demo/Bongo.rules @@ -1,20 +1,20 @@ # -*- Makefile -*- -demodir := $(pkgdatadir)/demo +demodir = $(pkgdatadir)/demo -calendardir := $(demodir)/calendars -dist_calendar_DATA := \ +calendardir = $(demodir)/calendars +dist_calendar_DATA = \ src/apps/storetool/demo/calendars/French%20Holidays.ics \ src/apps/storetool/demo/calendars/openSUSE.ics \ src/apps/storetool/demo/calendars/US%20Holidays.ics \ src/apps/storetool/demo/calendars/World%20Cup%202006.ics -contactdir := $(demodir)/contacts -dist_contact_DATA := \ +contactdir = $(demodir)/contacts +dist_contact_DATA = \ src/apps/storetool/demo/contacts/list.vcf -maildir := $(demodir)/mail +maildir = $(demodir)/mail -dist_mail_DATA := \ +dist_mail_DATA = \ src/apps/storetool/demo/mail/bbq \ src/apps/storetool/demo/mail/party-invite \ src/apps/storetool/demo/mail/desktop-devel-000 \ diff --git a/src/apps/testtool/Bongo.rules b/src/apps/testtool/Bongo.rules index ae2750b..4980415 100644 --- a/src/apps/testtool/Bongo.rules +++ b/src/apps/testtool/Bongo.rules @@ -1,15 +1,15 @@ # -*- Makefile -*- sbin_PROGRAMS += bongo-testtool -bongo_testtool_SOURCES := \ +bongo_testtool_SOURCES = \ $(conf_defaults) \ src/apps/testtool/config.h \ src/apps/testtool/testtool.c -bongo_testtool_CPPFLAGS := $(AM_CPPFLAGS) \ +bongo_testtool_CPPFLAGS = $(AM_CPPFLAGS) \ $(GNUTLS_CFLAGS) -bongo_testtool_LDADD := \ +bongo_testtool_LDADD = \ libbongonmap.la \ libbongomsgapi.la \ libbongoconnio.la \ diff --git a/src/apps/testtool/testtool.c b/src/apps/testtool/testtool.c index 471fd71..0307fe2 100644 --- a/src/apps/testtool/testtool.c +++ b/src/apps/testtool/testtool.c @@ -61,7 +61,6 @@ int main(int argc, char *argv[]) { int next_arg = 0; int command = 0; - int startup = 0; if (!MemoryManagerOpen("bongo-testtool")) { XplConsolePrintf(_("ERROR: Failed to initialize memory manager\n")); @@ -70,7 +69,6 @@ main(int argc, char *argv[]) { // parse options while (++next_arg < argc && argv[next_arg][0] == '-') { - char *arg = argv[next_arg]; printf(_("Unrecognized option: %s\n"), argv[next_arg]); } diff --git a/src/libs/bongoutil/Bongo.rules b/src/libs/bongoutil/Bongo.rules index bb5505e..110bb8c 100644 --- a/src/libs/bongoutil/Bongo.rules +++ b/src/libs/bongoutil/Bongo.rules @@ -3,7 +3,7 @@ lib_LTLIBRARIES += libbongoutil.la libbongoutil_la_LDFLAGS = $(GNUTLS_LIBS) -libbongoutil_la_SOURCES := \ +libbongoutil_la_SOURCES = \ src/libs/bongoutil/array.c \ src/libs/bongoutil/fileio.c \ src/libs/bongoutil/hashtable.c \ @@ -15,7 +15,7 @@ libbongoutil_la_SOURCES := \ src/libs/bongoutil/utf7mod.c \ src/libs/bongoutil/bongoutil.c -libbongoutil_la_LIBADD := \ +libbongoutil_la_LIBADD = \ libbongoxpl.la \ libbongomemmgr.la diff --git a/src/libs/bongoutil/array.c b/src/libs/bongoutil/array.c index a4c85a8..fc58c9e 100644 --- a/src/libs/bongoutil/array.c +++ b/src/libs/bongoutil/array.c @@ -28,7 +28,11 @@ int BongoArrayInit(BongoArray *array, unsigned int elementSize, unsigned int initialSize) { - if (initialSize > 0) { + if (!array) { + return -1; + } + + if (initialSize > 0) { array->data = MemMalloc(initialSize * elementSize); if (!array->data) { return -1; @@ -47,6 +51,10 @@ BongoArrayDestroy(BongoArray *array, BOOL freeSegment) { void *ret; + if (!array) { + return NULL; + } + if (freeSegment) { MemFree(array->data); ret = NULL; @@ -78,6 +86,10 @@ BongoArrayNew(unsigned int elementSize, unsigned int initialSize) void * BongoArrayFree(BongoArray *array, BOOL freeSegment) { + if (!array) { + return NULL; + } + void *ret = BongoArrayDestroy(array, freeSegment); MemFree(array); @@ -90,6 +102,10 @@ BongoArrayExpand(BongoArray *array, unsigned int newLen) { unsigned int newSize; + if (!array) { + return; + } + if (array->size >= newLen) { return; } @@ -111,6 +127,10 @@ BongoArrayExpand(BongoArray *array, unsigned int newLen) void BongoArrayAppendValues(BongoArray *array, const void *data, unsigned int len) { + if (!array) { + return; + } + BongoArrayExpand(array, array->len + len); memcpy((char*)array->data + (array->elemSize * array->len), data, (array->elemSize * len)); @@ -121,6 +141,10 @@ BongoArrayAppendValues(BongoArray *array, const void *data, unsigned int len) void BongoArrayRemove(BongoArray *array, unsigned int i) { + if (!array) { + return; + } + if (i >= array->len) { return; } @@ -136,6 +160,10 @@ BongoArrayFindUnsorted(BongoArray *array, void *needle, ArrayCompareFunc compare { unsigned int i; + if (!array) { + return -1; + } + for (i = 0; i < array->len; i++) { if (!compare(needle, (char*)array->data + (i * array->elemSize))) { return (int)i; @@ -150,6 +178,10 @@ BongoArrayFindSorted(BongoArray *array, void *needle, ArrayCompareFunc compare) { void *data; + if (!array) { + return -1; + } + data = bsearch(needle, array->data, array->len, array->elemSize, compare); if (data) { @@ -162,6 +194,10 @@ BongoArrayFindSorted(BongoArray *array, void *needle, ArrayCompareFunc compare) void BongoArraySetLength(BongoArray *array, unsigned int len) { + if (!array) { + return; + } + BongoArrayExpand(array, len); array->len = len; @@ -170,6 +206,10 @@ BongoArraySetLength(BongoArray *array, unsigned int len) void BongoArraySort(BongoArray *array, ArrayCompareFunc compare) { + if (!array) { + return; + } + qsort(array->data, array->len, array->elemSize, compare); } diff --git a/src/libs/bongoutil/bongoutil.c b/src/libs/bongoutil/bongoutil.c index 4ceeea3..948a50f 100644 --- a/src/libs/bongoutil/bongoutil.c +++ b/src/libs/bongoutil/bongoutil.c @@ -800,9 +800,8 @@ EncodeBase64(const unsigned char *UnencodedString) } BOOL -HashCredential(const unsigned char *DN, unsigned char *Credential, unsigned char *Hash) +HashCredential(unsigned char *Credential, unsigned char *Hash) { - unsigned char *delim; unsigned char *srcPtr; unsigned char *dstPtr; unsigned char *dstEnd; @@ -811,7 +810,7 @@ HashCredential(const unsigned char *DN, unsigned char *Credential, unsigned char unsigned long len; xpl_hash_context ctx; - if (Credential && DN && (DN[0] == '\\') && ((delim = strchr(DN + 1, '\\')) != NULL)) { + if (Credential) { len = strlen(Credential); if (len >= NMAP_CRED_STORE_SIZE) { srcPtr = Credential; @@ -820,7 +819,6 @@ HashCredential(const unsigned char *DN, unsigned char *Credential, unsigned char XplHashNew(&ctx, XPLHASH_MD5); XplHashWrite(&ctx, srcPtr, NMAP_CRED_CHUNK_SIZE); - XplHashWrite(&ctx, DN, delim - DN); XplHashFinalBytes(&ctx, digest, XPLHASH_MD5BYTES_LENGTH); srcPtr += NMAP_CRED_CHUNK_SIZE; diff --git a/src/libs/bongoutil/tests/Bongo.rules b/src/libs/bongoutil/tests/Bongo.rules index 56c3179..720f443 100644 --- a/src/libs/bongoutil/tests/Bongo.rules +++ b/src/libs/bongoutil/tests/Bongo.rules @@ -10,7 +10,7 @@ dist_noinst_DATA += \ CLEANFILES += \ src/libs/bongoutil/tests/checklog.xml -checktest_bongoutil_SOURCES := \ +checktest_bongoutil_SOURCES = \ src/libs/bongoutil/tests/checktest.c checktest_bongoutil_LDADD = $(CHECK_LIBS) \ diff --git a/src/libs/bongoutil/utf7mod.c b/src/libs/bongoutil/utf7mod.c index ec31847..cddd9ce 100644 --- a/src/libs/bongoutil/utf7mod.c +++ b/src/libs/bongoutil/utf7mod.c @@ -1052,7 +1052,7 @@ ValidateModifiedUtf7(char *utf7String) int ValidateUtf8(char *utf8String) { - int len; + int len = 0; char *resultUtf7; len = GetModifiedUtf7FromUtf8(utf8String, len, &resultUtf7); @@ -1074,7 +1074,7 @@ ValidateUtf7Utf8Pair(char *utf7String, size_t utf7StringLen, char *utf8String, s len = GetModifiedUtf7FromUtf8(utf8String, utf8StringLen, &resultUtf7); if (len > 0) { - if (len == utf7StringLen) { + if (len == (int)utf7StringLen) { if (strcmp(utf7String, resultUtf7) == 0) { MemFree(resultUtf7); return(UTF7_STATUS_SUCCESS); diff --git a/src/libs/cal/Bongo.rules b/src/libs/cal/Bongo.rules index 02bee65..0fe1fd4 100644 --- a/src/libs/cal/Bongo.rules +++ b/src/libs/cal/Bongo.rules @@ -1,7 +1,7 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongocal.la -libbongocal_la_SOURCES := \ +libbongocal_la_SOURCES = \ src/libs/cal/bongo-cal-object.c \ src/libs/cal/bongo-cal-instance.c \ src/libs/cal/bongo-cal-private.h \ @@ -10,11 +10,11 @@ libbongocal_la_SOURCES := \ src/libs/cal/bongo-cal-timezone.c \ src/libs/cal/cal-convert.c -libbongocal_la_CPPFLAGS := $(AM_CPPFLAGS) \ +libbongocal_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DZONEINFODIR=\""$(datadir)/bongo/zoneinfo"\" \ -I$(top_srcdir)/import/libical/src -libbongocal_la_LIBADD := \ +libbongocal_la_LIBADD = \ libbongomemmgr.la \ libbongoutil.la \ libbongoxpl.la \ @@ -26,9 +26,9 @@ libbongocal_la_LIBADD := \ noinst_PROGRAMS += bongo-import-tz -bongo_import_tz_SOURCES := src/libs/cal/bongo-import-tz.c -bongo_import_tz_LDADD := libbongocal.la -bongo_import_tz_CPPFLAGS := $(AM_CPPFLAGS) \ +bongo_import_tz_SOURCES = src/libs/cal/bongo-import-tz.c +bongo_import_tz_LDADD = libbongocal.la +bongo_import_tz_CPPFLAGS = $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/libs/cal src/libs/cal/all: libbongocal.la bongo-import-tz diff --git a/src/libs/cal/tests/Bongo.rules b/src/libs/cal/tests/Bongo.rules index c111bce..1721fae 100644 --- a/src/libs/cal/tests/Bongo.rules +++ b/src/libs/cal/tests/Bongo.rules @@ -4,10 +4,10 @@ check_PROGRAMS += checktest-cal CLEANFILES += checklog.xml -checktest_cal_SOURCES := \ +checktest_cal_SOURCES = \ src/libs/cal/tests/test-cal.c -checktest_cal_LDADD := $(CHECK_LIBS) \ +checktest_cal_LDADD = $(CHECK_LIBS) \ libbongomemmgr.la \ libbongoutil.la \ libbongoxpl.la \ @@ -17,7 +17,7 @@ checktest_cal_LDADD := $(CHECK_LIBS) \ $(PTHREAD_LIBS) \ $(ALL_LIBS) -checktest_CFLAGS := $(AM_CFLAGS) -g -O0 +checktest_CFLAGS = $(AM_CFLAGS) -g -O0 src/libs/cal/tests/all: src/libs/cal/tests/clean: clean diff --git a/src/libs/calcmd/Bongo.rules b/src/libs/calcmd/Bongo.rules index 3cf11f7..d25deae 100644 --- a/src/libs/calcmd/Bongo.rules +++ b/src/libs/calcmd/Bongo.rules @@ -1,23 +1,21 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongocalcmd.la -libbongocalcmd_la_SOURCES := \ +libbongocalcmd_la_SOURCES = \ src/libs/calcmd/parsecmd.y \ src/libs/calcmd/calcmd.c -libbongocalcmd_la_LIBADD := \ +libbongocalcmd_la_LIBADD = \ libbongocal.la \ libbongomemmgr.la \ libbongoxpl.la check_PROGRAMS += parsecmd -parsecmd_SOURCES := src/libs/calcmd/test.c +parsecmd_SOURCES = src/libs/calcmd/test.c -parsecmd_LDADD := \ - libbongomanagement.la \ +parsecmd_LDADD = \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongoconnio.la \ libbongomemmgr.la \ diff --git a/src/libs/calcmd/tests/Bongo.rules b/src/libs/calcmd/tests/Bongo.rules index cb5176e..260701a 100644 --- a/src/libs/calcmd/tests/Bongo.rules +++ b/src/libs/calcmd/tests/Bongo.rules @@ -2,10 +2,10 @@ TESTS += checktest-calcmd check_PROGRAMS += checktest-calcmd -checktest_calcmd_SOURCES := \ +checktest_calcmd_SOURCES = \ src/libs/calcmd/tests/checktest.c -checktest_calcmd_LDADD := $(CHECK_LIBS) +checktest_calcmd_LDADD = $(CHECK_LIBS) CLEANFILES += src/libs/calcmd/tests/checklog.xml diff --git a/src/libs/connio/Bongo.rules b/src/libs/connio/Bongo.rules index e71b017..57921c8 100644 --- a/src/libs/connio/Bongo.rules +++ b/src/libs/connio/Bongo.rules @@ -1,14 +1,15 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongoconnio.la -libbongoconnio_la_SOURCES := \ +libbongoconnio_la_SOURCES = \ src/libs/connio/connio.c \ src/libs/connio/trace.c \ src/libs/connio/conniop.h \ src/libs/connio/addrpool.c \ + src/libs/connio/sockets.c \ src/libs/connio/unix-ip.c -libbongoconnio_la_LIBADD := $(GNUTLS_LIBS) +libbongoconnio_la_LIBADD = $(GNUTLS_LIBS) src/libs/connio/all: libbongoconnio.la src/libs/connio/clean: clean diff --git a/src/libs/connio/connio.c b/src/libs/connio/connio.c index 37832d6..b4bffcf 100644 --- a/src/libs/connio/connio.c +++ b/src/libs/connio/connio.c @@ -79,7 +79,8 @@ __gnutls_new(bongo_ssl_context *context, gnutls_connection_end_t con_end) { gnutls_dh_set_prime_bits(session, 1024); } else { gnutls_certificate_credentials_t xcred = NULL; - const int cert_type_priority[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; + + const int cert_type_priority[4] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; /* defaults are ok here */ gnutls_set_default_priority (session); @@ -87,6 +88,8 @@ __gnutls_new(bongo_ssl_context *context, gnutls_connection_end_t con_end) { /* store the priority for x509 or openpgp out there * i doubt that openpgp will be used but perhaps there is a server that supports it */ gnutls_certificate_type_set_priority (session, cert_type_priority); + gnutls_certificate_allocate_credentials (&xcred); + gnutls_certificate_set_x509_trust_file (xcred, XPL_DEFAULT_CERT_PATH, GNUTLS_X509_FMT_PEM); /* set the empty credentials in the session */ gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); @@ -169,8 +172,6 @@ ConnStartup(unsigned long TimeOut, BOOL EnableSSL) srand((unsigned int)time(NULL)); - XPLCryptoLockInit(); - memset(seed, 0, sizeof(seed)); for (i = 0; i < 64; i++) { c = ' ' + ((unsigned char)rand() % 0x60) ; @@ -482,7 +483,8 @@ ConnClose(Connection *Conn, unsigned long Flags) CONN_TRACE_EVENT(Conn, CONN_TRACE_EVENT_CLOSE); CONN_TRACE_END(c); - CONN_TCP_CLOSE(c); + + ConnTcpClose(c); return(0); } @@ -497,7 +499,7 @@ ConnCloseAll(unsigned long Flags) c = ConnIO.allocated.head; while (c) { if (!c->bSelfManage) { - CONN_TCP_CLOSE(c); + ConnTcpClose(c); } c = c->allocated.next; @@ -518,7 +520,7 @@ ConnFree(Connection *Conn) } if (c->socket != -1) { - CONN_TCP_CLOSE(c); + ConnTcpClose(c); } if (c->receive.buffer) { @@ -561,7 +563,7 @@ ConnShutdown(void) ConnIO.allocated.head = NULL; while (c != NULL) { - CONN_TCP_CLOSE(c); + ConnTcpClose(c); if (c->receive.buffer) { MemFree(c->receive.buffer); @@ -580,15 +582,6 @@ ConnShutdown(void) if (ConnIO.encryption.enabled) { ConnIO.encryption.enabled = FALSE; - /* FIXME: OPENSSL - ERR_free_strings(); - ERR_remove_state(0); - - RAND_cleanup(); - EVP_cleanup(); - */ - - XPLCryptoLockDestroy(); } XplCloseLocalSemaphore(ConnIO.allocated.sem); @@ -624,9 +617,9 @@ int ConnAccept(Connection *Server, Connection **Client) int ConnSend(Connection *Conn, char *Buffer, unsigned int Length) { - register int count; + int count; - CONN_TCP_SEND(Conn, Buffer, Length, count); + ConnTcpWrite(Conn, Buffer, Length, &count); return(count); } @@ -634,9 +627,9 @@ ConnSend(Connection *Conn, char *Buffer, unsigned int Length) int ConnReceive(Connection *Conn, char *Buffer, unsigned int Length) { - register int count; + int count; - CONN_TCP_RECEIVE(Conn, Buffer, Length, count); + ConnTcpRead(Conn, Buffer, Length, &count); return(count); } @@ -654,8 +647,8 @@ ConnReceive(Connection *Conn, char *Buffer, unsigned int Length) int ConnRead(Connection *Conn, char *Dest, int Length) { - register int read; - register Connection *c = Conn; + int read; + Connection *c = Conn; read = c->receive.write - c->receive.read; do { @@ -677,7 +670,7 @@ ConnRead(Connection *Conn, char *Dest, int Length) return(Length); } - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, read); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &read); if (read > 0) { c->receive.read = c->receive.buffer; c->receive.write = c->receive.buffer + read; @@ -736,7 +729,7 @@ ConnReadCount(Connection *Conn, char *Dest, int Count) } if (remaining < CONN_TCP_MTU) { - CONN_TCP_RECEIVE(c, c->receive.write, c->receive.remaining, buffered); + ConnTcpRead(c, c->receive.write, c->receive.remaining, &buffered); if (buffered > 0) { c->receive.write += buffered; @@ -747,7 +740,7 @@ ConnReadCount(Connection *Conn, char *Dest, int Count) } } else { do { - CONN_TCP_RECEIVE(c, d, remaining, buffered); + ConnTcpRead(c, d, remaining, &buffered); if (buffered > 0) { d += buffered; remaining -= buffered; @@ -859,7 +852,7 @@ ConnReadLine(Connection *Conn, char *Line, int Length) } } - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &count); if (count > 0) { cur = c->receive.read = c->receive.buffer; limit = c->receive.write = cur + count; @@ -989,7 +982,7 @@ ConnReadAnswer(Connection *Conn, char *Line, int Length) } } - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &count); if (count > 0) { cur = c->receive.read = c->receive.buffer; limit = c->receive.write = cur + count; @@ -1136,7 +1129,7 @@ ConnReadToAllocatedBuffer(Connection *c, char **buffer, unsigned long *bufferSiz c->receive.remaining = CONN_TCP_MTU; c->receive.write[0] = '\0'; - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &count); if (count <= 0) { break; } @@ -1183,7 +1176,7 @@ ConnReadToAllocatedBuffer(Connection *c, char **buffer, unsigned long *bufferSiz } } - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &count); if (count <= 0) { c->send.remaining = 0; c->send.read = c->send.write; @@ -1202,9 +1195,9 @@ ConnReadToAllocatedBuffer(Connection *c, char **buffer, unsigned long *bufferSiz int ConnReadToFile(Connection *Conn, FILE *Dest, int Count) { - register size_t buffered; - register size_t remaining; - register Connection *c = Conn; + size_t buffered; + size_t remaining; + Connection *c = Conn; remaining = Count; while (remaining > 0) { @@ -1240,7 +1233,7 @@ ConnReadToFile(Connection *Conn, FILE *Dest, int Count) } } - CONN_TCP_RECEIVE(c, c->receive.write, c->receive.remaining, buffered); + ConnTcpRead(c, c->receive.write, c->receive.remaining, &buffered); if (buffered > 0) { c->receive.write += buffered; c->receive.remaining -= buffered; @@ -1350,7 +1343,7 @@ ConnReadToFileUntilEOS(Connection *Src, FILE *Dest) Src->receive.write[0] = '\0'; } - CONN_TCP_RECEIVE(Src, Src->receive.write, Src->receive.remaining, count); + ConnTcpRead(Src, Src->receive.write, Src->receive.remaining, &count); if (count > 0) { Src->receive.read = Src->receive.buffer; Src->receive.write += count; @@ -1369,14 +1362,14 @@ ConnReadToFileUntilEOS(Connection *Src, FILE *Dest) int ConnReadToConn(Connection *Src, Connection *Dest, int Count) { - size_t sent; + unsigned int sent; size_t buffered; size_t remaining; Connection *s = Src; Connection *d = Dest; if ((remaining = Count) > 0) { - CONN_TCP_FLUSH(d, d->send.read, d->send.write, sent); + ConnTcpFlush(d, d->send.read, d->send.write, &sent); if (sent >= 0) { d->send.read = d->send.write = d->send.buffer; d->send.remaining = CONN_TCP_MTU; @@ -1393,7 +1386,7 @@ ConnReadToConn(Connection *Src, Connection *Dest, int Count) buffered = s->receive.write - s->receive.read; if (buffered > 0) { if (remaining <= buffered) { - CONN_TCP_SEND(d, s->receive.read, remaining, sent); + ConnTcpWrite(d, s->receive.read, remaining, &sent); if (sent == remaining) { s->receive.read += sent; if (s->receive.read == s->receive.write) { @@ -1410,7 +1403,7 @@ ConnReadToConn(Connection *Src, Connection *Dest, int Count) } if ((remaining > s->receive.remaining) && (s->receive.remaining < CONN_TCP_THRESHOLD)) { - CONN_TCP_SEND(d, s->receive.read, buffered, sent); + ConnTcpWrite(d, s->receive.read, buffered, &sent); if (sent == buffered) { remaining -= sent; @@ -1424,7 +1417,7 @@ ConnReadToConn(Connection *Src, Connection *Dest, int Count) } } - CONN_TCP_RECEIVE(s, s->receive.write, s->receive.remaining, buffered); + ConnTcpRead(s, s->receive.write, s->receive.remaining, &buffered); if (buffered > 0) { s->receive.write += buffered; s->receive.remaining -= buffered; @@ -1443,12 +1436,12 @@ int ConnReadToConnUntilEOS(Connection *Src, Connection *Dest) { int written = 0; - size_t count; + unsigned int count; char *cur; char *limit; BOOL finished = FALSE; - CONN_TCP_FLUSH(Dest, Dest->send.read, Dest->send.write, count); + ConnTcpFlush(Dest, Dest->send.read, Dest->send.write, &count); if (count >= 0) { Dest->send.read = Dest->send.write = Dest->send.buffer; Dest->send.remaining = CONN_TCP_MTU; @@ -1488,7 +1481,7 @@ ConnReadToConnUntilEOS(Connection *Src, Connection *Dest) } if (Src->receive.read < cur) { - CONN_TCP_FLUSH(Dest, Src->receive.read, cur, count); + ConnTcpFlush(Dest, Src->receive.read, cur, &count); if ((size_t)(cur - Src->receive.read) == count) { written += count; @@ -1520,7 +1513,7 @@ ConnReadToConnUntilEOS(Connection *Src, Connection *Dest) } } - CONN_TCP_RECEIVE(Src, Src->receive.write, Src->receive.remaining, count); + ConnTcpRead(Src, Src->receive.write, Src->receive.remaining, &count); if (count > 0) { Src->receive.read = Src->receive.buffer; Src->receive.write += count; @@ -1535,14 +1528,14 @@ ConnReadToConnUntilEOS(Connection *Src, Connection *Dest) return(written); } - + int ConnWrite(Connection *Conn, const char *Buffer, int Length) { - register const char *b; - register int i; - register size_t r; - register Connection *c = Conn; + const char *b; + int i; + size_t r; + Connection *c = Conn; b = Buffer; r = Length; @@ -1564,7 +1557,7 @@ ConnWrite(Connection *Conn, const char *Buffer, int Length) c->send.write += c->send.remaining; - CONN_TCP_FLUSH(c, c->send.read, c->send.write, i); + ConnTcpFlush(c, c->send.read, c->send.write, &i); if (i > 0) { c->send.read = c->send.write = c->send.buffer; c->send.remaining = CONN_TCP_MTU; @@ -1579,7 +1572,7 @@ ConnWrite(Connection *Conn, const char *Buffer, int Length) } do { - CONN_TCP_FLUSH(c, b, b + r, i); + ConnTcpFlush(c, b, b + r, &i); if (i > 0) { b += r; r -= r; @@ -1599,10 +1592,10 @@ ConnWrite(Connection *Conn, const char *Buffer, int Length) int ConnWriteFromFile(Connection *Conn, FILE *Source, int Count) { - register int i; - register size_t n; - register size_t r; - register Connection *c = Conn; + int i; + size_t n; + size_t r; + Connection *c = Conn; r = Count; while (r > 0) { @@ -1623,7 +1616,7 @@ ConnWriteFromFile(Connection *Conn, FILE *Source, int Count) return(-1); } - CONN_TCP_FLUSH(c, c->send.read, c->send.write, i); + ConnTcpFlush(c, c->send.read, c->send.write, &i); if (i > 0) { c->send.read = c->send.write = c->send.buffer; c->send.remaining = CONN_TCP_MTU; @@ -1641,11 +1634,11 @@ ConnWriteFromFile(Connection *Conn, FILE *Source, int Count) int ConnWriteFile(Connection *Conn, FILE *Source) { - register int i; - register size_t n; - register size_t r; - register Connection *c = Conn; - + int i; + size_t n; + size_t r; + Connection *c = Conn; + n = 0; r = c->send.remaining; do { @@ -1659,21 +1652,21 @@ ConnWriteFile(Connection *Conn, FILE *Source) return(-1); } } - + n += c->send.write - c->send.read; - - CONN_TCP_FLUSH(c, c->send.read, c->send.write, i); + + ConnTcpFlush(c, c->send.read, c->send.write, &i); if (i > 0) { c->send.read = c->send.write = c->send.buffer; - c->send.remaining = CONN_TCP_MTU; + c->send.remaining = r = CONN_TCP_MTU; c->send.write[0] = '\0'; continue; } - + return(-1); } while (!feof(Source) && !ferror(Source)); - + return(n); } @@ -1717,7 +1710,7 @@ ConnWriteVF(Connection *c, const char *format, va_list ap) va_end(ap2); } - CONN_TCP_FLUSH(c, c->send.read, c->send.write, i); + ConnTcpFlush(c, c->send.read, c->send.write, &i); if (i > 0) { c->send.read = c->send.write = c->send.buffer; c->send.remaining = CONN_TCP_MTU; @@ -1746,10 +1739,10 @@ ConnWriteF(Connection *conn, const char *Format, ...) int ConnFlush(Connection *Conn) { - register int count; - register Connection *c = Conn; + int count; + Connection *c = Conn; - CONN_TCP_FLUSH(c, c->send.read, c->send.write, count); + ConnTcpFlush(c, c->send.read, c->send.write, &count); if (count >= 0) { c->send.read += count; diff --git a/src/libs/connio/sockets.c b/src/libs/connio/sockets.c new file mode 100644 index 0000000..cb3198e --- /dev/null +++ b/src/libs/connio/sockets.c @@ -0,0 +1,187 @@ + +#include +#include +#include +#include +#include +#include "config.h" + +void +CHOP_NEWLINE(unsigned char *s) +{ + unsigned char *p; + p = strchr(s, 0x0A); + if (p) { + *p = '\0'; + } + p = strrchr(s, 0x0D); + if (p) { + *p = '\0'; + } +} + +void +SET_POINTER_TO_VALUE(unsigned char *p, unsigned char *s) +{ + // FIXME: Unused? + p = s; + while(isspace(*p)) { + p++; + } + if ((*p == '=') || (*p == ':')) { + p++; + } + while(isspace(*p)) { + p++; + } +} + +void +ConnTcpFlush(Connection *c, char *b, char *e, int *r) +{ + if (b < e) { + char *curPTR = (char *)b; + while (curPTR < e) { + ConnTcpWrite(c, curPTR, e - curPTR, r); + if (*r > 0) { + curPTR = curPTR + (int)*r; + continue; + } + break; + } + if (curPTR == e) { + *r = e - b; + } else { + b = -1; + } + } else { + *r = 0; + } +} + +void +ConnTcpClose(Connection *c) +{ + if (c->receive.buffer) { + c->receive.remaining = CONN_TCP_MTU; + } else { + c->receive.remaining = 0; + } + c->receive.read = c->receive.write = c->receive.buffer; + if (c->send.buffer) { + ConnFlush(c); + c->send.remaining = CONN_TCP_MTU; + } else { + c->send.remaining = 0; + } + c->send.read = c->send.write = c->send.buffer; + if (c->ssl.enable) { + gnutls_bye(c->ssl.context, GNUTLS_SHUT_RDWR); + gnutls_deinit(c->ssl.context); + c->ssl.context = NULL; + c->ssl.enable = FALSE; + } + if (c->socket != -1) { + IPshutdown(c->socket, 2); + IPclose(c->socket); + c->socket = -1; + } +} + +//#if defined(S390RH) || defined(SOLARIS) + +// TODO: is this correct for Solaris? + +void +ConnTcpRead(Connection *c, char *b, size_t l, int *r) +{ + struct pollfd pfd; + do { + pfd.fd = (int)c->socket; + pfd.events = POLLIN; + *r = poll(&pfd, 1, c->receive.timeOut * 1000); + if (*r > 0) { + if ((pfd.revents & (POLLIN | POLLPRI))) { + do { + if (!c->ssl.enable) { + *r = IPrecv((c)->socket, b, l, 0); + } else { + *r = gnutls_record_recv(c->ssl.context, (void *)b, l); + } + if (*r >= 0) { + CONN_TRACE_DATA(c, CONN_TRACE_EVENT_READ, b, r); + break; + } else if (errno == EINTR) { + continue; + } + CONN_TRACE_ERROR(c, "RECV", r); + break; + } while (TRUE); + break; + } else if ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL))) { + CONN_TRACE_ERROR(c, "POLL EVENT", r); + *r = -2; + break; + } + } + if (errno == EINTR) { + continue; + } + CONN_TRACE_ERROR(c, "POLL", r); + *r = -3; + break; + } while (TRUE); +} + +void +ConnTcpWrite(Connection *c, char *b, size_t l, int *r) +{ + do { + if (!c->ssl.enable) { + *r = IPsend(c->socket, b, l, MSG_NOSIGNAL); + } else { + *r = gnutls_record_send(c->ssl.context, (void *)b, l); + } + if (*r >= 0) { + CONN_TRACE_DATA(c, CONN_TRACE_EVENT_WRITE, b, r); + break; + } else if (errno == EINTR) { + continue; + } + CONN_TRACE_ERROR(c, "POLL", r); + *r = -1; + break; + } while (TRUE); +} + +//#else +#if 0 + +void +ConnTcpRead(Connection *c, char *b, size_t l, int *r) +{ + fd_set rfds; + struct timeval timeout; + FD_ZERO(&rfds); + FD_SET(c->socket, &rfds); + timeout.tv_usec = 0; + timeout.tv_sec = c->receive.timeOut; + *r = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout); + if (*r > 0) { + *r = recv(c->socket, b, l, 0); + CONN_TRACE_DATA_AND_ERROR(c, CONN_TRACE_EVENT_READ, b, *r, "RECV"); + } else { + CONN_TRACE_ERROR(c, "SELECT", *r); + *r = -1; + } +} + +void +ConnTcpWrite(Connection *c, char *b, size_t l, int *r) +{ + *r = IPsend(c->socket, b, l, 0); + CONN_TRACE_DATA_AND_ERROR(c, CONN_TRACE_EVENT_WRITE, b, *r, "SEND"); +} + + +#endif diff --git a/src/libs/connio/tests/Bongo.rules b/src/libs/connio/tests/Bongo.rules index f44e097..b10cc56 100644 --- a/src/libs/connio/tests/Bongo.rules +++ b/src/libs/connio/tests/Bongo.rules @@ -2,15 +2,13 @@ TESTS += checktest-connio check_PROGRAMS += checktest-connio -checktest_connio_SOURCES := \ +checktest_connio_SOURCES = \ src/libs/connio/tests/checktest.c -checktest_connio_LDADD := $(CHECK_LIBS) \ +checktest_connio_LDADD = $(CHECK_LIBS) \ libbongoconnio.la \ libbongonmap.la \ - libbongomanagement.la \ libbongomsgapi.la \ - libbongomdb.la \ libbongologger.la \ libbongomemmgr.la \ libbongoutil.la \ diff --git a/src/libs/json/json.c b/src/libs/json/json.c index aae8792..2ea6f03 100644 --- a/src/libs/json/json.c +++ b/src/libs/json/json.c @@ -171,7 +171,7 @@ BongoJsonJPathGetFloat(BongoJsonNode *n, const char *path, float *val) { return BONGO_JSON_BAD_TYPE; } BongoJsonResult -BongoJsonJPathGetString(BongoJsonNode *n, const char *path, const char **val) { +BongoJsonJPathGetString(BongoJsonNode *n, const char *path, char **val) { // caller must free the memory allocated BongoJsonNode *result = BongoJsonJPath(n, path); if (!result) return BONGO_JSON_NOT_FOUND; diff --git a/src/libs/logger/Bongo.rules b/src/libs/logger/Bongo.rules index 44505ca..c4aeccf 100644 --- a/src/libs/logger/Bongo.rules +++ b/src/libs/logger/Bongo.rules @@ -1,19 +1,19 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongologger.la -logconfdir := $(XPL_DEFAULT_CONF_DIR) +logconfdir = $(XPL_DEFAULT_CONF_DIR) -dist_logconf_DATA := \ +dist_logconf_DATA = \ src/libs/logger/logs.conf -libbongologger_la_SOURCES := \ +libbongologger_la_SOURCES = \ src/libs/logger/bongo.lsc \ src/libs/logger/logger-format.pl \ src/libs/logger/logger.c \ src/libs/logger/logger-format.c \ src/libs/logger/loggerp.h -libbongologger_la_LIBADD := \ +libbongologger_la_LIBADD = \ libbongoxpl.la \ $(DL_LIBS) diff --git a/src/libs/logger/logs.conf b/src/libs/logger/logs.conf index e5207bd..8dc6a04 100644 --- a/src/libs/logger/logs.conf +++ b/src/libs/logger/logs.conf @@ -10,23 +10,19 @@ 1 + diff --git a/src/libs/management/Bongo.rules b/src/libs/management/Bongo.rules index d91e2f3..d0f20b8 100644 --- a/src/libs/management/Bongo.rules +++ b/src/libs/management/Bongo.rules @@ -1,12 +1,12 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongomanagement.la -#libbongomanagement_la_LDFLAGS := -static -libbongomanagement_la_SOURCES := \ +#libbongomanagement_la_LDFLAGS = -static +libbongomanagement_la_SOURCES = \ src/libs/management/bongomanagee.c \ src/libs/management/managee.c -libbongomanagement_la_LIBADD := libbongoutil.la libbongo-json.la +libbongomanagement_la_LIBADD = libbongoutil.la libbongo-json.la src/libs/management/all: libbongomanagement.la src/libs/management/clean: clean diff --git a/src/libs/management/managee.c b/src/libs/management/managee.c index 55c458e..dc63c87 100644 --- a/src/libs/management/managee.c +++ b/src/libs/management/managee.c @@ -632,11 +632,7 @@ ManagementInit(const unsigned char *Identity, MDBHandle DirectoryHandle) MDBFreeValues(config); } - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, config)) { - result = HashCredential(Management.dmc.dn, config->Value[0], Management.dmc.credential); - - MDBFreeValues(config); - } + MsgGetServerCredential(&Management.dmc.credential); } if (config) { diff --git a/src/libs/mdb-odbc/Makefile.am b/src/libs/mdb-odbc/Makefile.am deleted file mode 100644 index 84464a4..0000000 --- a/src/libs/mdb-odbc/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -INCLUDES= \ - $(ALL_CFLAGS) \ - -I$(top_srcdir)/include \ - -DLOCALSTATEDIR=\""$(localstatedir)"\" \ - -DMDB_INTERNAL - -LIBS= -lodbc - -mdbdir=$(libdir)/bongomdb - -mdb_LTLIBRARIES=libmdbodbc.la - -libmdbodbc_la_SOURCES = \ - mdbodbc.c \ - mdbodbcp.h - -libmdbodbc_la_LDFLAGS = -module -avoid-version -libmdbodbc_la_LIBADD = \ - ../bongoutil/libbongoutil.la \ - ../xpl/libbongoxpl.la diff --git a/src/libs/mdb-odbc/mdbodbc.c b/src/libs/mdb-odbc/mdbodbc.c deleted file mode 100644 index 4c6ca10..0000000 --- a/src/libs/mdb-odbc/mdbodbc.c +++ /dev/null @@ -1,4466 +0,0 @@ -/* Product defines */ -#define PRODUCT_NAME "MDB ODBC Driver" -#define PRODUCT_VERSION "$Revision: 1.1 $" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "mdbodbcp.h" -#include - -struct { - BOOL unload; - - struct { - XplSemaphore shutdown; - } sem; - - struct { - XplThreadID main; - XplThreadID group; - } id; - - struct { - unsigned char dsn[256 + 1]; - unsigned char user[256 + 1]; - unsigned char pass[256 + 1]; - unsigned char servername[64 + 1]; - unsigned char treename[64 + 1]; - unsigned long treenameLength; - - SQLINTEGER defaultContext; - - /* Special Attibutes, which require extra actions */ - struct { - SQLINTEGER member; - } special; - } config; - - SQLHENV env; -} MDBodbc; - -/* Prototypes for registration functions */ - -BOOL MDBodbcGetServerInfo(unsigned char *ServerDN, unsigned char *ServerTree, MDBValueStruct *V); -char *MDBodbcGetServerInfo(MDBValueStruct *V); -MDBHandle MDBodbcAuthenticate(const unsigned char *Object, const unsigned char *Password, const unsigned char *Arguments); -BOOL MDBodbcRelease(MDBHandle Context); -MDBValueStruct *MDBodbcCreateValueStruct(MDBHandle Handle, const unsigned char *Context); -BOOL MDBodbcFreeValues(MDBValueStruct *V); -BOOL MDBodbcDestroyValueStruct(MDBValueStruct *V); -MDBEnumStruct *MDBodbcCreateEnumStruct(MDBValueStruct *V); -BOOL MDBodbcDestroyEnumStruct(MDBEnumStruct *ES, MDBValueStruct *V); -BOOL MDBodbcSetValueStructContext(const unsigned char *Context, MDBValueStruct *V); -MDBValueStruct *MDBodbcShareContext(MDBValueStruct *V); -BOOL MDBodbcAddValue(const unsigned char *Value, MDBValueStruct *V); -BOOL MDBodbcFreeValue(unsigned long Index, MDBValueStruct *V); -BOOL MDBodbcDefineAttribute(const unsigned char *Attribute, const unsigned char *ASN1, unsigned long Type, BOOL SingleValue, BOOL ImmediateSync, BOOL Public, MDBValueStruct *V); -BOOL MDBodbcAddAttribute(const unsigned char *Attribute, const unsigned char *Class, MDBValueStruct *V); -BOOL MDBodbcUndefineAttribute(const unsigned char *Attribute, MDBValueStruct *V); -BOOL MDBodbcDefineClass(const unsigned char *Class, const unsigned char *ASN1, BOOL Container, MDBValueStruct *Superclass, MDBValueStruct *Containment, MDBValueStruct *Naming, MDBValueStruct *Mandatory, MDBValueStruct *Optional, MDBValueStruct *V); -BOOL MDBodbcUndefineClass(const unsigned char *Class, MDBValueStruct *V); -static __inline BOOL MDBodbcUndefineClassByID(unsigned long class, MDBValueStruct *V); -BOOL MDBodbcListContainableClasses(const unsigned char *Object, MDBValueStruct *V); -BOOL MDBodbcWriteTyped(const unsigned char *Object, const unsigned char *Attribute, const int AttrType, MDBValueStruct *V); -BOOL MDBodbcWrite(const unsigned char *Object, const unsigned char *AttributeIn, MDBValueStruct *V); -BOOL MDBodbcWriteDN(const unsigned char *Object, const unsigned char *AttributeIn, MDBValueStruct *V); -BOOL MDBodbcAdd(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V); -BOOL MDBodbcAddDN(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V); -BOOL MDBodbcRemove(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V); -BOOL MDBodbcRemoveDN(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V); -BOOL MDBodbcClear(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V); -BOOL MDBodbcIsObject(const unsigned char *Object, MDBValueStruct *V); -BOOL MDBodbcGetObjectDetails(const unsigned char *Object, unsigned char *Type, unsigned char *RDN, unsigned char *DN, MDBValueStruct *V); -BOOL MDBodbcGetObjectDetailsEx(const unsigned char *Object, MDBValueStruct *Types, unsigned char *RDN, unsigned char *DN, MDBValueStruct *V); -BOOL MDBodbcVerifyPassword(const unsigned char *Object, const unsigned char *Password, MDBValueStruct *V); -BOOL MDBodbcChangePassword(const unsigned char *Object, const unsigned char *OldPassword, const unsigned char *NewPassword, MDBValueStruct *V); -BOOL MDBodbcChangePasswordEx(const unsigned char *Object, const unsigned char *OldPassword, const unsigned char *NewPassword, MDBValueStruct *V); -BOOL MDBodbcCreateAlias(const unsigned char *Alias, const unsigned char *AliasedObjectDn, MDBValueStruct *V); -BOOL MDBodbcCreateObject(const unsigned char *Object, const unsigned char *Class, MDBValueStruct *Attribute, MDBValueStruct *Data, MDBValueStruct *V); -BOOL MDBodbcDeleteObject(const unsigned char *Object, BOOL Recursive, MDBValueStruct *V); -static __inline BOOL MDBodbcDeleteObjectByID(signed long id, BOOL Recursive, MDBValueStruct *V); -BOOL MDBodbcRenameObject(const unsigned char *ObjectOld, const unsigned char *ObjectNew, MDBValueStruct *V); -BOOL MDBodbcGrantObjectRights(const unsigned char *Object, const unsigned char *TrusteeDN, BOOL Read, BOOL Write, BOOL Delete, BOOL Rename, BOOL Admin, MDBValueStruct *V); -BOOL MDBodbcGrantAttributeRights(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *TrusteeDN, BOOL Read, BOOL Write, BOOL Admin, MDBValueStruct *V); - -const unsigned char *MDBodbcListContainableClassesEx(const unsigned char *Object, MDBEnumStruct *E, MDBValueStruct *V); -const unsigned char *MDBodbcReadEx(const unsigned char *Object, const unsigned char *Attribute, MDBEnumStruct *E, MDBValueStruct *V); -const unsigned char *MDBodbcEnumerateAttributesEx(const unsigned char *Object, MDBEnumStruct *E, MDBValueStruct *V); -const unsigned char *MDBodbcEnumerateObjectsEx(const unsigned char *Container, const unsigned char *Type, const unsigned char *Pattern, unsigned long Flags, MDBEnumStruct *E, MDBValueStruct *V); - -long MDBodbcRead(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V); -long MDBodbcEnumerateObjects(const unsigned char *Container, const unsigned char *Type, const unsigned char *Pattern, MDBValueStruct *V); - -EXPORT BOOL MDBODBCInit(MDBDriverInitStruct *Init); -EXPORT void MDBODBCShutdown(void); - -void PrintSQLError(MDBValueStruct *V, HSTMT stmt); -static __inline BOOL MDBodbcGetObjectID(const unsigned char *dn, SQLINTEGER *id, SQLINTEGER *class, BOOL *read, BOOL *write, BOOL *delete, BOOL *rename, MDBValueStruct *V); -static __inline BOOL MDBodbcGetObjectDN(unsigned char *dn, const unsigned long maxlength, const signed long id, BOOL relative, MDBValueStruct *V); -static __inline BOOL MDBodbcWriteAny(const unsigned char *Object, const unsigned char *Attribute, const unsigned char Type, const BOOL clear, const unsigned char *Value, MDBValueStruct *V); - -/* Prototype for placeholder */ -BOOL MWHandleNamedTemplate(void *ignored1, unsigned char *ignored2, void *ignored3); - -#define PrepareStatement(stmt, sql, requireBindings, V) \ -{ \ - (requireBindings) = FALSE; \ - \ - if ((stmt) == SQL_NULL_HSTMT) { \ - signed long prepareRC; \ - \ - prepareRC = SQLAllocHandle(SQL_HANDLE_STMT, (V)->handle->connection, &(stmt)); \ - if (prepareRC == SQL_SUCCESS || prepareRC == SQL_SUCCESS_WITH_INFO) { \ - prepareRC = SQLPrepare((stmt), (sql), SQL_NTS); \ - (V)->statementCount++; \ - } \ - \ - if (prepareRC == SQL_SUCCESS || prepareRC == SQL_SUCCESS_WITH_INFO) { \ - (requireBindings) = TRUE; \ - } \ - } \ -} - -#define ReleaseStatement(V, stmt) \ -{ \ - if ((stmt) != SQL_NULL_HSTMT) { \ - (V)->statementCount--; \ - SQLFreeHandle(SQL_HANDLE_STMT, (stmt)); \ - } \ -} - -#ifdef DEBUG -#define ExecuteStatement(stmt) (printf("%s:%d\n", __FILE__, __LINE__) && \ - DebugExecuteStatement((stmt))) - -static __inline SQLRETURN -DebugExecuteStatement(SQLHSTMT stmt) -{ - SQLRETURN rc = SQLExecute(stmt); - if (rc < 0) { - PrintSQLError(NULL, stmt); - } - - return(rc); -} -#else -#define ExecuteStatement(stmt) SQLExecute((stmt)) -#endif - -#define BindLongInput(stmt, position, paramAddr) \ -{ \ - SQLBindParameter((stmt), (position), SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, \ - 0, 0, (paramAddr), 0, NULL); \ -} - -#define BindCharInput(stmt, position, stringAddr, lengthAddr, size) \ -{ \ - SQLBindParameter((stmt), (position), SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, \ - (size), 0, (stringAddr), 0, (lengthAddr)); \ -} - -#define BindLongResult(stmt, position, resultAddr) \ -{ \ - SQLBindCol((stmt), (position), SQL_C_ULONG, (resultAddr), 0, NULL); \ -} - -#define BindCharResult(stmt, position, resultAddr, resultSize) \ -{ \ - SQLBindCol((stmt), (position), SQL_C_CHAR, &resultAddr, resultSize, NULL); \ -} - -#define StoreCharInput(string, stringAddr, length, maxLength) \ -{ \ - (length) = strlen((string)); \ - if ((length) >= (maxLength)) { \ - (length) = (maxLength); \ - } \ - \ - strncpy((stringAddr), (string), (length)); \ - (stringAddr)[(length)] = '\0'; \ -} - - -#define PrintSQLErr(V, stmt) \ -{ \ - XplConsolePrintf("SQL Error\n %s:%d\n", __FILE__, __LINE__); \ - \ - PrintSQLError((V), (stmt)); \ -} - -void -PrintSQLError(MDBValueStruct *V, HSTMT stmt) -{ - SQLCHAR state[6]; - SQLCHAR msg[SQL_MAX_MESSAGE_LENGTH]; - SQLSMALLINT len; - SQLINTEGER nativeError; - SQLSMALLINT i; - SQLRETURN rc; - - i = 1; - if (MDBodbc.env != SQL_NULL_HENV) { - while ((rc = SQLGetDiagRec(SQL_HANDLE_ENV, (SQLHANDLE)MDBodbc.env, i, state, &nativeError, - msg, sizeof(msg), &len)) == SQL_SUCCESS) - { - XplConsolePrintf(" SQLSTATE = %s\n", state); - XplConsolePrintf(" NATIVE ERROR = %ld\n", nativeError); - XplConsolePrintf(" MSG = %s\n\n", msg); - - i++; - } - } - - if (V && V->handle && V->handle->connection != SQL_NULL_HDBC) { - i = 1; - while ((rc = SQLGetDiagRec(SQL_HANDLE_DBC, (SQLHANDLE)V->handle->connection, i, state, &nativeError, - msg, sizeof(msg), &len)) != SQL_NO_DATA) - { - XplConsolePrintf(" SQLSTATE = %s\n", state); - XplConsolePrintf(" NATIVE ERROR = %ld\n", nativeError); - XplConsolePrintf(" MSG = %s\n\n", msg); - - i++; - } - } - - if (stmt != SQL_NULL_HSTMT) { - i = 1; - while ((rc = SQLGetDiagRec(SQL_HANDLE_STMT, (SQLHANDLE)stmt, i, state, &nativeError, - msg, sizeof(msg), &len)) != SQL_NO_DATA) - { - XplConsolePrintf(" SQLSTATE = %s\n", state); - XplConsolePrintf(" NATIVE ERROR = %ld\n", nativeError); - XplConsolePrintf(" MSG = %s\n\n", msg); - - i++; - } - } -} - -static __inline BOOL -MDBodbcGetObjectID(const unsigned char *dn, SQLINTEGER *id, SQLINTEGER *class, BOOL *read, BOOL *write, BOOL *delete, BOOL *rename, MDBValueStruct *V) -{ - if (dn && id) { - SQLINTEGER rc; - BOOL requireBindings; - BOOL r; - BOOL w; - BOOL d; - BOOL n; - unsigned long now = time(NULL); - - if (now <= V->cache.time + 5 && XplStrCaseCmp(dn, V->cache.dn) == 0) { - /* The value is in the cache, and is still valid */ - if (read) { - *read = V->cache.read; - } - - if (write) { - *write = V->cache.write; - } - - if (delete) { - *delete = V->cache.delete; - } - - if (rename) { - *rename = V->cache.rename; - } - - if (class) { - *class = V->cache.class; - } - - *id = V->cache.id; - - return(TRUE); - } - - PrepareStatement(V->stmts.getRootRights, SQL_GET_ROOT_RIGHTS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getRootRights, 1, &V->handle->object); - - BindLongResult(V->stmts.getRootRights, 1, &V->params.getRootRights.read); - BindLongResult(V->stmts.getRootRights, 2, &V->params.getRootRights.write); - BindLongResult(V->stmts.getRootRights, 3, &V->params.getRootRights.delete); - BindLongResult(V->stmts.getRootRights, 4, &V->params.getRootRights.rename); - } - - PrepareStatement(V->stmts.getObjectID, SQL_GET_OBJECT_ID, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getObjectID, 1, - &V->params.getObjectID.object, &V->params.getObjectID.objectLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.getObjectID, 2, &V->params.getObjectID.id); - BindLongInput(V->stmts.getObjectID, 3, &V->handle->object); - - /* Resulting object id */ - BindLongResult(V->stmts.getObjectID, 1, &V->params.getObjectID.id); - BindLongResult(V->stmts.getObjectID, 2, &V->params.getObjectID.class); - - /* Rights if specified */ - BindLongResult(V->stmts.getObjectID, 3, &V->params.getObjectID.read); - BindLongResult(V->stmts.getObjectID, 4, &V->params.getObjectID.write); - BindLongResult(V->stmts.getObjectID, 5, &V->params.getObjectID.delete); - BindLongResult(V->stmts.getObjectID, 6, &V->params.getObjectID.rename); - } - - if (V->stmts.getObjectID != SQL_NULL_HSTMT) { - unsigned char *s = (unsigned char *)dn; - unsigned char *e; - - if (*s == '\\') { - - /* - Check for rights assigned to this object at the root. If there are any, use those. If not then - use the default, (ie readonly). - */ - rc = ExecuteStatement(V->stmts.getRootRights); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getRootRights); - SQLCloseCursor(V->stmts.getRootRights); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - r = V->params.getRootRights.read; - w = V->params.getRootRights.write; - d = V->params.getRootRights.delete; - n = V->params.getRootRights.rename; - } else { - /* Set the default rights */ - r = TRUE; - w = FALSE; - d = FALSE; - n = FALSE; - } - - V->params.getObjectID.id = MDB_ODBC_ROOT_ID; - s++; - } else { - V->params.getObjectID.id = *V->base.id; - - /* Set the default rights */ - r = *V->base.read; - w = *V->base.write; - d = *V->base.delete; - n = *V->base.rename; - } - - do { - while (*s == '\\') { - s++; - } - - e = strchr(s, '\\'); - - if (*s) { - V->params.getObjectID.objectLength = (e) ? (unsigned long) (e - s) : strlen(s); - if (V->params.getObjectID.objectLength >= MDB_ODBC_NAME_SIZE) { - V->params.getObjectID.objectLength = MDB_ODBC_NAME_SIZE; - } - - strncpy(V->params.getObjectID.object, s, V->params.getObjectID.objectLength); - V->params.getObjectID.object[V->params.getObjectID.objectLength] = '\0'; - } else { - V->params.getObjectID.objectLength = strlen(MDBodbc.config.treename); - strcpy(V->params.getObjectID.object, MDBodbc.config.treename); - } - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.getObjectID); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getObjectID); - SQLCloseCursor(V->stmts.getObjectID); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (V->params.getObjectID.read >= 0) { - r = (V->params.getObjectID.read == 1); - } - - if (V->params.getObjectID.write >= 0) { - w = (V->params.getObjectID.write == 1); - } - - if (V->params.getObjectID.delete >= 0) { - d = (V->params.getObjectID.delete == 1); - } - - if (V->params.getObjectID.rename >= 0) { - n = (V->params.getObjectID.rename == 1); - } - } - } - - s = e; - } while (s && *(s++) && (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - *id = V->params.getObjectID.id; - - if (class) { - *class = V->params.getObjectID.class; - } - - if (read) { - *read = r; - } - - if (write) { - *write = w; - } - - if (delete) { - *delete = d; - } - - if (rename) { - *rename = n; - } - - /* Store the cached value */ - V->cache.read = r; - V->cache.write = w; - V->cache.delete = d; - V->cache.rename = n; - - V->cache.id = *id; - V->cache.class = V->params.getObjectID.class; - V->cache.time = now; - - strcpy(V->cache.dn, dn); - - return(TRUE); - } - } - } - - V->ErrNo = ERR_NO_SUCH_ENTRY; - - return(FALSE); -} - -static __inline BOOL MDBodbcGetObjectDN(unsigned char *dn, const unsigned long maxlength, const signed long id, BOOL relative, MDBValueStruct *V) -{ - unsigned char *s = dn; - signed long i; - signed long u; - BOOL requireBindings; - BOOL result = TRUE; - - if (!dn || !V) { - return(FALSE); - } - - u = (signed long) V->Used; - - PrepareStatement(V->stmts.getParentInfo, SQL_GET_PARENT_INFO, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getParentInfo, 1, &V->params.getParentInfo.object); - BindLongResult(V->stmts.getParentInfo, 1, &V->params.getParentInfo.object); - BindCharResult(V->stmts.getParentInfo, 2, V->params.getParentInfo.name, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.getParentInfo == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.getParentInfo.object = id; - - do { - SQLINTEGER rc; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.getParentInfo); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getParentInfo); - SQLCloseCursor(V->stmts.getParentInfo); - } - - if (V->params.getParentInfo.object == id) { - /* We need to be sure we are not looping */ - break; - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbcAddValue(V->params.getParentInfo.name, V); - } else { - result = FALSE; - break; - } - } while (V->params.getParentInfo.object != -1 && (!relative || V->params.getParentInfo.object != *(V->base.id))); - - /* If relative is true, then we can be relative even to the root */ - if (V->params.getParentInfo.object == -1 && !relative) { - s += sprintf(s, "\\%s\\", MDBodbc.config.treename); - } - - if (result) { - for (i = V->Used - 1; i >= u ; i--) { - if ((s - dn) + strlen(V->Value[i]) < maxlength) { - s += sprintf(s, "%s\\", V->Value[i]); - } else { - result = FALSE; - break; - } - } - } - - if (result) { - /* Cut off the trailing slash */ - *--s = '\0'; - } - - while (V->Used > (unsigned long)u) { - MDBodbcFreeValue(u, V); - } - - return(result); -} - -static __inline BOOL -MDBodbcRemoveInheritedRights(SQLINTEGER trustee, BOOL first, SQLINTEGER provider, MDBValueStruct *V) -{ - SQLHSTMT getChildrenIDs = SQL_NULL_HSTMT; - SQLINTEGER child; - SQLINTEGER rc; - BOOL requireBindings; - - if (first) { - PrepareStatement(V->stmts.getRightsProviders, SQL_GET_RIGHTS_PROVIDERS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getRightsProviders, 1, &V->params.getRightsProviders.trustee); - BindLongResult(V->stmts.getRightsProviders, 1, &V->params.getRightsProviders.provider); - } - - V->params.getRightsProviders.trustee = trustee; - - rc = ExecuteStatement(V->stmts.getRightsProviders); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getRightsProviders); - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcRemoveInheritedRights(trustee, FALSE, V->params.getRightsProviders.provider, V)) { - SQLCloseCursor(V->stmts.getRightsProviders); - return(FALSE); - } - - rc = SQLFetch(V->stmts.getRightsProviders); - } - SQLCloseCursor(V->stmts.getRightsProviders); - } - } else { - PrepareStatement(V->stmts.delRightsByChild, SQL_DEL_RIGHTS_BY_CHILD, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.delRightsByChild, 1, &V->params.delRightsByChild.provider); - BindLongInput(V->stmts.delRightsByChild, 2, &V->params.delRightsByChild.trustee); - } - - V->params.delRightsByChild.provider = provider; - V->params.delRightsByChild.trustee = trustee; - - rc = ExecuteStatement(V->stmts.delRightsByChild); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - /* Get the children */ - PrepareStatement(getChildrenIDs, SQL_GET_CHILDREN_IDS, requireBindings, V); - if (requireBindings) { - BindLongInput(getChildrenIDs, 1, &trustee); - BindLongResult(getChildrenIDs, 1, &child); - } - - if (getChildrenIDs == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(getChildrenIDs); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildrenIDs); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcRemoveInheritedRights(child, FALSE, provider, V)) { - ReleaseStatement(V, getChildrenIDs); - return(FALSE); - } - - rc = SQLFetch(getChildrenIDs); - } - - ReleaseStatement(V, getChildrenIDs); - if (rc != SQL_NO_DATA) { - return(FALSE); - } - } - - return(TRUE); -} - -static __inline BOOL -MDBodbcCopyObjectRights(SQLINTEGER trustee, SQLINTEGER parent, BOOL fromParent, MDBValueStruct *V) -{ - SQLHSTMT getChildrenIDs = SQL_NULL_HSTMT; - SQLINTEGER child; - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.setRights, SQL_SET_RIGHTS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.setRights, 1, &V->params.setGetRights.object); - BindLongInput(V->stmts.setRights, 2, &V->params.setGetRights.trustee); - BindLongInput(V->stmts.setRights, 3, &V->params.setGetRights.provider); - BindLongInput(V->stmts.setRights, 4, &V->params.setGetRights.parent); - BindLongInput(V->stmts.setRights, 5, &V->params.setGetRights.read); - BindLongInput(V->stmts.setRights, 6, &V->params.setGetRights.write); - BindLongInput(V->stmts.setRights, 7, &V->params.setGetRights.delete); - BindLongInput(V->stmts.setRights, 8, &V->params.setGetRights.rename); - } - - PrepareStatement(V->stmts.getRights, SQL_GET_RIGHTS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getRights, 1, &V->params.setGetRights.trustee); - - BindLongResult(V->stmts.getRights, 1, &V->params.setGetRights.provider); - BindLongResult(V->stmts.getRights, 2, &V->params.setGetRights.object); - BindLongResult(V->stmts.getRights, 3, &V->params.setGetRights.read); - BindLongResult(V->stmts.getRights, 4, &V->params.setGetRights.write); - BindLongResult(V->stmts.getRights, 5, &V->params.setGetRights.delete); - BindLongResult(V->stmts.getRights, 6, &V->params.setGetRights.rename); - } - - V->params.setGetRights.trustee = parent; - - /* - Get each set of rights assigned to the parent, and add a copy to each - child. This has to be done as seperate queries because some ODBC drivers - do not support INSERT using data from a SELECT that uses the same table. - */ - rc = ExecuteStatement(V->stmts.getRights); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getRights); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - V->params.setGetRights.trustee = trustee; - V->params.setGetRights.parent = fromParent ? 1 : 0; - - rc = ExecuteStatement(V->stmts.setRights); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getRights); - } - } - - SQLCloseCursor(V->stmts.getRights); - - /* Do the same for all the children */ - PrepareStatement(getChildrenIDs, SQL_GET_CHILDREN_IDS, requireBindings, V); - if (requireBindings) { - BindLongInput(getChildrenIDs, 1, &trustee); - BindLongResult(getChildrenIDs, 1, &child); - } - - if (getChildrenIDs == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(getChildrenIDs); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildrenIDs); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcCopyObjectRights(child, trustee, TRUE, V)) { - ReleaseStatement(V, getChildrenIDs); - return(FALSE); - } - - rc = SQLFetch(getChildrenIDs); - } - - ReleaseStatement(V, getChildrenIDs); - if (rc != SQL_NO_DATA) { - return(FALSE); - } - - return(TRUE); -} - -BOOL -MDBodbcGetServerInfo(unsigned char *ServerDN, unsigned char *ServerTree, MDBValueStruct *V) -{ - signed long server; - MDBHandle handle = NULL; - MDBValueStruct *v; - BOOL result = TRUE; - - if (!V) { - handle = MDBodbcAuthenticate(NULL, NULL, NULL); - v = (handle) ? MDBodbcCreateValueStruct(handle, NULL) : NULL; - } else { - v = V; - } - - if (!v) { - if (handle) { - MDBodbcRelease(handle); - } - - return(FALSE); - } - - if (ServerTree) { - strcpy(ServerTree, MDBodbc.config.treename); - } - - if (ServerDN) { - unsigned long base = *(v->base.id); - *(v->base.id) = MDBodbc.config.defaultContext; - - result = FALSE; - if (MDBodbcGetObjectID(MDBodbc.config.servername, &server, NULL, NULL, NULL, NULL, NULL, v)) { - *(v->base.id) = -1; - - if (MDBodbcGetObjectDN(ServerDN, MDB_MAX_OBJECT_CHARS, server, FALSE, v)) { - result = TRUE; - } - } - - *(v->base.id) = base; - - } - - if (handle) { - MDBodbcDestroyValueStruct(v); - MDBodbcRelease(handle); - } - - return(result); -} - -char * -MDBodbcGetBaseDN(MDBValueStruct *V) -{ - return(MDBodbc.config.treename); -} - - -MDBHandle -MDBodbcAuthenticate(const unsigned char *Object, const unsigned char *Password, const unsigned char *Arguments) -{ - BOOL result = TRUE; - - MDBHandle h = malloc(sizeof(MDBodbcContextStruct)); - - if (h) { - SQLINTEGER rc; - - memset(h, 0, sizeof(MDBodbcContextStruct)); - - rc = SQLAllocHandle(SQL_HANDLE_DBC, MDBodbc.env, &h->connection); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - SQLSetConnectAttr(h->connection, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)30, 0); - SQLSetConnectAttr(h->connection, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0); - - /* Connect to the datasource */ - rc = SQLConnect(h->connection, (SQLCHAR *) MDBodbc.config.dsn, SQL_NTS, - (SQLCHAR *) MDBodbc.config.user, SQL_NTS, - (SQLCHAR *) MDBodbc.config.pass, SQL_NTS); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - /* We now have a connection */ - if (Object) { - MDBValueStruct *V = MDBodbcCreateValueStruct(h, NULL); - - if (!MDBodbcGetObjectID(Object, &h->object, NULL, NULL, NULL, NULL, NULL, V)) { - /* The object doesn't exist here, lets try again in the default container */ - - *(V->base.id) = MDBodbc.config.defaultContext; - if (*Object != '\\' || !MDBodbcGetObjectID(Object, &h->object, NULL, NULL, NULL, NULL, NULL, V)) { - /* The object doesn't exist */ - result = FALSE; - } - } - - if (result && !MDBodbcVerifyPassword(Object, Password, V)) { - /* Wrong password */ - result = FALSE; - } - - MDBodbcDestroyValueStruct(V); - } - - if (result) { - return(h); - } - } - - SQLDisconnect(h->connection); - } - - free(h); - h = NULL; - } - - return(NULL); -} - -BOOL -MDBodbcRelease(MDBHandle Context) -{ - if (Context) { - SQLEndTran(SQL_HANDLE_DBC, Context->connection, SQL_COMMIT); - SQLDisconnect(Context->connection); - SQLFreeHandle(SQL_HANDLE_DBC, Context->connection); - - free(Context); - return(TRUE); - } else { - return(FALSE); - } -} - -MDBValueStruct * -MDBodbcCreateValueStruct(MDBHandle Handle, const unsigned char *Context) -{ - if (Handle) { - MDBValueStruct *v = malloc(sizeof(MDBValueStruct)); - - if (v) { - memset(v, 0, sizeof(MDBValueStruct)); - - v->handle = Handle; - - v->base.id = &(v->base.value); - v->base.class = &(v->base.classValue); - v->base.read = &(v->base.readValue); - v->base.write = &(v->base.writeValue); - v->base.delete = &(v->base.deleteValue); - v->base.rename = &(v->base.renameValue); - - MDBodbcSetValueStructContext(Context, v); - - /* Everything seems to have worked */ - return(v); - } - } - - return(NULL); -} - -BOOL -MDBodbcFreeValues(MDBValueStruct *V) -{ - register unsigned long i; - - if (V->Allocated) { - for (i = 0; i < V->Used; i++) { - free(V->Value[i]); - } - - if (V->Allocated > VALUE_ALLOC_SIZE) { - if (V->Value) { - free(V->Value); - } - - V->Allocated = 0; - V->Value = NULL; - } - - V->Used = 0; - } - - return(TRUE); -} - -BOOL -MDBodbcDestroyValueStruct(MDBValueStruct *V) -{ - if (V) { - unsigned long i; - - for (i = 0; i < (sizeof(V->stmts) / sizeof(SQLHSTMT)); i++) { - ReleaseStatement(V, V->stmts.asArray[i]); - } - - MDBodbcFreeValues(V); - if (V->Value) { - free(V->Value); - } - - if (V->statementCount) { - XplConsolePrintf("This value struct still has %ld statement handles\n", V->statementCount); - } - - free(V); - return(TRUE); - } else { - return(FALSE); - } -} - -MDBEnumStruct * -MDBodbcCreateEnumStruct(MDBValueStruct *V) -{ - if (V) { - MDBEnumStruct *e = malloc(sizeof(MDBEnumStruct)); - - if (e) { - memset(e, 0, sizeof(MDBEnumStruct)); - - return(e); - } - } - - return(NULL); -} - -BOOL -MDBodbcDestroyEnumStruct(MDBEnumStruct *E, MDBValueStruct *V) -{ - if (E) { - ReleaseStatement(V, E->stmt); - - if (E->largeResult) { - free(E->largeResult); - } - - free(E); - return(TRUE); - } else { - return(FALSE); - } -} - -BOOL -MDBodbcSetValueStructContext(const unsigned char *Context, MDBValueStruct *V) -{ - if (V) { - return(MDBodbcGetObjectID(Context ? Context : (unsigned char *)"\\", V->base.id, V->base.class, V->base.read, V->base.write, V->base.delete, V->base.rename, V)); - } - - return(FALSE); -} - -MDBValueStruct * -MDBodbcShareContext(MDBValueStruct *V) -{ - if (V) { - MDBValueStruct *v = malloc(sizeof(MDBValueStruct)); - - if (v) { - memset(v, 0, sizeof(MDBValueStruct)); - - v->base.id = V->base.id; - v->base.class = V->base.class; - v->base.read = V->base.read; - v->base.write = V->base.write; - v->base.delete = V->base.delete; - v->base.rename = V->base.rename; - - v->handle = V->handle; - - return(v); - } - } - - return(NULL); -} - -BOOL -MDBodbcAddValue(const unsigned char *Value, MDBValueStruct *V) -{ - register unsigned char *ptr; - - if (Value && (*Value != '\0')) { - if ((V->Used + 1) > V->Allocated) { - ptr = (unsigned char *)realloc(V->Value, (V->Allocated + VALUE_ALLOC_SIZE) * sizeof(unsigned char *)); - if (ptr) { - V->Value = (unsigned char **)ptr; - V->Allocated += VALUE_ALLOC_SIZE; - } else { - if (V->Allocated) { - MDBodbcFreeValues(V); - - if (V->Value) { - free(V->Value); - } - } - - V->Value = NULL; - - V->Used = 0; - V->Allocated = 0; - - return(FALSE); - } - } - - ptr = strdup(Value); - if (ptr) { - V->Value[V->Used] = ptr; - V->Used++; - - return(TRUE); - } - } - - return(FALSE); -} - -BOOL -MDBodbcFreeValue(unsigned long Index, MDBValueStruct *V) -{ - if (Index < V->Used) { - free(V->Value[Index]); - - if (Index < (V->Used - 1)) { - memmove(&V->Value[Index], &V->Value[Index + 1], ((V->Used - 1) - Index) * sizeof(unsigned char *)); - } - - V->Used--; - - return(TRUE); - } - - return(FALSE); -} - -BOOL -MDBodbcDefineAttribute(const unsigned char *Attribute, const unsigned char *ASN1, unsigned long Type, BOOL Single, BOOL ImmediateSync, BOOL Public, MDBValueStruct *V) -{ - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - if (Attribute) { - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.createAttribute, SQL_CREATE_ATTRIBUTE, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.createAttribute, 1, V->params.createAttribute.name, &V->params.createAttribute.nameLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.createAttribute, 2, &V->params.createAttribute.type); - BindLongInput(V->stmts.createAttribute, 3, &V->params.createAttribute.single); - BindLongInput(V->stmts.createAttribute, 4, &V->params.createAttribute.public); - } - - if (V->stmts.createAttribute != SQL_NULL_HSTMT) { - StoreCharInput(Attribute, V->params.createAttribute.name, V->params.createAttribute.nameLength, MDB_ODBC_NAME_SIZE); - - switch (Type) { - case MDB_ATTR_SYN_BOOL: - case MDB_ATTR_SYN_DIST_NAME: - case MDB_ATTR_SYN_BINARY: - case MDB_ATTR_SYN_STRING: { - V->params.createAttribute.type = Type; - break; - } - - default: { - /* Unknown Type */ - V->params.createAttribute.type = 0; - break; - } - } - - V->params.createAttribute.single = Single ? 1 : 0; - V->params.createAttribute.public = Public ? 1 : 0; - - /* Ok, we're ready */ - rc = ExecuteStatement(V->stmts.createAttribute); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } - } - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); -} - -static __inline BOOL -MDBodbcAddAttributeByID(const unsigned char *Attribute, unsigned long class, MDBValueStruct *V) -{ - SQLINTEGER rc; - BOOL requireBindings; - SQLHSTMT stmt = SQL_NULL_HSTMT; - unsigned long subclass; - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - /* Get all subclasses and call add attribute on them as well (recursively) */ - PrepareStatement(stmt, SQL_GET_SUBCLASSES, requireBindings, V); - if (requireBindings) { - BindLongInput(stmt, 1, &class); - BindLongResult(stmt, 1, &subclass); - } - - if (stmt == SQL_NULL_HSTMT) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - rc = ExecuteStatement(stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - rc = SQLFetch(stmt); - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbcAddAttributeByID(Attribute, subclass, V); - - rc = SQLFetch(stmt); - } - - if (rc != SQL_NO_DATA) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - ReleaseStatement(V, stmt); - - PrepareStatement(V->stmts.createOptional, SQL_CREATE_OPTIONAL, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createOptional, 1, &V->params.createOptional.class); - BindCharInput(V->stmts.createOptional, 2, V->params.createOptional.name, &V->params.createOptional.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.createOptional == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.createOptional.class = class; - StoreCharInput(Attribute, V->params.createOptional.name, V->params.createOptional.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createOptional); - return(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO); -} - -BOOL -MDBodbcAddAttribute(const unsigned char *Attribute, const unsigned char *Class, MDBValueStruct *V) -{ - SQLINTEGER rc; - BOOL requireBindings; - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - PrepareStatement(V->stmts.getClassByName, SQL_GET_CLASS_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getClassByName, 1, V->params.getClassByName.name, &V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getClassByName, 1, &V->params.getClassByName.class); - } - - if (V->stmts.getClassByName == SQL_NULL_HSTMT) { - return(FALSE); - } - - StoreCharInput(Class, V->params.getClassByName.name, V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.getClassByName); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getClassByName); - SQLCloseCursor(V->stmts.getClassByName); - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(MDBodbcAddAttributeByID(Attribute, V->params.getClassByName.class, V)); - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } -} - -BOOL -MDBodbcUndefineAttribute(const unsigned char *Attribute, MDBValueStruct *V) -{ - SQLINTEGER attribute; - SQLINTEGER rc; - BOOL requireBindings; - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - if (!Attribute || !V) { - return(FALSE); - } - - /* Get the attribute ID */ - BindLongResult(V->stmts.verifyPassword, 1, &V->params.verifyPassword.object); - PrepareStatement(V->stmts.getAttrByName, SQL_GET_ATTRIBUTE_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getAttrByName, 1, - V->params.getAttrByName.attribute, &V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getAttrByName, 1, &V->params.getAttrByName.id); - } - - if (V->stmts.getAttrByName == SQL_NULL_HSTMT) { - return(FALSE); - } - - StoreCharInput(Attribute, V->params.getAttrByName.attribute, V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.getAttrByName); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getAttrByName); - SQLCloseCursor(V->stmts.getAttrByName); - attribute = V->params.getAttrByName.id; - } - - /* Remove all references to the attribute */ - PrepareStatement(V->stmts.deleteAttrFromMandatory, SQL_MANDATORY_DELETE_ATTR, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteAttrFromMandatory, 1, &V->params.deleteAttrFromMandatory.attribute); - } - - if (V->stmts.deleteAttrFromMandatory == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.deleteAttrFromMandatory.attribute = attribute; - - rc = ExecuteStatement(V->stmts.deleteAttrFromMandatory); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - - PrepareStatement(V->stmts.deleteAttrFromOptional, SQL_OPTIONAL_DELETE_ATTR, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteAttrFromOptional, 1, &V->params.deleteAttrFromOptional.attribute); - } - - if (V->stmts.deleteAttrFromOptional == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.deleteAttrFromOptional.attribute = attribute; - - rc = ExecuteStatement(V->stmts.deleteAttrFromOptional); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - - PrepareStatement(V->stmts.deleteAttrFromNaming, SQL_NAMING_DELETE_ATTR, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteAttrFromNaming, 1, &V->params.deleteAttrFromNaming.attribute); - } - - if (V->stmts.deleteAttrFromNaming == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.deleteAttrFromNaming.attribute = attribute; - - rc = ExecuteStatement(V->stmts.deleteAttrFromNaming); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - PrepareStatement(V->stmts.deleteAttrFromValues, SQL_VALUES_DELETE_ATTR, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteAttrFromValues, 1, &V->params.deleteAttrFromValues.attribute); - } - - if (V->stmts.deleteAttrFromValues == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.deleteAttrFromValues.attribute = attribute; - - rc = ExecuteStatement(V->stmts.deleteAttrFromValues); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - - /* Actually remove the attribute */ - PrepareStatement(V->stmts.deleteAttr, SQL_DELETE_ATTRIBUTE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteAttr, 1, &V->params.deleteAttr.attribute); - } - - if (V->stmts.deleteAttr == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.deleteAttr.attribute = attribute; - - rc = ExecuteStatement(V->stmts.deleteAttr); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); -} - -/* This driver does not supprt/use the ASN1, or naming fields of a class */ -BOOL -MDBodbcDefineClass(const unsigned char *Class, const unsigned char *ASN1, BOOL Container, MDBValueStruct *Superclass, MDBValueStruct *Containment, MDBValueStruct *Naming, MDBValueStruct *Mandatory, MDBValueStruct *Optional, MDBValueStruct *V) -{ - unsigned long class; - unsigned long i; - BOOL result = TRUE; - SQLINTEGER rc; - BOOL requireBindings; - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - /* Add the class */ - PrepareStatement(V->stmts.createClass, SQL_CREATE_CLASS, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.createClass, 1, V->params.createClass.name, &V->params.createClass.nameLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.createClass, 2, &V->params.createClass.container); - } - - if (V->stmts.createClass == SQL_NULL_HSTMT) { - return(FALSE); - } - - StoreCharInput(Class, V->params.createClass.name, V->params.createClass.nameLength, MDB_ODBC_NAME_SIZE); - V->params.createClass.container = Container ? 1 : 0; - - rc = ExecuteStatement(V->stmts.createClass); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - /* The class is already there */ - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(TRUE); - } - - /* Get the ID of the newly created class */ - PrepareStatement(V->stmts.getClassByName, SQL_GET_CLASS_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getClassByName, 1, V->params.getClassByName.name, &V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getClassByName, 1, &V->params.getClassByName.class); - } - - if (V->stmts.getClassByName == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - StoreCharInput(Class, V->params.getClassByName.name, V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.getClassByName); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getClassByName); - SQLCloseCursor(V->stmts.getClassByName); - - class = V->params.getClassByName.class; - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - /* Assign the Containment */ - PrepareStatement(V->stmts.createContainment, SQL_CREATE_CONTAINMENT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createContainment, 1, &V->params.createContainment.class); - BindCharInput(V->stmts.createContainment, 2, V->params.createContainment.name, &V->params.createContainment.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.createContainment == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result && Containment) { - V->params.createContainment.class = class; - - for (i = 0; i < Containment->Used; i++) { - StoreCharInput(Containment->Value[i], V->params.createContainment.name, V->params.createContainment.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createContainment); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - PrepareStatement(V->stmts.createMandatory, SQL_CREATE_MANDATORY, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createMandatory, 1, &V->params.createMandatory.class); - BindCharInput(V->stmts.createMandatory, 2, V->params.createMandatory.name, &V->params.createMandatory.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (result && Mandatory) { - V->params.createMandatory.class = class; - - for (i = 0; i < Mandatory->Used; i++) { - BOOL create = TRUE; - - /* Naming attributes are always provided by the object name, so there is no need to add them to the mandatory list. */ - if (Naming) { - unsigned long n; - - for (n = 0; n < Naming->Used; n++) { - if (XplStrCaseCmp(Naming->Value[n], Mandatory->Value[i]) == 0) { - create = FALSE; - break; - } - } - } - - if (create) { - StoreCharInput(Mandatory->Value[i], V->params.createMandatory.name, V->params.createMandatory.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createMandatory); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - } - - - /* Assign the Optional Attributes */ - PrepareStatement(V->stmts.createOptional, SQL_CREATE_OPTIONAL, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createOptional, 1, &V->params.createOptional.class); - BindCharInput(V->stmts.createOptional, 2, V->params.createOptional.name, &V->params.createOptional.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.createOptional == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result) { - V->params.createOptional.class = class; - - if (Optional) { - for (i = 0; i < Optional->Used; i++) { - StoreCharInput(Optional->Value[i], V->params.createOptional.name, V->params.createOptional.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createOptional); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - /* We add mandatory attributes as optional as well, so that we only have to check one list in MDBWrite */ - if (Mandatory) { - for (i = 0; i < Mandatory->Used; i++) { - StoreCharInput(Mandatory->Value[i], V->params.createOptional.name, V->params.createOptional.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createOptional); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - } - - /* Assign the Naming Attributes */ - PrepareStatement(V->stmts.createNaming, SQL_CREATE_NAMING, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createNaming, 1, &V->params.createNaming.class); - BindCharInput(V->stmts.createNaming, 2, V->params.createNaming.name, &V->params.createNaming.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.createNaming == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result && Naming) { - V->params.createNaming.class = class; - - for (i = 0; i < Naming->Used; i++) { - StoreCharInput(Naming->Value[i], V->params.createNaming.name, V->params.createNaming.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createNaming); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - /* - Assign the super classes - - This must be done before we do the copying, but we have to be sure to not copy the superclasses - until last, to prevent getting duplicate values. - */ - PrepareStatement(V->stmts.createSuperClass, SQL_CREATE_SUPERCLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.createSuperClass, 1, &V->params.createSuperClass.class); - BindCharInput(V->stmts.createSuperClass, 2, V->params.createSuperClass.name, &V->params.createSuperClass.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.createSuperClass == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result && Superclass) { - V->params.createSuperClass.class = class; - - for (i = 0; i < Superclass->Used; i++) { - StoreCharInput(Superclass->Value[i], V->params.createSuperClass.name, V->params.createSuperClass.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.createSuperClass); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - /* - Now that we have assigned all the values we need, we need to copy all the same things - from the superclasses. - */ - if (!Containment || Containment->Used == 0) { - /* Containment is only inherited if it is not specified for a class */ - - PrepareStatement(V->stmts.copyContainment, SQL_COPY_CONTAINMENT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.copyContainment, 1, &V->params.copyContainment.class); - } - - if (V->stmts.copyContainment == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result) { - V->params.copyContainment.class = class; - - rc = ExecuteStatement(V->stmts.copyContainment); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - PrepareStatement(V->stmts.copyOptional, SQL_COPY_OPTIONAL, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.copyOptional, 1, &V->params.copyOptional.class); - } - - if (V->stmts.copyOptional == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result) { - V->params.copyOptional.class = class; - - rc = ExecuteStatement(V->stmts.copyOptional); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - - PrepareStatement(V->stmts.copyMandatory, SQL_COPY_MANDATORY, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.copyMandatory, 1, &V->params.copyMandatory.class); - } - - if (V->stmts.copyMandatory == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result) { - V->params.copyMandatory.class = class; - - rc = ExecuteStatement(V->stmts.copyMandatory); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - - PrepareStatement(V->stmts.copyNaming, SQL_COPY_NAMING, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.copyNaming, 1, &V->params.copyNaming.class); - } - - if (V->stmts.copyNaming == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result) { - V->params.copyNaming.class = class; - - rc = ExecuteStatement(V->stmts.copyNaming); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - - /* - Copy the superclasses from the superclasses. This has to be done after the copying - because each class has the info from its superclass already, so if we do this before - we'll get duplicate values. - - This has to be done though so that if an attribute is added to the superclass of a - superclass at a later point that it can be added to this class as well. - */ - PrepareStatement(V->stmts.copySuperClass, SQL_COPY_SUPERCLASSES, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.copySuperClass, 1, &V->params.copySuperClass.class); - BindCharInput(V->stmts.copySuperClass, 2, - V->params.copySuperClass.name, &V->params.copySuperClass.nameLength, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.copySuperClass == SQL_NULL_HSTMT) { - result = FALSE; - } - - if (result && Superclass) { - V->params.copySuperClass.class = class; - - for (i = 0; i < Superclass->Used; i++) { - StoreCharInput(Superclass->Value[i], V->params.copySuperClass.name, V->params.copySuperClass.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.copySuperClass); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - result = FALSE; - } - } - } - - /* Done */ - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, result ? SQL_COMMIT : SQL_ROLLBACK); - return(result); -} - -BOOL -MDBodbcUndefineClass(const unsigned char *Class, MDBValueStruct *V) -{ - SQLINTEGER rc; - BOOL requireBindings; - SQLINTEGER root; - BOOL allowed; - - if (!MDBodbcGetObjectID("\\", &root, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - if (!Class || !V) { - return(FALSE); - } - - /* Get the class ID */ - PrepareStatement(V->stmts.getClassByName, SQL_GET_CLASS_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getClassByName, 1, - V->params.getClassByName.name, &V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getClassByName, 1, &V->params.getClassByName.class); - } - - if (V->stmts.getClassByName == SQL_NULL_HSTMT) { - return(FALSE); - } - - StoreCharInput(Class, V->params.getClassByName.name, V->params.getClassByName.nameLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.getClassByName); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getClassByName); - SQLCloseCursor(V->stmts.getClassByName); - - if (MDBodbcUndefineClassByID(V->params.getClassByName.class, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); -} - -static __inline BOOL -MDBodbcUndefineClassByID(unsigned long class, MDBValueStruct *V) -{ - SQLINTEGER rc; - BOOL requireBindings; - SQLHSTMT stmt = SQL_NULL_HSTMT; - unsigned long subclass; - unsigned long object; - - /* Get all subclasses and call undefine class on them (recursive) */ - PrepareStatement(stmt, SQL_GET_SUBCLASSES, requireBindings, V); - if (requireBindings) { - BindLongInput(stmt, 1, &class); - BindLongResult(stmt, 1, &subclass); - } - - if (stmt == SQL_NULL_HSTMT) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - rc = ExecuteStatement(stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - rc = SQLFetch(stmt); - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbcUndefineClassByID(subclass, V); - - rc = SQLFetch(stmt); - } - - if (rc != SQL_NO_DATA) { - ReleaseStatement(V, stmt); - return(FALSE); - } - - ReleaseStatement(V, stmt); - - /* Get all objects of that type and delete recursively */ - stmt = SQL_NULL_HSTMT; - PrepareStatement(stmt, SQL_GET_OBJECTS_BY_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(stmt, 1, &class); - BindLongResult(stmt, 1, &object); - } - - if (stmt == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - return(FALSE); - } - - rc = SQLFetch(stmt); - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbcDeleteObjectByID(object, TRUE, V); - - rc = SQLFetch(stmt); - } - - if (rc != SQL_NO_DATA) { - return(FALSE); - } - - ReleaseStatement(V, stmt); - - - /* Remove from containment, mandatory, optional, and naming */ - PrepareStatement(V->stmts.deleteClassFromContainment, SQL_CONTAINMENT_DEL_CLASS, requireBindings, V); - if (requireBindings) { - /* Yes these are supposed to be the same */ - BindLongInput(V->stmts.deleteClassFromContainment, 1, &V->params.deleteClassFromContainment.class); - BindLongInput(V->stmts.deleteClassFromContainment, 2, &V->params.deleteClassFromContainment.class); - } - - if (V->stmts.deleteClassFromContainment == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteClassFromContainment.class = class; - - rc = ExecuteStatement(V->stmts.deleteClassFromContainment); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - - PrepareStatement(V->stmts.deleteClassFromMandatory, SQL_MANDATORY_DEL_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteClassFromMandatory, 1, &V->params.deleteClassFromMandatory.class); - } - - if (V->stmts.deleteClassFromMandatory == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteClassFromMandatory.class = class; - - rc = ExecuteStatement(V->stmts.deleteClassFromMandatory); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - PrepareStatement(V->stmts.deleteClassFromOptional, SQL_OPTIONAL_DEL_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteClassFromOptional, 1, &V->params.deleteClassFromOptional.class); - } - - if (V->stmts.deleteClassFromOptional == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteClassFromOptional.class = class; - - rc = ExecuteStatement(V->stmts.deleteClassFromOptional); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - PrepareStatement(V->stmts.deleteClassFromNaming, SQL_NAMING_DEL_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteClassFromNaming, 1, &V->params.deleteClassFromNaming.class); - } - - if (V->stmts.deleteClassFromNaming == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteClassFromNaming.class = class; - - rc = ExecuteStatement(V->stmts.deleteClassFromNaming); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - /* Ok delete the actual class now */ - PrepareStatement(V->stmts.deleteClass, SQL_DELETE_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteClass, 1, &V->params.deleteClass.class); - } - - if (V->stmts.deleteClass== SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteClass.class = class; - - rc = ExecuteStatement(V->stmts.deleteClass); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - return(TRUE); -} - -BOOL -MDBodbcListContainableClasses(const unsigned char *Object, MDBValueStruct *V) -{ - signed long id; - SQLINTEGER rc; - BOOL requireBindings; - BOOL allowed; - - if (!V || !Object || !MDBodbcGetObjectID(Object, &id, NULL, &allowed, NULL, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - PrepareStatement(V->stmts.listContainment, SQL_LIST_CONTAINMENT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.listContainment, 1, &V->params.listContainment.object); - BindCharResult(V->stmts.listContainment, 1, V->params.listContainment.name, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.listContainment == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.listContainment.object = id; - rc = ExecuteStatement(V->stmts.listContainment); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.listContainment); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbcAddValue(V->params.listContainment.name, V); - - rc = SQLFetch(V->stmts.listContainment); - } - - SQLCloseCursor(V->stmts.listContainment); - - return(V->Used); -} - -const unsigned char * -MDBodbcListContainableClassesEx(const unsigned char *Object, MDBEnumStruct *E, MDBValueStruct *V) -{ - SQLINTEGER rc; - - if (!E || !V) { - return(NULL); - } - - if (E->stmt == SQL_NULL_HSTMT) { - BOOL requireBindings; - BOOL allowed; - - if (!Object || !MDBodbcGetObjectID(Object, &E->object, NULL, &allowed, NULL, NULL, NULL, V) || !allowed) { - return(NULL); - } - - /* We are not in a statement, so prepare one */ - E->sql = SQL_LIST_CONTAINMENT; - PrepareStatement(E->stmt, SQL_LIST_CONTAINMENT, requireBindings, V); - if (requireBindings) { - BindLongInput(E->stmt, 1, &E->object); - BindCharResult(E->stmt, 1, E->result, MDB_ODBC_NAME_SIZE); - } - - rc = ExecuteStatement(E->stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - if (E->stmt != SQL_NULL_HSTMT && E->sql == SQL_LIST_CONTAINMENT) { - rc = SQLFetch(E->stmt); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - return(E->result); - } else if (rc == SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - return(NULL); -} - -long -MDBodbcRead(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V) -{ - signed long id; - SQLINTEGER rc; - BOOL requireBindings; - unsigned char *value = NULL; - unsigned long used = 0; - unsigned long before; - BOOL allowed; - - if (!Object || !Attribute || !V || !MDBodbcGetObjectID(Object, &id, NULL, &allowed, NULL, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - before = V->Used; - - PrepareStatement(V->stmts.readValue, SQL_READ_VALUE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.readValue, 1, &V->params.readValue.object); - BindCharInput(V->stmts.readValue, 2, - &V->params.readValue.attribute, &V->params.readValue.attributeLength, MDB_ODBC_NAME_SIZE); - - BindCharResult(V->stmts.readValue, 1, V->params.readValue.value, MDB_ODBC_PART_SIZE + 1); - BindLongResult(V->stmts.readValue, 2, &V->params.readValue.dn); - BindLongResult(V->stmts.readValue, 3, &V->params.readValue.bool); - BindLongResult(V->stmts.readValue, 4, &V->params.readValue.complete); - BindLongResult(V->stmts.readValue, 5, &V->params.readValue.type); - } - - if (V->stmts.readValue == SQL_NULL_HSTMT) { - return(0); - } - - V->params.readValue.object = id; - StoreCharInput(Attribute, V->params.readValue.attribute, V->params.readValue.attributeLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.readValue); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.readValue); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - switch (V->params.readValue.type) { - case MDB_ATTR_SYN_STRING: { - if (value || V->params.readValue.complete != 1) { - value = realloc(value, used + MDB_ODBC_PART_SIZE + 1); - - strncpy(value + used, V->params.readValue.value, MDB_ODBC_PART_SIZE + 1); - used += strlen(V->params.readValue.value); - value[used] = '\0'; - } - - if (V->params.readValue.complete == 1) { - MDBodbcAddValue(value ? value : V->params.readValue.value, V); - if (value) { - free(value); - value = NULL; - used = 0; - } - } - - break; - } - - case MDB_ATTR_SYN_DIST_NAME: { - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - - /* We have a DN value */ - if (MDBodbcGetObjectDN(dn, MDB_MAX_OBJECT_CHARS, V->params.readValue.dn, FALSE, V)) { - MDBodbcAddValue(dn, V); - } - - break; - } - - case MDB_ATTR_SYN_BOOL: { - if (V->params.readValue.bool == 1) { - MDBodbcAddValue("1", V); - } else { - MDBodbcAddValue("0", V); - } - - break; - } - } - - V->params.readValue.value[0] = '\0'; - rc = SQLFetch(V->stmts.readValue); - } - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - XplConsolePrintf("Error reading value: %lu\n", rc); - PrintSQLErr(V, V->stmts.readValue); - } - - SQLCloseCursor(V->stmts.readValue); - - if (value) { - XplConsolePrintf("%s:%d Failed to read the final part of a value\n", __FILE__, __LINE__); - free(value); - } - - return(V->Used - before); -} - -const unsigned char * -MDBodbcReadEx(const unsigned char *Object, const unsigned char *Attribute, MDBEnumStruct *E, MDBValueStruct *V) -{ - SQLINTEGER rc; - - if (!E || !V) { - return(NULL); - } - - if (E->largeResult) { - free(E->largeResult); - E->largeResult = NULL; - } - - if (E->stmt == SQL_NULL_HSTMT) { - BOOL requireBindings; - BOOL allowed; - - if (!Object || !Attribute || !MDBodbcGetObjectID(Object, &E->object, NULL, &allowed, NULL, NULL, NULL, V) || !allowed) { - return(NULL); - } - - /* We are not in a statement, so prepare one */ - E->sql = SQL_READ_VALUE; - PrepareStatement(E->stmt, SQL_READ_VALUE, requireBindings, V); - if (requireBindings) { - unsigned long attributeLength = strlen(Attribute); - - BindLongInput(E->stmt, 1, &E->object); - BindCharInput(E->stmt, 2, &Attribute, &attributeLength, MDB_ODBC_NAME_SIZE); - - BindCharResult(E->stmt, 1, E->result, MDB_ODBC_PART_SIZE + 1); - BindLongResult(E->stmt, 2, &E->id); - BindLongResult(E->stmt, 3, &E->bool); - BindLongResult(E->stmt, 4, &E->complete); - BindLongResult(E->stmt, 5, &E->type); - } - - rc = ExecuteStatement(E->stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - if (E->stmt != SQL_NULL_HSTMT && E->sql == SQL_READ_VALUE) { - rc = SQLFetch(E->stmt); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - switch (V->params.readValue.type) { - case MDB_ATTR_SYN_STRING: { - unsigned long used = 0; - - do { - if (E->largeResult || E->complete != 1) { - E->largeResult = realloc(E->largeResult, used + MDB_ODBC_PART_SIZE + 1); - - strncpy(E->largeResult + used, E->result, MDB_ODBC_PART_SIZE + 1); - used += strlen(E->result); - E->largeResult[used] = '\0'; - } - } while (E->complete != 1 && (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)); - - if (E->complete == 1) { - if (E->largeResult) { - return(E->largeResult); - } else { - return(E->result); - } - } - - break; - } - - case MDB_ATTR_SYN_DIST_NAME: { - /* We have a DN value */ - if (MDBodbcGetObjectDN(E->result, MDB_MAX_OBJECT_CHARS, E->id, FALSE, V)) { - return(E->result); - } - - break; - } - - case MDB_ATTR_SYN_BOOL: { - if (E->bool == 1) { - E->result[0] = '1'; - } else { - E->result[0] = '0'; - } - E->result[1] = '\0'; - - return(E->result); - } - } - } else if (rc == SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - return(NULL); -} - -BOOL -MDBodbcWriteTyped(const unsigned char *Object, const unsigned char *Attribute, const int AttrType, MDBValueStruct *V) -{ - return(MDBodbcWriteAny(Object, Attribute, AttrType, TRUE, NULL, V)); -} - -BOOL -MDBodbcWrite(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V) -{ - return(MDBodbcWriteAny(Object, Attribute, MDB_ATTR_SYN_STRING, TRUE, NULL, V)); -} - -BOOL -MDBodbcWriteDN(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V) -{ - return(MDBodbcWriteAny(Object, Attribute, MDB_ATTR_SYN_DIST_NAME, TRUE, NULL, V)); -} - -BOOL -MDBodbcAdd(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V) -{ - if (Value) { - return(MDBodbcWriteAny(Object, Attribute, MDB_ATTR_SYN_STRING, FALSE, Value, V)); - } else { - /* WriteAny will attempt to write the values in V if Value is NULL */ - return(FALSE); - } -} - -BOOL -MDBodbcAddDN(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V) -{ - if (Value) { - return(MDBodbcWriteAny(Object, Attribute, MDB_ATTR_SYN_DIST_NAME, FALSE, Value, V)); - } else { - /* WriteAny will attempt to write the values in V if Value is NULL */ - return(FALSE); - } -} - -static __inline BOOL -MDBodbcWriteAny(const unsigned char *Object, const unsigned char *Attribute, const unsigned char Type, const BOOL clear, const unsigned char *Value, MDBValueStruct *V) -{ - SQLINTEGER object; - SQLINTEGER attribute; - BOOL single; - unsigned char type; - unsigned char **v = (Value) ? (unsigned char **)&(Value) : V->Value; - unsigned long u = (Value) ? 1 : V->Used; - SQLINTEGER rc; - BOOL requireBindings; - BOOL allowed; - - if (!Object || !Attribute || !V || !MDBodbcGetObjectID(Object, &object, NULL, NULL, &allowed, NULL, NULL, V) || !allowed) { - return(FALSE); - } - - PrepareStatement(V->stmts.getObjectAttrInfo, SQL_GET_OBJECT_ATTR_INFO, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getObjectAttrInfo, 1, &V->params.getObjectAttrInfo.object); - BindCharInput(V->stmts.getObjectAttrInfo, 2, - V->params.getObjectAttrInfo.attribute, &V->params.getObjectAttrInfo.attributeLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getObjectAttrInfo, 1, &V->params.getObjectAttrInfo.id); - BindLongResult(V->stmts.getObjectAttrInfo, 2, &V->params.getObjectAttrInfo.single); - BindLongResult(V->stmts.getObjectAttrInfo, 3, &V->params.getObjectAttrInfo.type); - } - - if (V->stmts.getObjectAttrInfo == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.getObjectAttrInfo.object = object; - StoreCharInput(Attribute, V->params.getObjectAttrInfo.attribute, V->params.getObjectAttrInfo.attributeLength, MDB_ODBC_NAME_SIZE); - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.getObjectAttrInfo); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - SQLINTEGER count = 0; - - rc = SQLRowCount(V->stmts.getObjectAttrInfo, &count); - if (count < 1) { - /* No rows will be returned if we are not allowed to write this attribute to this object */ - return(FALSE); - } - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getObjectAttrInfo); - SQLCloseCursor(V->stmts.getObjectAttrInfo); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - attribute = V->params.getObjectAttrInfo.id; - single = (V->params.getObjectAttrInfo.single == 1); - type = (unsigned char) V->params.getObjectAttrInfo.type; - } else { - return(FALSE); - } - - /* - We now have the object ID, attribute ID, and the value for single and type. We can now begin. - */ - - /* If they are trying to write multiple values to a single, then bail */ - if (single && u > 1) { - return(FALSE); - } - - /* If it is a single value attribute make sure there are no other values stored already */ - if ((clear || single) && !MDBodbcClear(Object, Attribute, V)) { - return(FALSE); - } - - /* - We can finally add the value. Write it as the type the attribute should hold, even if it does not - match the type that the calling program is trying to write. If they don't match the calling program - is wrong. - */ - switch (type) { - case MDB_ATTR_SYN_DIST_NAME: { - unsigned long i; - - PrepareStatement(V->stmts.addDNValue, SQL_ADD_DN_VALUE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.addDNValue, 1, &V->params.addDNValue.owner); - BindLongInput(V->stmts.addDNValue, 2, &V->params.addDNValue.attribute); - BindLongInput(V->stmts.addDNValue, 3, &V->params.addDNValue.value); - } - - if (V->stmts.addDNValue == SQL_NULL_HSTMT) { - return(FALSE); - } - - for (i = 0; i < u; i++) { - SQLINTEGER referencee; - - if (MDBodbcGetObjectID(v[i], &referencee, NULL, NULL, NULL, NULL, NULL, V)) { - /* We have to reset these, because GetObjectID will have overwritten then */ - V->params.addDNValue.owner = object; - V->params.addDNValue.attribute = attribute; - V->params.addDNValue.value = referencee; - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.addDNValue); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - if (attribute == MDBodbc.config.special.member) { - /* This is changing group membership, which means we need to copy rights to the members */ - - if (!MDBodbcCopyObjectRights(referencee, object, FALSE, V)) { - return(FALSE); - } - } - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - break; - } - - case MDB_ATTR_SYN_BOOL: { - unsigned long i; - - PrepareStatement(V->stmts.addBoolValue, SQL_ADD_BOOL_VALUE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.addBoolValue, 1, &V->params.addBoolValue.owner); - BindLongInput(V->stmts.addBoolValue, 2, &V->params.addBoolValue.attribute); - BindLongInput(V->stmts.addBoolValue, 3, &V->params.addBoolValue.value); - } - - if (V->stmts.addBoolValue == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.addBoolValue.owner = object; - V->params.addBoolValue.attribute = attribute; - - for (i = 0; i < u; i++) { - BOOL value; - - switch (v[i][0]) { - case '1': - case 'Y': - case 'y': - case 'T': - case 't': { - value = TRUE; - } - - case '0': - case 'N': - case 'n': - case 'F': - case 'f': - default: { - value = FALSE; - } - } - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.addBoolValue); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - break; - } - - case MDB_ATTR_SYN_BINARY: { - /* - FIXME - This should be implemented by Base 64ing the data, and storing it as if - it where a string. It would be best if it can be base 64'ed into the param that - is already bound so that we don't have to worry about memory. - */ - break; - } - - case MDB_ATTR_SYN_STRING: { - unsigned long i; - - PrepareStatement(V->stmts.addStringValue, SQL_ADD_STRING_VALUE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.addStringValue, 1, &V->params.addStringValue.owner); - BindLongInput(V->stmts.addStringValue, 2, &V->params.addStringValue.attribute); - BindCharInput(V->stmts.addStringValue, 3, - V->params.addStringValue.value, &V->params.addStringValue.valueLength, MDB_ODBC_PART_SIZE);; - BindLongInput(V->stmts.addStringValue, 4, &V->params.addStringValue.complete); - } - - if (V->stmts.addStringValue == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.addStringValue.owner = object; - V->params.addStringValue.attribute = attribute; - - for (i = 0; i < u; i++) { - unsigned char *value = v[i]; - - /* - It is important to be able to store strings of any length as a value, but it is much easier to deal with - the database if we have fixed sized records. Also some ODBC drivers may not like variable sized records. - - To handle this any string value larger than MDBC_ODBC_PART_SIZE (255) will be split into multiple records - which will be stored in order. The complete row will be set to true on the final record, to allow for easy - reading. Simply read them order by id until complete is true. - - That means they have to be split here though. This should rarely actually happen, because most values will - be much smaller than 255. - */ - - do { - StoreCharInput(value, V->params.addStringValue.value, V->params.addStringValue.valueLength, MDB_ODBC_PART_SIZE); - V->params.addStringValue.complete = (V->params.addStringValue.valueLength != MDB_ODBC_PART_SIZE); - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.addStringValue); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - value += MDB_ODBC_PART_SIZE; - } while (V->params.addStringValue.valueLength == MDB_ODBC_PART_SIZE); - } - - break; - } - - default: { - return(FALSE); - } - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); -} - -BOOL -MDBodbcRemove(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V) -{ - MDBValueStruct *v; - unsigned long i; - - if (!Object || !Attribute || !Value || !V) { - return(FALSE); - } - - v = MDBodbcShareContext(V); - - MDBodbcRead(Object, Attribute, v); - for (i = 0; i < v->Used; i++) { - if (XplStrCaseCmp(v->Value[i], Value)) { - MDBodbcFreeValue(i, v); - MDBodbcWrite(Object, Attribute, v); - MDBodbcDestroyValueStruct(v); - - return(TRUE); - } - } - - V->ErrNo = ERR_NO_SUCH_VALUE; - - MDBodbcDestroyValueStruct(v); - return(FALSE); -} - -BOOL -MDBodbcRemoveDN(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *Value, MDBValueStruct *V) -{ - MDBValueStruct *v; - unsigned long i; - SQLINTEGER value; - - if (!Object || !Attribute || !Value || !V || !MDBodbcGetObjectID(Value, &value, NULL, NULL, NULL, NULL, NULL, V)) { - return(FALSE); - } - - v = MDBodbcShareContext(V); - - MDBodbcRead(Object, Attribute, v); - for (i = 0; i < v->Used; i++) { - SQLINTEGER c; - - if (MDBodbcGetObjectID(v->Value[i], &c, NULL, NULL, NULL, NULL, NULL, V) && c == value) { - MDBodbcFreeValue(i, v); - MDBodbcWriteDN(Object, Attribute, v); - MDBodbcDestroyValueStruct(v); - return(TRUE); - } - } - - V->ErrNo = ERR_NO_SUCH_VALUE; - - MDBodbcDestroyValueStruct(v); - return(FALSE); -} - -BOOL -MDBodbcClear(const unsigned char *Object, const unsigned char *Attribute, MDBValueStruct *V) -{ - SQLINTEGER id; - BOOL allow; - - if (Object && Attribute && V && MDBodbcGetObjectID(Object, &id, NULL, NULL, &allow, NULL, NULL, V) && allow) { - SQLINTEGER attribute = 0; - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.getAttrByName, SQL_GET_ATTRIBUTE_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getAttrByName, 1, - V->params.getAttrByName.attribute, &V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getAttrByName, 1, &V->params.getAttrByName.id); - } - - if (V->stmts.getAttrByName == SQL_NULL_HSTMT) { - return(FALSE); - } - - StoreCharInput(Attribute, V->params.getAttrByName.attribute, V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.getAttrByName); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getAttrByName); - SQLCloseCursor(V->stmts.getAttrByName); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - attribute = V->params.getAttrByName.id; - } else { - return(FALSE); - } - - if (attribute == MDBodbc.config.special.member) { - /* The attribute is 'Member' so we need to remove the rights that where granted by this group to its members. */ - PrepareStatement(V->stmts.delRightsByProvider, SQL_DEL_RIGHTS_BY_PROVIDER, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.delRightsByProvider, 1, &V->params.delRightsByProvider.provider); - } - - if (V->stmts.delRightsByProvider == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.delRightsByProvider.provider = id; - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.delRightsByProvider); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - } - - /* Ok try to delete the values now */ - PrepareStatement(V->stmts.clearAttribute, SQL_CLEAR_ATTRIBUTE, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.clearAttribute, 1, &V->params.clearAttribute.object); - BindLongInput(V->stmts.clearAttribute, 2, &V->params.clearAttribute.attribute); - } - - if (V->stmts.clearAttribute == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.clearAttribute.object = id; - V->params.clearAttribute.attribute = attribute; - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.clearAttribute); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - return(FALSE); -} - -BOOL -MDBodbcIsObject(const unsigned char *Object, MDBValueStruct *V) -{ - signed long id; - BOOL allow; - - return(Object && V && MDBodbcGetObjectID(Object, &id, NULL, &allow, NULL, NULL, NULL, V) && allow); -} - -BOOL -MDBodbcGetObjectDetails(const unsigned char *Object, unsigned char *Type, unsigned char *RDN, unsigned char *DN, MDBValueStruct *V) -{ - signed long id; - BOOL allow; - - if (!Object || !V || !MDBodbcGetObjectID(Object, &id, NULL, &allow, NULL, NULL, NULL, V) || !allow) { - return(FALSE); - } - - if (RDN && !MDBodbcGetObjectDN(RDN, MDB_MAX_OBJECT_CHARS, id, TRUE, V)) { - return(FALSE); - } - - if (DN) { - unsigned long base = *(V->base.id); - - *(V->base.id) = -1; - if (!MDBodbcGetObjectDN(DN, MDB_MAX_OBJECT_CHARS, id, FALSE, V)) { - *(V->base.id) = base; - return(FALSE); - } - - *(V->base.id) = base; - } - - if (Type) { - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.getObjectClassName, SQL_GET_OBJECT_CLASSNAME, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getObjectClassName, 1, &V->params.getObjectClassName.object); - BindCharResult(V->stmts.getObjectClassName, 1, V->params.getObjectClassName.class, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.getObjectClassName == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.getObjectClassName.object = id; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.getObjectClassName); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getObjectClassName); - SQLCloseCursor(V->stmts.getObjectClassName); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - strcpy(Type, V->params.getObjectClassName.class); - } else { - return(FALSE); - } - } - - return(TRUE); -} - -BOOL -MDBodbcGetObjectDetailsEx(const unsigned char *Object, MDBValueStruct *Types, unsigned char *RDN, unsigned char *DN, MDBValueStruct *V) -{ - /* FIXME: Implement this function */ - XplConsolePrintf("MDBodbcGetObjectDetailsEx() not implemented!\n"); - return FALSE; -} - -BOOL -MDBodbcVerifyPassword(const unsigned char *Object, const unsigned char *Password, MDBValueStruct *V) -{ - signed long id; - MD5_CTX md5; - unsigned char hash[32 + 1]; - unsigned char digest[16]; - unsigned long i; - SQLINTEGER rc; - BOOL requireBindings; - - if (!Object || !Password || !V || !MDBodbcGetObjectID(Object, &id, NULL, NULL, NULL, NULL, NULL, V)) { - return(FALSE); - } - - MD5_Init(&md5); - MD5_Update(&md5, Password, strlen(Password)); - MD5_Final(digest, &md5); - - for (i = 0; i < 16; i++) { - sprintf(hash + (i * 2), "%02x", digest[i]); - } - - PrepareStatement(V->stmts.verifyPassword, SQL_VERIFY_PASSWORD, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.verifyPassword, 1, &V->params.verifyPassword.object); - BindCharInput(V->stmts.verifyPassword, 2, - &V->params.verifyPassword.pass, &V->params.verifyPassword.passLength, 32); - } - - if (V->stmts.verifyPassword != SQL_NULL_HSTMT) { - V->params.verifyPassword.object = id; - StoreCharInput(hash, V->params.verifyPassword.pass, V->params.verifyPassword.passLength, 32); - - /* Ok, we're ready */ - rc = ExecuteStatement(V->stmts.verifyPassword); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.verifyPassword); - SQLCloseCursor(V->stmts.verifyPassword); - - if (((rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) && - V->params.verifyPassword.object == id) || - (rc == SQL_NO_DATA && Password[0] == '\0')) - { - return(TRUE); - } - } - } - - return(FALSE); -} - -BOOL -MDBodbcChangePassword(const unsigned char *Object, const unsigned char *OldPassword, const unsigned char *NewPassword, MDBValueStruct *V) -{ - if (!OldPassword) { - return(FALSE); - } - - return(MDBodbcChangePasswordEx(Object, OldPassword, NewPassword, V)); -} - -BOOL -MDBodbcChangePasswordEx(const unsigned char *Object, const unsigned char *OldPassword, const unsigned char *NewPassword, MDBValueStruct *V) -{ - signed long id; - MD5_CTX md5; - unsigned char hash[32 + 1]; - unsigned char digest[16]; - unsigned long i; - SQLINTEGER rc; - BOOL requireBindings; - BOOL allow; - - if (!Object || !NewPassword || !V || !MDBodbcGetObjectID(Object, &id, NULL, NULL, &allow, NULL, NULL, V)) { - return(FALSE); - } - - /* - The password can only be changed if the current password is given, or the object logged in has - the right to write to the object. - */ - if ((allow && !OldPassword) || MDBodbcVerifyPassword(Object, OldPassword, V)) { - MD5_Init(&md5); - MD5_Update(&md5, NewPassword, strlen(NewPassword)); - MD5_Final(digest, &md5); - - for (i = 0; i < 16; i++) { - sprintf(hash + (i * 2), "%02x", digest[i]); - } - - /* Ok, set the new password */ - PrepareStatement(V->stmts.setPassword, SQL_SET_PASSWORD, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.setPassword, 1, - &V->params.setPassword.pass, &V->params.setPassword.passLength, 32); - BindLongInput(V->stmts.setPassword, 2, &V->params.setPassword.object); - } - - if (V->stmts.setPassword == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.setPassword.object = id; - StoreCharInput(hash, V->params.setPassword.pass, V->params.setPassword.passLength, 32); - - /* Ok, we're ready */ - rc = ExecuteStatement(V->stmts.setPassword); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - } - } - - return(FALSE); -} - -static __inline BOOL -checkFilter(unsigned char *value, const unsigned char *filter) -{ - if (filter) { - unsigned char *filt = strdup(filter); - unsigned char *f = filt; - - while (f && *f) { - switch (*f) { - case '?': { - /* A question mark matches one character. */ - if (*value == '\0') { - free(filt); - return(FALSE); - } - - value++; - f++; - - break; - } - - case '*': { - unsigned char *ptr; - unsigned char *e; - unsigned char w = '\0'; - - /* An asterisk matches zero or more characters. */ - - do { - f++; - } while (*f == '*'); - - if (*f == '\0') { - /* The asterisk is the last char, so the string matches */ - free(filt); - return(TRUE); - } - - /* Find the next wildcard */ - e = (unsigned char *) f; - while (*e && *e != '*' && *e != '?') { - e++; - } - - w = *e; - *e = '\0'; - - ptr = strstr(value, f); - if (!ptr) { - free(filt); - return(FALSE); - } - - value = ptr + strlen(f); - f = e; - - *e = w; - break; - } - - default: { - /* All other characters match themselves. */ - if (toupper(*f) != toupper(*value)) { - free(filt); - return(FALSE); - } - - f++; - value++; - - break; - } - } - } - - free(filt); - return(*value == '\0'); - } else { - /* If there is no filter, then it is a match */ - return(TRUE); - } -} - -long -MDBodbcEnumerateObjects(const unsigned char *Container, const unsigned char *Type, const unsigned char *Pattern, MDBValueStruct *V) -{ - signed long id; - SQLINTEGER rc; - BOOL requireBindings; - SQLHSTMT getChildren; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - unsigned char *e; - BOOL allow; - - if (!Container || !V || !MDBodbcGetObjectID(Container, &id, NULL, &allow, NULL, NULL, NULL, V) || - !allow || !MDBodbcGetObjectDN(dn, MDB_MAX_OBJECT_CHARS, id, TRUE, V)) - { - return(FALSE); - } - - /* Set the position to write the new object names to */ - e = dn + strlen(dn); - *e = '\\'; - e++; - - /* Prepare both the statement with the class and without, bind to the same params */ - PrepareStatement(V->stmts.getChildren, SQL_GET_CHILDREN, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getChildren, 1, &V->params.getChildren.object); - BindCharResult(V->stmts.getChildren, 1, V->params.getChildren.child, MDB_ODBC_PART_SIZE + 1); - BindLongResult(V->stmts.getChildren, 2, &V->params.getChildren.container); - } - - PrepareStatement(V->stmts.getChildrenByClass, SQL_GET_CHILDREN_BY_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getChildrenByClass, 1, &V->params.getChildren.object); - BindCharInput(V->stmts.getChildrenByClass, 2, - &V->params.getChildren.class, &V->params.getChildren.classLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.getChildrenByClass, 3, &V->params.getChildren.allContainers); - BindCharResult(V->stmts.getChildrenByClass, 1, V->params.getChildren.child, MDB_ODBC_PART_SIZE + 1); - BindLongResult(V->stmts.getChildrenByClass, 2, &V->params.getChildren.container); - } - - if (V->stmts.getChildren == SQL_NULL_HSTMT || V->stmts.getChildrenByClass == SQL_NULL_HSTMT) { - return(0); - } - - /* All Containers should be set to -1 for normal use */ - V->params.getChildren.allContainers = -1; - V->params.getChildren.object = id; - - if (Type && Type[0] != '\0' && !(Type[0] == '*' && Type[1] == '\0')) { - StoreCharInput(Type, V->params.getChildren.class, V->params.getChildren.classLength, MDB_ODBC_NAME_SIZE); - getChildren = V->stmts.getChildrenByClass; - } else { - getChildren = V->stmts.getChildren; - } - - rc = ExecuteStatement(getChildren); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildren); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!Pattern || !(*Pattern) || checkFilter(V->params.getChildren.child, Pattern)) { - strncpy(e, V->params.getChildren.child, MDB_MAX_OBJECT_CHARS - (e - dn)); - MDBodbcAddValue(dn, V); - } - - rc = SQLFetch(getChildren); - } - - SQLCloseCursor(getChildren); - - return(V->Used); -} - -const unsigned char * -MDBodbcEnumerateObjectsEx(const unsigned char *Container, const unsigned char *Type, const unsigned char *Pattern, unsigned long Flags, MDBEnumStruct *E, MDBValueStruct *V) -{ - SQLINTEGER rc; - - if (!E || !V) { - return(NULL); - } - - if (E->stmt == SQL_NULL_HSTMT) { - BOOL requireBindings; - BOOL allow; - - if (!Container || !MDBodbcGetObjectID(Container, &E->object, NULL, &allow, NULL, NULL, NULL, V) || - !allow || !MDBodbcGetObjectDN(E->dn, MDB_MAX_OBJECT_CHARS, E->object, FALSE, V)) - { - return(NULL); - } - - E->name = E->dn + strlen(E->dn); - *(E->name) = '\\'; - (E->name)++; - - /* We are not in a statement, so prepare one */ - if (Type && Type[0] != '\0' && !(Type[0] == '*' && Type[1] == '\0')) { - E->classlen = (Type) ? strlen(Type) : 0; - strcpy(E->class, Type); - - E->sql = SQL_GET_CHILDREN_BY_CLASS; - - if (Flags) { - E->allContainers = 1; - } else { - E->allContainers = -1; - } - } else { - E->sql = SQL_GET_CHILDREN; - } - - PrepareStatement(E->stmt, E->sql, requireBindings, V); - if (requireBindings) { - BindLongInput(E->stmt, 1, &E->object); - - if (E->sql == SQL_GET_CHILDREN_BY_CLASS) { - BindCharInput(E->stmt, 2, &E->class, &E->classlen, MDB_ODBC_NAME_SIZE); - BindLongInput(E->stmt, 3, &E->allContainers); - } - - BindCharResult(E->stmt, 1, E->result, MDB_ODBC_NAME_SIZE); - BindLongResult(E->stmt, 2, &E->container); - } - - rc = ExecuteStatement(E->stmt); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - if (E->stmt != SQL_NULL_HSTMT && (E->sql == SQL_GET_CHILDREN || E->sql == SQL_GET_CHILDREN_BY_CLASS)) { - rc = SQLFetch(E->stmt); - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if ((Flags && E->container) || !Pattern || !(*Pattern) || checkFilter(E->result, Pattern)) { - strncpy(E->name, E->result, MDB_MAX_OBJECT_CHARS - (E->name - E->dn)); - return(E->dn); - } - - rc = SQLFetch(E->stmt); - } - - if (rc == SQL_NO_DATA) { - ReleaseStatement(V, E->stmt); - E->stmt = SQL_NULL_HSTMT; - } - } - - return(NULL); -} - -const unsigned char * -MDBodbcEnumerateAttributesEx(const unsigned char *Object, MDBEnumStruct *E, MDBValueStruct *V) -{ - return(FALSE); -} - -BOOL -MDBodbcCreateAlias(const unsigned char *Alias, const unsigned char *AliasedObjectDn, MDBValueStruct *V) -{ - return(FALSE); -} - -BOOL -MDBodbcCreateObject(const unsigned char *Object, const unsigned char *Class, MDBValueStruct *Attribute, MDBValueStruct *Data, MDBValueStruct *V) -{ - SQLINTEGER parent; - SQLINTEGER parentClass; - SQLINTEGER id; - unsigned char *ptr; - unsigned char buffer[MDB_MAX_OBJECT_CHARS + 1]; - unsigned long i; - SQLINTEGER rc; - BOOL requireBindings; - BOOL allow; - - strncpy(buffer, Object, MDB_MAX_OBJECT_CHARS); - ptr = strrchr(buffer, '\\'); - - if (ptr == buffer) { - if (!MDBodbcGetObjectID("\\", &parent, &parentClass, NULL, &allow, NULL, NULL, V)) { - return(FALSE); - } - - ptr++; - } else if (ptr) { - *ptr = '\0'; - if (!MDBodbcGetObjectID(buffer, &parent, &parentClass, NULL, &allow, NULL, NULL, V)) { - return(FALSE); - } - - ptr++; - } else { - parent = *(V->base.id); - parentClass = *(V->base.class); - ptr = buffer; - - allow = *(V->base.write); - } - - if (!allow) { - return(FALSE); - } - - /* Verify mandatory attributes */ - PrepareStatement(V->stmts.getMandatoryByName, SQL_GET_MANDATORY_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getMandatoryByName, 1, - &V->params.getMandatoryByName.class, &V->params.getMandatoryByName.classLength, MDB_ODBC_NAME_SIZE); - BindCharResult(V->stmts.getMandatoryByName, 1, V->params.getMandatoryByName.class, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.getMandatoryByName != SQL_NULL_HSTMT) { - StoreCharInput(Class, V->params.getMandatoryByName.class, V->params.getMandatoryByName.classLength, MDB_ODBC_NAME_SIZE); - - rc = ExecuteStatement(V->stmts.getMandatoryByName); - if ((rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) && (!Attribute || Attribute->Used == 0)) { - SQLINTEGER count = 0; - - /* We don't have any attributes, so if we have any mandatorys then we fail right now */ - rc = SQLRowCount(V->stmts.getMandatoryByName, &count); - SQLCloseCursor(V->stmts.getMandatoryByName); - - if (count > 0) { - V->ErrNo = ERR_MISSING_MANDATORY; - return(FALSE); - } - } else { - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getMandatoryByName); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - unsigned long i; - BOOL found = FALSE; - - for (i = 0; i < Attribute->Used; i++) { - /* Ignore the first char */ - if (XplStrCaseCmp(Attribute->Value[i] + 1, V->params.getMandatoryByName.class) == 0) { - found = TRUE; - break; - } - } - - if (!found) { - SQLCloseCursor(V->stmts.getMandatoryByName); - V->ErrNo = ERR_MISSING_MANDATORY; - return(FALSE); - } - - rc = SQLFetch(V->stmts.getMandatoryByName); - } - - if (rc != SQL_NO_DATA) { - V->ErrNo = ERR_MISSING_MANDATORY; - return(FALSE); - } else { - SQLCloseCursor(V->stmts.getMandatoryByName); - } - } - } - - PrepareStatement(V->stmts.createObject, SQL_CREATE_OBJECT, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.createObject, 1, - &V->params.createObject.name, &V->params.createObject.nameLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.createObject, 2, &V->params.createObject.parent); - BindCharInput(V->stmts.createObject, 3, - &V->params.createObject.class, &V->params.createObject.classLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.createObject, 4, &V->params.createObject.parentClass); - } - - if (V->stmts.createObject != SQL_NULL_HSTMT) { - V->params.createObject.parent = parent; - V->params.createObject.parentClass = parentClass; - StoreCharInput(ptr, V->params.createObject.name, V->params.createObject.nameLength, MDB_ODBC_NAME_SIZE); - StoreCharInput(Class, V->params.createObject.class, V->params.createObject.classLength, MDB_ODBC_NAME_SIZE); - - /* Ok, we're ready */ - rc = ExecuteStatement(V->stmts.createObject); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - /* - Setup rights - - Get the ID of the newly created object, and then copy the rights of the parent object - to it, with parent set properly. - */ - if (!MDBodbcGetObjectID(Object, &id, NULL, NULL, NULL, NULL, NULL, V)) { - /* - The object doesn't seem to have actually be created. This implies it can not be - contained in this type of container. - */ - V->ErrNo = ERR_ILLEGAL_CONTAINMENT; - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - if (!MDBodbcCopyObjectRights(id, parent, TRUE, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - if (Attribute && Data) { - unsigned long l = Attribute->Used; - - if (l > Data->Used) { - l = Data->Used; - } - - for (i = 0; i < l; i++) { - MDBodbcWriteAny(Object, Attribute->Value[i] + 1, Attribute->Value[i][0], FALSE, Data->Value[i], V); - } - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); -} - -BOOL -MDBodbcDeleteObject(const unsigned char *Object, BOOL Recursive, MDBValueStruct *V) -{ - signed long id; - BOOL allow; - BOOL result; - - if (!Object || !V || !MDBodbcGetObjectID(Object, &id, NULL, NULL, NULL, &allow, NULL, V) || !allow) { - return(FALSE); - } - - result = MDBodbcDeleteObjectByID(id, Recursive, V); - if (result) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } -} - -static __inline BOOL -MDBodbcDeleteObjectByID(signed long id, BOOL Recursive, MDBValueStruct *V) -{ - SQLINTEGER rc; - BOOL requireBindings; - - if (id == -1) { - /* We don't allow deleting the root */ - return(FALSE); - } - - /* Remove all rights associated with this object */ - PrepareStatement(V->stmts.deleteObjectRights, SQL_DELETE_OBJECT_RIGHTS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteObjectRights, 1, &V->params.deleteObjectRights.object); - } - - if (V->stmts.deleteObjectRights == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteObjectRights.object = id; - rc = ExecuteStatement(V->stmts.deleteObjectRights); - - if (Recursive) { - SQLHSTMT getChildrenIDs = SQL_NULL_HSTMT; - signed long child; - - PrepareStatement(getChildrenIDs, SQL_GET_CHILDREN_IDS, requireBindings, V); - if (requireBindings) { - BindLongInput(getChildrenIDs, 1, &id); - BindLongResult(getChildrenIDs, 1, &child); - } - - if (getChildrenIDs == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(getChildrenIDs); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildrenIDs); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcDeleteObjectByID(child, Recursive, V)) { - ReleaseStatement(V, getChildrenIDs); - return(FALSE); - } - - rc = SQLFetch(getChildrenIDs); - } - - ReleaseStatement(V, getChildrenIDs); - if (rc != SQL_NO_DATA) { - return(FALSE); - } - } else { - SQLINTEGER count = 0; - - /* Fail if there are any children */ - PrepareStatement(V->stmts.hasChildren, SQL_HAS_CHILDREN, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.hasChildren, 1, &V->params.hasChildren.object); - BindLongResult(V->stmts.hasChildren, 1, &V->params.hasChildren.child); - } - - if (V->stmts.hasChildren == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.hasChildren.object = id; - rc = ExecuteStatement(V->stmts.hasChildren); - SQLRowCount(V->stmts.hasChildren, &count); - SQLCloseCursor(V->stmts.hasChildren); - - if (count > 0) { - return(FALSE); - } - } - - /* Ok delete it now */ - PrepareStatement(V->stmts.deleteObjectValues, SQL_DELETE_OBJECT_VALUES, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteObjectValues, 1, &V->params.deleteObjectValues.object); - } - - if (V->stmts.deleteObjectValues == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteObjectValues.object = id; - rc = ExecuteStatement(V->stmts.deleteObjectValues); - - PrepareStatement(V->stmts.deleteObject, SQL_DELETE_OBJECT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.deleteObject, 1, &V->params.deleteObject.object); - } - - if (V->stmts.deleteObject== SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.deleteObject.object = id; - rc = ExecuteStatement(V->stmts.deleteObject); - return(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO); -} - - -BOOL -MDBodbcRenameObject(const unsigned char *ObjectOld, const unsigned char *ObjectNew, MDBValueStruct *V) -{ - signed long object; - signed long id; - unsigned char *new; - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - SQLINTEGER rc; - BOOL requireBindings; - BOOL allow; - SQLINTEGER parent = -1; - - /* Verify that we have good arguments, and that the old object exists and that the new doesn't */ - if (!V || !ObjectNew || !ObjectOld || - !MDBodbcGetObjectID(ObjectOld, &object, NULL, NULL, NULL, NULL, &allow, V) || !allow) - { - return(FALSE); - } - - new = strrchr(ObjectNew, '\\'); - if (new) { - signed long class; - - strncpy(dn, ObjectNew, sizeof(dn)); - - /* A path was given, not just a name. Make sure the object referenced doesn't exist */ - if (MDBodbcGetObjectID(ObjectNew, &id, NULL, NULL, NULL, NULL, NULL, V)) { - return(FALSE); - } - - /* We have a container, so we need to move the object */ - dn[new - ObjectNew] = '\0'; - if (!MDBodbcGetObjectID(dn, &id, NULL, NULL, &allow, NULL, NULL, V) || !allow) { - /* The new container doesn't exist, or we aren't allowed to create in it */ - return(FALSE); - } - - /* Get the class of the object so we can verify containment */ - PrepareStatement(V->stmts.getObjectClass, SQL_GET_OBJECT_CLASS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getObjectClass, 1, &V->params.getObjectClass.object); - BindLongResult(V->stmts.getObjectClass, 1, &V->params.getObjectClass.class); - } - - if (V->stmts.getObjectClass == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.getObjectClass.object = object; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.getObjectClass); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getObjectClass); - SQLCloseCursor(V->stmts.getObjectClass); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - class = V->params.getObjectClass.class; - } else { - return(FALSE); - } - - /* Ok, now verify that the new container can contain this class */ - PrepareStatement(V->stmts.verifyContainment, SQL_VERIFY_CONTAINMENT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.verifyContainment, 1, &V->params.verifyContainment.object); - BindLongInput(V->stmts.verifyContainment, 2, &V->params.verifyContainment.class); - BindLongResult(V->stmts.verifyContainment, 1, &V->params.verifyContainment.class); - } - - if (V->stmts.verifyContainment == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.verifyContainment.object = id; - V->params.verifyContainment.class = class; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.verifyContainment); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.verifyContainment); - SQLCloseCursor(V->stmts.verifyContainment); - } - - if ((rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) || - class != V->params.verifyContainment.class) - { - return(FALSE); - } - - /* - Verify that the new parent is not actual below the object we are trying to - move, because that would cause a detached part of the tree. - */ - PrepareStatement(V->stmts.getParentInfo, SQL_GET_PARENT_INFO, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.getParentInfo, 1, &V->params.getParentInfo.object); - BindLongResult(V->stmts.getParentInfo, 1, &V->params.getParentInfo.object); - BindCharResult(V->stmts.getParentInfo, 2, V->params.getParentInfo.name, MDB_ODBC_NAME_SIZE); - } - - if (V->stmts.getParentInfo == SQL_NULL_HSTMT) { - return(FALSE); - } - - V->params.getParentInfo.object = id; - - do { - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.getParentInfo); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (parent == -1) { - parent = V->params.getParentInfo.object; - } - - rc = SQLFetch(V->stmts.getParentInfo); - SQLCloseCursor(V->stmts.getParentInfo); - } - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - break; - } - } while (V->params.getParentInfo.object != -1 && V->params.getParentInfo.object != object); - - if (V->params.getParentInfo.object == object) { - /* We can't move an object to a container below it */ - return(FALSE); - } - - /* - Now that we know that the object can be moved to the new container, we need to - remove all rights from this object, and all child objects that this object gets - from its parent container. - - We can not remove rights that are provided at a lower level though. Only remove - rights from the children that the current object has. - */ - if (!MDBodbcRemoveInheritedRights(id, TRUE, -1, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - /* Ok, it has now passed all the checks, so the object can be moved */ - PrepareStatement(V->stmts.moveObject, SQL_MOVE_OBJECT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.moveObject, 1, &V->params.moveObject.parent); - BindLongInput(V->stmts.moveObject, 2, &V->params.moveObject.object); - } - - if (V->stmts.moveObject == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - V->params.moveObject.object = object; - V->params.moveObject.parent = id; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.moveObject); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - /* Update the pointer in case the object still needs to be renamed in its new container */ - new++; - - /* Copy the rights from the new container to the object */ - if (!MDBodbcCopyObjectRights(id, object, TRUE, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } else { - /* Verify that an object doesn't exist with this name already */ - strncpy(dn, ObjectOld, sizeof(dn)); - - new = strrchr(dn, '\\'); - if (new) { - *(++new) = '\0'; - } - - strncpy(new, ObjectNew, sizeof(dn) - (new - dn)); - if (MDBodbcGetObjectID(dn, &id, NULL, NULL, NULL, NULL, NULL, V)) { - return(FALSE); - } - - /* No object exists with that name */ - new = (unsigned char *)ObjectNew; - } - - if (*new) { - /* Ok, time to rename */ - PrepareStatement(V->stmts.renameObject, SQL_RENAME_OBJECT, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.renameObject, 1, - &V->params.renameObject.name, &V->params.renameObject.nameLength, MDB_ODBC_NAME_SIZE); - BindLongInput(V->stmts.renameObject, 2, &V->params.renameObject.object); - } - - if (V->stmts.renameObject == SQL_NULL_HSTMT) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - StoreCharInput(new, V->params.renameObject.name, V->params.renameObject.nameLength, MDB_ODBC_NAME_SIZE); - V->params.renameObject.object = object; - - /* Ok, do it */ - rc = ExecuteStatement(V->stmts.renameObject); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); -} - -static __inline BOOL -MDBodbcSetObjectRightsByID(SQLINTEGER trustee, SQLINTEGER object, BOOL fromParent, SQLINTEGER provider, BOOL Read, BOOL Write, BOOL Delete, BOOL Rename, MDBValueStruct *V) -{ - SQLHSTMT getChildrenIDs = SQL_NULL_HSTMT; - SQLINTEGER child; - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.setRights, SQL_SET_RIGHTS, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.setRights, 1, &V->params.setGetRights.object); - BindLongInput(V->stmts.setRights, 2, &V->params.setGetRights.trustee); - BindLongInput(V->stmts.setRights, 3, &V->params.setGetRights.provider); - BindLongInput(V->stmts.setRights, 4, &V->params.setGetRights.parent); - BindLongInput(V->stmts.setRights, 5, &V->params.setGetRights.read); - BindLongInput(V->stmts.setRights, 6, &V->params.setGetRights.write); - BindLongInput(V->stmts.setRights, 7, &V->params.setGetRights.delete); - BindLongInput(V->stmts.setRights, 8, &V->params.setGetRights.rename); - } - - V->params.setGetRights.object = object; - V->params.setGetRights.trustee = trustee; - - V->params.setGetRights.parent = fromParent ? 1 : 0; - V->params.setGetRights.provider = provider; - - V->params.setGetRights.read = Read ? 1 : 0; - V->params.setGetRights.write = Write ? 1 : 0; - V->params.setGetRights.delete = Delete ? 1 : 0; - V->params.setGetRights.rename = Rename ? 1 : 0; - - rc = ExecuteStatement(V->stmts.setRights); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - /* Get the children */ - PrepareStatement(getChildrenIDs, SQL_GET_CHILDREN_IDS, requireBindings, V); - if (requireBindings) { - BindLongInput(getChildrenIDs, 1, &trustee); - BindLongResult(getChildrenIDs, 1, &child); - } - - if (getChildrenIDs == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(getChildrenIDs); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildrenIDs); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcSetObjectRightsByID(child, object, TRUE, provider, Read, Write, Delete, Rename, V)) { - ReleaseStatement(V, getChildrenIDs); - return(FALSE); - } - - rc = SQLFetch(getChildrenIDs); - } - - ReleaseStatement(V, getChildrenIDs); - if (rc != SQL_NO_DATA) { - return(FALSE); - } - - return(TRUE); -} - -static __inline BOOL -MDBodbcRemoveObjectRightsByID(SQLINTEGER trustee, SQLINTEGER object, MDBValueStruct *V) -{ - SQLHSTMT getChildrenIDs = SQL_NULL_HSTMT; - SQLINTEGER child; - SQLINTEGER rc; - BOOL requireBindings; - - PrepareStatement(V->stmts.delRightsByObject, SQL_DEL_RIGHTS_BY_OBJECT, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.delRightsByObject, 1, &V->params.delRightsByObject.object); - BindLongInput(V->stmts.delRightsByObject, 2, &V->params.delRightsByObject.trustee); - } - - V->params.delRightsByObject.object = object; - V->params.delRightsByObject.trustee = trustee; - - rc = ExecuteStatement(V->stmts.delRightsByObject); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - return(FALSE); - } - - /* Get the children */ - PrepareStatement(getChildrenIDs, SQL_GET_CHILDREN_IDS, requireBindings, V); - if (requireBindings) { - BindLongInput(getChildrenIDs, 1, &trustee); - BindLongResult(getChildrenIDs, 1, &child); - } - - if (getChildrenIDs == SQL_NULL_HSTMT) { - return(FALSE); - } - - rc = ExecuteStatement(getChildrenIDs); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(getChildrenIDs); - } - - while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (!MDBodbcRemoveObjectRightsByID(child, object, V)) { - ReleaseStatement(V, getChildrenIDs); - return(FALSE); - } - - rc = SQLFetch(getChildrenIDs); - } - - ReleaseStatement(V, getChildrenIDs); - if (rc != SQL_NO_DATA) { - return(FALSE); - } - - return(TRUE); -} - -BOOL -MDBodbcGrantObjectRights(const unsigned char *Object, const unsigned char *TrusteeDN, BOOL Read, BOOL Write, BOOL Delete, BOOL Rename, BOOL Admin, MDBValueStruct *V) -{ - BOOL requireBindings; - SQLINTEGER rc; - SQLINTEGER object; - SQLINTEGER trustee; - BOOL r; - BOOL w; - BOOL d; - BOOL n; - BOOL allowed; - unsigned long used; - - /* - Ensure that both objects exist, and that we are allowed to write to the trustee - object. We will also get the rights that the current user has to the object, to - ensure that no rights are given that the current user does not have. - */ - if (!Object || !TrusteeDN || !V || - !MDBodbcGetObjectID(Object, &object, NULL, &r, &w, &d, &n, V) || - !MDBodbcGetObjectID(TrusteeDN, &trustee, NULL, NULL, &allowed, NULL, NULL, V) || - !allowed) - { - return(FALSE); - } - - used = V->Used; - - if ((Read && !r) || (Write && !w) || (Delete && !d) || (Rename && !n)) { - /* An attempt was made to give a right that the current user doesn't have */ - return(FALSE); - } - - /* - Ok, we now have the IDs of both objects, and we know that we are allowed to perform - this operation. First remove any right assignment that may already be in place - between this trustee and this object. By removing all rights to this object, where - the provider matches the trustee we can be sure this will work for all cases (child - objects, groups, security equals, etc) - */ - PrepareStatement(V->stmts.delRightsByProviderAndObject, SQL_DEL_RIGHTS_BY_PROVIDER_AND_OBJ, requireBindings, V); - if (requireBindings) { - BindLongInput(V->stmts.delRightsByProviderAndObject, 1, &V->params.delRightsByProviderAndObject.provider); - BindLongInput(V->stmts.delRightsByProviderAndObject, 2, &V->params.delRightsByProviderAndObject.object); - } - - if (V->stmts.delRightsByProviderAndObject != SQL_NULL_HSTMT) { - rc = ExecuteStatement(V->stmts.delRightsByProviderAndObject); - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - } - - if (!MDBodbcRemoveObjectRightsByID(trustee, object, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - /* Update the rights on group members */ - MDBodbcRead(Object, "Member", V); - - while (V->Used > used) { - SQLINTEGER id; - - if (MDBodbcGetObjectID(V->Value[used], &id, NULL, NULL, NULL, NULL, NULL, V) && - !MDBodbcSetObjectRightsByID(id, object, FALSE, trustee, Read, Write, Delete, Rename, V)) - { - while (V->Used > used) { - MDBodbcFreeValue(used, V); - } - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } - - MDBodbcFreeValue(used, V); - } - - /* Alright, now its time to do the same thing, except to assign rights this time. */ - if (MDBodbcSetObjectRightsByID(trustee, object, FALSE, trustee, Read, Write, Delete, Rename, V)) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - return(TRUE); - } else { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - return(FALSE); - } -} - -/* MDB-ODBC does not support MDBGrantAttributeRights. As far as I can tell nothing uses it anyway. */ -BOOL -MDBodbcGrantAttributeRights(const unsigned char *Object, const unsigned char *Attribute, const unsigned char *TrusteeDN, BOOL Read, BOOL Write, BOOL Admin, MDBValueStruct *V) -{ - return(TRUE); -} - -static BOOL -MDBodbcParseArguments(const unsigned char *Arguments) -{ - unsigned char *toFree; - unsigned char *ptr; - unsigned char *end; - BOOL result = TRUE; - - toFree = strdup(Arguments); - ptr = toFree; - - while (ptr) { - end = ptr + 1; - do { - end = strchr(end + 1, ','); - } while (end && end[-1] == '\\'); - - if (end) { - *end = '\0'; - } - - if (XplStrNCaseCmp(ptr, "DSN=", 4) == 0) { - strncpy(MDBodbc.config.dsn, ptr + 4, sizeof(MDBodbc.config.dsn)); - } else if (XplStrNCaseCmp(ptr, "user=", 5) == 0) { - strncpy(MDBodbc.config.user, ptr + 5, sizeof(MDBodbc.config.user)); - } else if (XplStrNCaseCmp(ptr, "pass=", 5) == 0) { - strncpy(MDBodbc.config.pass, ptr + 5, sizeof(MDBodbc.config.pass)); - } else if (XplStrNCaseCmp(ptr, "servername=", 11) == 0) { - strncpy(MDBodbc.config.servername, ptr + 11, sizeof(MDBodbc.config.servername)); - } else if (XplStrNCaseCmp(ptr, "treename=", 9) == 0) { - strncpy(MDBodbc.config.treename, ptr + 9, sizeof(MDBodbc.config.treename)); - } - - ptr = end; - if (ptr) { - ptr++; - } - } - - if (toFree) { - free(toFree); - } - - return(result); -} - -/* - Connect to the DB and ensure that all tables have been created, and that an - object exists for this server. -*/ -static BOOL -MDBodbcSetup() -{ - MDBHandle handle = MDBodbcAuthenticate(NULL, NULL, NULL); - MDBValueStruct *V = (handle) ? MDBodbcCreateValueStruct(handle, NULL) : NULL; - SQLHSTMT stmt = SQL_NULL_HSTMT; - SQLINTEGER rc; - BOOL requireBindings; - BOOL result = TRUE; - unsigned long i = 0; - - if (!V) { - if (handle) { - MDBodbcRelease(handle); - } - - XplConsolePrintf("MDBODBC: Failed to connect to database\n"); - - return(FALSE); - } - - /* Assume that the table does not exist */ - while (result && MDBodbcSQLPrepare[i]) { - PrepareStatement(stmt, MDBodbcSQLPrepare[i], requireBindings, V); - - rc = ExecuteStatement(stmt); - ReleaseStatement(V, stmt); - stmt = SQL_NULL_HSTMT; - - /* - Only return FALSE if it is the first line that fails. There are some other - lines which are expected to fail. A few of the table definitions work differently - for one database than they do for others, so both versions are included, and one - will fail. - */ - if (i == 0 && rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - - result = FALSE; - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - i++; - } - - /* Commit the new tables */ - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - - if (result) { - /* Prepare rights for setup. These rights will allow full access, until they are removed later */ - i = 0; - - while (result && MDBodbcSQLSetPrepareRights[i]) { - SQLSMALLINT count; - - PrepareStatement(stmt, MDBodbcSQLSetPrepareRights[i], requireBindings, V); - rc = SQLNumParams(stmt, &count); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (count == 1) { - /* We know that the only param required is the treename */ - MDBodbc.config.treenameLength = strlen(MDBodbc.config.treename); - BindCharInput(stmt, 1, MDBodbc.config.treename, &MDBodbc.config.treenameLength, MDB_ODBC_NAME_SIZE); - } - - rc = ExecuteStatement(stmt); - } - - ReleaseStatement(V, stmt); - stmt = SQL_NULL_HSTMT; - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - - result = FALSE; - } - - i++; - } - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - - /* Define the default attributes */ - if (result) { - MDBodbcBaseSchemaAttributes *attribute; - - /* End the transaction */ - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - - /* Define the default attributes */ - attribute = &MDBodbcBaseSchemaAttributesList[0]; - while (result && (attribute->name != NULL)) { - result = MDBodbcDefineAttribute(attribute->name, NULL, attribute->type, - attribute->flags & 0x0001, attribute->flags & 0x0040, attribute->flags & 0x0080, V); - - attribute++; - } - } - - /* Define the default classes */ - if (result) { - MDBValueStruct *superclass = MDBodbcShareContext(V); - MDBValueStruct *containedby = MDBodbcShareContext(V); - MDBValueStruct *naming = MDBodbcShareContext(V); - MDBValueStruct *mandatory = MDBodbcShareContext(V); - MDBValueStruct *optional = MDBodbcShareContext(V); - MDBodbcBaseSchemaClasses *c; - MDBodbcBaseSchemaClasses *cSource; - unsigned char *ptr; - unsigned char *cur; - - c = (MDBodbcBaseSchemaClasses *)malloc(sizeof(MDBodbcBaseSchemaClasses)); - if (superclass && containedby && naming && mandatory && optional && c) { - cSource = &MDBodbcBaseSchemaClassesList[0]; - while (result && (cSource->name != NULL)) { - c->flags = cSource->flags; - - c->name = strdup(cSource->name); - - if (cSource->superClass) { - c->superClass = strdup(cSource->superClass); - } else { - c->superClass = NULL; - } - - if (cSource->containedBy) { - c->containedBy = strdup(cSource->containedBy); - } else { - c->containedBy = NULL; - } - - if (cSource->namedBy) { - c->namedBy = strdup(cSource->namedBy); - } else { - c->namedBy = NULL; - } - - if (cSource->mandatory) { - c->mandatory = strdup(cSource->mandatory); - } else { - c->mandatory = NULL; - } - - if (cSource->optional) { - c->optional = strdup(cSource->optional); - } else { - c->optional = NULL; - } - - if (c->superClass) { - MDBodbcAddValue(c->superClass, superclass); - } - - if (c->containedBy) { - ptr = c->containedBy; - - do { - cur = ptr; - ptr = strchr(cur, ','); - if (ptr) { - *ptr = '\0'; - } - - MDBodbcAddValue(cur, containedby); - - if (ptr) { - *ptr = ','; - - ptr++; - } - } while (ptr); - } - - if (c->namedBy) { - ptr = c->namedBy; - - do { - cur = ptr; - ptr = strchr(cur, ','); - if (ptr) { - *ptr = '\0'; - } - - MDBodbcAddValue(cur, naming); - - if (ptr) { - *ptr = ','; - - ptr++; - } - } while (ptr); - } - - if (c->mandatory) { - ptr = c->mandatory; - - do { - cur = ptr; - ptr = strchr(cur, ','); - if (ptr) { - *ptr = '\0'; - } - - MDBodbcAddValue(cur, mandatory); - - if (ptr) { - *ptr = ','; - - ptr++; - } - } while (ptr); - } - - if (c->optional) { - ptr = c->optional; - - do { - cur = ptr; - ptr = strchr(cur, ','); - if (ptr) { - *ptr = '\0'; - } - - MDBodbcAddValue(cur, optional); - - if (ptr) { - *ptr = ','; - - ptr++; - } - } while (ptr); - } - - result = MDBodbcDefineClass(c->name, NULL, c->flags & 0x01, superclass, containedby, naming, mandatory, optional, V); - - free(c->name); - c->name = NULL; - - if (c->superClass) { - free(c->superClass); - c->superClass = NULL; - } - - if (c->containedBy) { - free(c->containedBy); - c->containedBy = NULL; - } - - if (c->namedBy) { - free(c->namedBy); - c->namedBy = NULL; - } - - if (c->mandatory) { - free(c->mandatory); - c->mandatory = NULL; - } - - if (c->optional) { - free(c->optional); - c->optional = NULL; - } - - MDBodbcFreeValues(optional); - MDBodbcFreeValues(mandatory); - MDBodbcFreeValues(naming); - MDBodbcFreeValues(containedby); - MDBodbcFreeValues(superclass); - - cSource++; - } - } - - if (optional) { - MDBodbcDestroyValueStruct(optional); - } - - if (mandatory) { - MDBodbcDestroyValueStruct(mandatory); - } - - if (naming) { - MDBodbcDestroyValueStruct(naming); - } - - if (containedby) { - MDBodbcDestroyValueStruct(containedby); - } - - if (superclass) { - MDBodbcDestroyValueStruct(superclass); - } - - if (c) { - free(c); - } - } - - /* - Create the root of the tree. This must be done after creating the default - class list, but before creating any other objects. This object has an id - of -1. It is the only object with a fixed id, so that we always know where - the root of the tree is. It is also listed as its own parent. This way if - a DN is given with a format of \Tree\Blah\Foo or \Blah\Foo they will both - work correctly. - */ - if (result) { - i = 0; - - while (result && MDBodbcSQLCreateRoot[i]) { - SQLSMALLINT count; - - PrepareStatement(stmt, MDBodbcSQLCreateRoot[i], requireBindings, V); - rc = SQLNumParams(stmt, &count); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - if (count == 1) { - /* We know that the only param required is the treename */ - MDBodbc.config.treenameLength = strlen(MDBodbc.config.treename); - BindCharInput(stmt, 1, MDBodbc.config.treename, &MDBodbc.config.treenameLength, MDB_ODBC_NAME_SIZE); - } - - rc = ExecuteStatement(stmt); - } - - ReleaseStatement(V, stmt); - stmt = SQL_NULL_HSTMT; - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - - result = FALSE; - } - - i++; - } - - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_COMMIT); - } - - /* - Now that we have created the schema, we need to destroy the value struct we have been using - and create a new one. The cached data in that value struct will now be incorrect because there - was no schema when it was created. - */ - MDBodbcDestroyValueStruct(V); - V = MDBodbcCreateValueStruct(handle, NULL); - - /* Create the base objects */ - if (result) { - if (!MDBodbcCreateObject("\\System", "Organization", NULL, NULL, V) || - !MDBodbcCreateObject("\\System\\admin", "User", NULL, NULL, V) || - !MDBodbcCreateObject("\\System\\administrators", "Group", NULL, NULL, V)) - { - XplConsolePrintf("Failed to create default objects\n"); - - result = FALSE; - } - - if (result) { - result = MDBodbcChangePasswordEx("\\System\\admin", NULL, MDBodbc.config.pass, V); - } - - if (result) { - MDBodbcSetValueStructContext("\\System", V); - result = MDBodbcCreateObject(MDBodbc.config.servername, "NCP Server", NULL, NULL, V); - } - } - - if (result) { - /* Create the tree info entry */ - MDBodbcGetObjectID("\\System", &MDBodbc.config.defaultContext, NULL, NULL, NULL, NULL, NULL, V); - - /* Create the tree info entry */ - PrepareStatement(V->stmts.setTreeInfo, SQL_SET_TREE_INFO, requireBindings, V); - if (requireBindings) { - MDBodbc.config.treenameLength = strlen(MDBodbc.config.treename); - BindCharInput(V->stmts.setTreeInfo, 1, - &MDBodbc.config.treename, &MDBodbc.config.treenameLength, sizeof(MDBodbc.config.treename)); - BindLongInput(V->stmts.setTreeInfo, 2, &MDBodbc.config.defaultContext); - } - - rc = ExecuteStatement(V->stmts.setTreeInfo); - result = (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO); - ReleaseStatement(V, stmt); - } - - if (result) { - i = 0; - - while (result && MDBodbcSQLSetInitialRights[i]) { - PrepareStatement(stmt, MDBodbcSQLSetInitialRights[i], requireBindings, V); - rc = ExecuteStatement(stmt); - - ReleaseStatement(V, stmt); - stmt = SQL_NULL_HSTMT; - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - - result = FALSE; - } - - i++; - } - } - - if (!result) { - SQLEndTran(SQL_HANDLE_DBC, V->handle->connection, SQL_ROLLBACK); - } - - MDBodbcDestroyValueStruct(V); - MDBodbcRelease(handle); - ReleaseStatement(V, stmt); - - return(result); - } else { - /* The tree is already setup, just read the tree info */ - PrepareStatement(V->stmts.getTreeInfo, SQL_GET_TREE_INFO, requireBindings, V); - if (requireBindings) { - BindCharResult(V->stmts.getTreeInfo, 1, MDBodbc.config.treename, sizeof(MDBodbc.config.treename)); - BindLongResult(V->stmts.getTreeInfo, 2, &MDBodbc.config.defaultContext); - } - - rc = ExecuteStatement(V->stmts.getTreeInfo); - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getTreeInfo); - } - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - SQLCloseCursor(V->stmts.getTreeInfo); - - } - } - - /* - Get the ID of the 'Member' attribute. It is a special attribute in that we - need to update rights whenever it is written to (or cleared). - */ - PrepareStatement(V->stmts.getAttrByName, SQL_GET_ATTRIBUTE_BY_NAME, requireBindings, V); - if (requireBindings) { - BindCharInput(V->stmts.getAttrByName, 1, - V->params.getAttrByName.attribute, &V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - BindLongResult(V->stmts.getAttrByName, 1, &V->params.getAttrByName.id); - } - - StoreCharInput("Member", V->params.getAttrByName.attribute, V->params.getAttrByName.attributeLength, MDB_ODBC_NAME_SIZE); - - /* Ok, we're all setup - Do the query */ - rc = ExecuteStatement(V->stmts.getAttrByName); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - rc = SQLFetch(V->stmts.getAttrByName); - SQLCloseCursor(V->stmts.getAttrByName); - } - - /* Cleanup */ - MDBodbcDestroyValueStruct(V); - MDBodbcRelease(handle); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - MDBodbc.config.special.member = V->params.getAttrByName.id; - return(TRUE); - } else { - return(FALSE); - } -} - -EXPORT BOOL -MDBODBCInit(MDBDriverInitStruct *Init) -{ - MDBodbc.unload = FALSE; - SQLINTEGER rc; - - /* Allocate the ODBC environment */ - MDBodbc.env = SQL_NULL_HENV; - rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &MDBodbc.env); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - return(FALSE); - } - - rc = SQLSetEnvAttr(MDBodbc.env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLFreeHandle(SQL_HANDLE_ENV, MDBodbc.env); - return(FALSE); - } - - /* - Setup some defaults - - If a username or password isn't provided in Init->Arguments we'll have to assume that the - DSN is already configured with a proper username and password. - */ - memset(&MDBodbc.config, 0, sizeof(MDBodbc.config)); - strcpy(MDBodbc.config.dsn, "MDB"); - strcpy(MDBodbc.config.treename, "Tree"); - - gethostname(MDBodbc.config.servername, sizeof(MDBodbc.config.servername)); - - if (Init->Arguments) { - MDBodbcParseArguments(Init->Arguments); - } - - Init->Interface.MDBAdd = MDBodbcAdd; - Init->Interface.MDBAddAttribute = MDBodbcAddAttribute; - Init->Interface.MDBAddDN = MDBodbcAddDN; - Init->Interface.MDBAddValue = MDBodbcAddValue; - Init->Interface.MDBAuthenticate = MDBodbcAuthenticate; - Init->Interface.MDBChangePassword = MDBodbcChangePassword; - Init->Interface.MDBChangePasswordEx = MDBodbcChangePasswordEx; - Init->Interface.MDBClear = MDBodbcClear; - Init->Interface.MDBCreateAlias = MDBodbcCreateAlias; - Init->Interface.MDBCreateEnumStruct = MDBodbcCreateEnumStruct; - Init->Interface.MDBCreateObject = MDBodbcCreateObject; - Init->Interface.MDBCreateValueStruct = MDBodbcCreateValueStruct; - Init->Interface.MDBDefineAttribute = MDBodbcDefineAttribute; - Init->Interface.MDBDefineClass = MDBodbcDefineClass; - Init->Interface.MDBDeleteObject = MDBodbcDeleteObject; - Init->Interface.MDBDestroyEnumStruct = MDBodbcDestroyEnumStruct; - Init->Interface.MDBDestroyValueStruct = MDBodbcDestroyValueStruct; - Init->Interface.MDBEnumerateAttributesEx = MDBodbcEnumerateAttributesEx; - Init->Interface.MDBEnumerateObjects = MDBodbcEnumerateObjects; - Init->Interface.MDBEnumerateObjectsEx = MDBodbcEnumerateObjectsEx; - Init->Interface.MDBFreeValue = MDBodbcFreeValue; - Init->Interface.MDBFreeValues = MDBodbcFreeValues; - Init->Interface.MDBGetObjectDetails = MDBodbcGetObjectDetails; - Init->Interface.MDBGetObjectDetailsEx = MDBodbcGetObjectDetailsEx; - Init->Interface.MDBGetServerInfo = MDBodbcGetServerInfo; - Init->Interface.MDBGetBaseDN = MDBodbcGetBaseDN; - Init->Interface.MDBGrantAttributeRights = MDBodbcGrantAttributeRights; - Init->Interface.MDBGrantObjectRights = MDBodbcGrantObjectRights; - Init->Interface.MDBIsObject = MDBodbcIsObject; - Init->Interface.MDBListContainableClasses = MDBodbcListContainableClasses; - Init->Interface.MDBListContainableClassesEx = MDBodbcListContainableClassesEx; - Init->Interface.MDBRead = MDBodbcRead; - Init->Interface.MDBReadDN = MDBodbcRead; - Init->Interface.MDBReadEx = MDBodbcReadEx; - Init->Interface.MDBRelease = MDBodbcRelease; - Init->Interface.MDBRemove = MDBodbcRemove; - Init->Interface.MDBRemoveDN = MDBodbcRemoveDN; - Init->Interface.MDBRenameObject = MDBodbcRenameObject; - Init->Interface.MDBSetValueStructContext = MDBodbcSetValueStructContext; - Init->Interface.MDBShareContext = MDBodbcShareContext; - Init->Interface.MDBUndefineAttribute = MDBodbcUndefineAttribute; - Init->Interface.MDBUndefineClass = MDBodbcUndefineClass; - Init->Interface.MDBVerifyPassword = MDBodbcVerifyPassword; - Init->Interface.MDBVerifyPasswordEx = MDBodbcVerifyPassword; - Init->Interface.MDBWrite = MDBodbcWrite; - Init->Interface.MDBWriteDN = MDBodbcWriteDN; - Init->Interface.MDBWriteTyped = MDBodbcWriteTyped; - - if (!MDBodbcSetup()) { - SQLFreeHandle(SQL_HANDLE_ENV, MDBodbc.env); - return(FALSE); - } else { - return(TRUE); - } -} - -EXPORT void -MDBODBCShutdown(void) -{ - SQLFreeHandle(SQL_HANDLE_ENV, MDBodbc.env); - MDBodbc.unload = TRUE; - return; -} - -#if defined(NETWARE) || defined(LIBC) -int -MDBodbcRequestUnload(void) -{ - if (!MDBodbc.unload) { - int OldTGid; - - OldTGid=XplSetThreadGroupID(MDBodbc.id.group); - - XplConsolePrintf("\rThis NLM will automatically be unloaded by the thread that loaded it.\n"); - XplConsolePrintf("\rIt does not allow manual unloading.\n"); - XplSetCurrentScreen(XplCreateScreen("System Console", 0)); - XplUngetCh('n'); - - XplSetThreadGroupID(OldTGid); - - return(1); - } - - return(0); -} - -void -MDBodbcSigHandler(int Signal) -{ - int OldTGid; - - OldTGid=XplSetThreadGroupID(MDBodbc.id.group); - - XplSignalLocalSemaphore(MDBodbc.sem.shutdown); - XplWaitOnLocalSemaphore(MDBodbc.sem.shutdown); - - /* Do any required cleanup */ - MDBodbcShutdown(); - - XplCloseLocalSemaphore(MDBodbc.sem.shutdown); - XplSetThreadGroupID(OldTGid); -} - -int -main(int argc, char *argv[]) -{ - MDBodbc.id.main=XplGetThreadID(); - MDBodbc.id.group=XplGetThreadGroupID(); - - signal(SIGTERM, MDBodbcSigHandler); - - /* - This will "park" the module 'til we get unloaded; - it would not be neccessary to do this on NetWare, - but to prevent from automatically exiting on Unix - we need to keep main around... - */ - - XplOpenLocalSemaphore(MDBodbc.sem.shutdown, 0); - XplWaitOnLocalSemaphore(MDBodbc.sem.shutdown); - XplSignalLocalSemaphore(MDBodbc.sem.shutdown); - return(0); -} -#endif - -#ifdef WIN32 -BOOL WINAPI -DllMain(HINSTANCE hInst, DWORD Reason, LPVOID Reserved) -{ - if (Reason == DLL_PROCESS_ATTACH) { - DisableThreadLibraryCalls(hInst); - } - - return(TRUE); -} -#endif - -/* StreamIO needs this */ -BOOL -MWHandleNamedTemplate(void *ignored1, unsigned char *ignored2, void *ignored3) -{ - return(FALSE); -} diff --git a/src/libs/mdb-odbc/mdbodbcp.h b/src/libs/mdb-odbc/mdbodbcp.h deleted file mode 100644 index 52bb71b..0000000 --- a/src/libs/mdb-odbc/mdbodbcp.h +++ /dev/null @@ -1,956 +0,0 @@ -#ifndef MDBODBCP_H -#define MDBODBCP_H - -#define MDB_ODBC_ROOT_ID -1 -#define VALUE_ALLOC_SIZE 20 -#define MDB_ODBC_NAME_SIZE 64 -#define MDB_ODBC_PART_SIZE 255 - -typedef struct { - /* Semi-public; known to the main MDB library */ - unsigned char Description[128]; - struct _MDBInterfaceStruct *Interface; - - /* Private */ - signed long object; - SQLHDBC connection; -} MDBodbcContextStruct; - -typedef MDBodbcContextStruct *MDBHandle; - -typedef struct { - /* Public part, exposed to allow simpler code */ - unsigned char **Value; - unsigned long Used; - unsigned long ErrNo; - struct _MDBInterfaceStruct *Interface; - - /* Private part, not exposed in public header */ - unsigned long Allocated; - MDBodbcContextStruct *handle; - - signed long statementCount; - - /* - The base pointer will be used whenever the Base DN ID is needed. This is - a pointer so that it can be set to the address of another value struct when - MDBShareContext() is used. - */ - struct { - SQLINTEGER *id; - SQLINTEGER value; - - SQLINTEGER *class; - SQLINTEGER classValue; - - BOOL *read; - BOOL readValue; - BOOL *write; - BOOL writeValue; - BOOL *delete; - BOOL deleteValue; - BOOL *rename; - BOOL renameValue; - } base; - - struct { - unsigned char dn[255 + 1]; - SQLINTEGER id; - SQLINTEGER class; - - BOOL read; - BOOL write; - BOOL delete; - BOOL rename; - unsigned long time; - } cache; - - struct { - SQLHSTMT asArray[0]; - SQLHSTMT getTreeInfo; - SQLHSTMT setTreeInfo; - SQLHSTMT getRootRights; - SQLHSTMT getRightsProviders; - SQLHSTMT getRights; - SQLHSTMT setRights; - SQLHSTMT delRightsByProviderAndObject; - SQLHSTMT delRightsByProvider; - SQLHSTMT delRightsByObject; - SQLHSTMT delRightsByParent; - SQLHSTMT delRightsByChild; - SQLHSTMT getObjectID; - SQLHSTMT getAttrByName; - SQLHSTMT getClassByName; - SQLHSTMT getObjectAttrInfo; - SQLHSTMT getParentInfo; - SQLHSTMT getObjectClass; - SQLHSTMT getObjectClassName; - SQLHSTMT verifyContainment; - SQLHSTMT listContainment; - SQLHSTMT createObject; - SQLHSTMT createAttribute; - SQLHSTMT createClass; - SQLHSTMT createSuperClass; - SQLHSTMT deleteObjectValues; - SQLHSTMT deleteObjectRights; - SQLHSTMT deleteObject; - SQLHSTMT copySuperClass; - SQLHSTMT createContainment; - SQLHSTMT createMandatory; - SQLHSTMT getMandatoryByName; - SQLHSTMT createOptional; - SQLHSTMT createNaming; - SQLHSTMT copyContainment; - SQLHSTMT copyMandatory; - SQLHSTMT copyOptional; - SQLHSTMT copyNaming; - SQLHSTMT clearAttribute; - SQLHSTMT addDNValue; - SQLHSTMT addStringValue; - SQLHSTMT addBoolValue; - SQLHSTMT moveObject; - SQLHSTMT renameObject; - SQLHSTMT verifyPassword; - SQLHSTMT setPassword; - SQLHSTMT deleteAttr; - SQLHSTMT deleteAttrFromMandatory; - SQLHSTMT deleteAttrFromOptional; - SQLHSTMT deleteAttrFromNaming; - SQLHSTMT deleteAttrFromValues; - SQLHSTMT deleteAttrFromRights; - SQLHSTMT deleteClassFromContainment; - SQLHSTMT deleteClassFromMandatory; - SQLHSTMT deleteClassFromOptional; - SQLHSTMT deleteClassFromNaming; - SQLHSTMT deleteClass; - SQLHSTMT readValue; - SQLHSTMT getChildren; - SQLHSTMT getChildrenByClass; - SQLHSTMT getChildrenIDs; - SQLHSTMT hasChildren; - } stmts; - - union { - struct { - SQLINTEGER read; - SQLINTEGER write; - SQLINTEGER delete; - SQLINTEGER rename; - } getRootRights; - - struct { - SQLINTEGER trustee; - SQLINTEGER provider; - } getRightsProviders; - - /* Used by getRights and setRights */ - struct { - SQLINTEGER object; - SQLINTEGER trustee; - SQLINTEGER provider; - SQLINTEGER parent; - SQLINTEGER read; - SQLINTEGER write; - SQLINTEGER delete; - SQLINTEGER rename; - } setGetRights; - - struct { - SQLINTEGER provider; - SQLINTEGER object; - } delRightsByProviderAndObject; - - struct { - SQLINTEGER provider; - } delRightsByProvider; - - struct { - SQLINTEGER object; - SQLINTEGER trustee; - } delRightsByObject; - - struct { - SQLINTEGER trustee; - } delRightsByParent; - - struct { - SQLINTEGER provider; - SQLINTEGER trustee; - } delRightsByChild; - - struct { - unsigned char object[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER objectLength; - SQLINTEGER id; - SQLINTEGER class; - SQLINTEGER read; - SQLINTEGER write; - SQLINTEGER delete; - SQLINTEGER rename; - } getObjectID; - - struct { - unsigned char attribute[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER attributeLength; - SQLINTEGER id; - } getAttrByName; - - struct { - SQLINTEGER attribute; - } deleteAttr; - - struct { - SQLINTEGER object; - unsigned char attribute[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER attributeLength; - SQLINTEGER id; - SQLINTEGER single; - SQLINTEGER type; - } getObjectAttrInfo; - - struct { - SQLINTEGER object; - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - } getParentInfo; - - struct { - SQLINTEGER object; - SQLINTEGER class; - } getObjectClass; - - struct { - SQLINTEGER object; - unsigned char class[MDB_ODBC_NAME_SIZE + 1]; - } getObjectClassName; - - struct { - SQLINTEGER object; - SQLINTEGER child; - } hasChildren; - - struct { - SQLINTEGER object; - SQLINTEGER class; - } verifyContainment; - - struct { - SQLINTEGER object; - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - } listContainment; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER parent; - SQLINTEGER parentClass; - unsigned char class[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER classLength; - } createObject; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER type; - SQLINTEGER single; - SQLINTEGER public; - } createAttribute; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER container; - } createClass; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } getClassByName; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } createSuperClass; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } copySuperClass; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } createContainment; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } createMandatory; - - struct { - unsigned char class[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER classLength; - } getMandatoryByName; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } createOptional; - - struct { - unsigned char name[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER nameLength; - SQLINTEGER class; - } createNaming; - - struct { - SQLINTEGER object; - } deleteObjectValues; - - struct { - SQLINTEGER object; - } deleteObjectRights; - - struct { - SQLINTEGER object; - } deleteObject; - - struct { - SQLINTEGER class; - } copyContainment; - - struct { - SQLINTEGER class; - } copyMandatory; - - struct { - SQLINTEGER class; - } copyOptional; - - struct { - SQLINTEGER class; - } copyNaming; - - struct { - SQLINTEGER object; - SQLINTEGER attribute; - } clearAttribute; - - struct { - SQLINTEGER owner; - SQLINTEGER attribute; - SQLINTEGER value; - } addDNValue; - - struct { - SQLINTEGER owner; - SQLINTEGER attribute; - unsigned char value[MDB_ODBC_PART_SIZE + 1]; - SQLINTEGER valueLength; - SQLINTEGER complete; - } addStringValue; - - struct { - SQLINTEGER owner; - SQLINTEGER attribute; - SQLINTEGER value; - } addBoolValue; - - struct { - SQLINTEGER object; - SQLINTEGER parent; - } moveObject; - - struct { - SQLINTEGER object; - unsigned char name[MDB_ODBC_PART_SIZE + 1]; - SQLINTEGER nameLength; - } renameObject; - - struct { - SQLINTEGER object; - unsigned char pass[32 + 1]; - SQLINTEGER passLength; - } verifyPassword; - - struct { - SQLINTEGER object; - unsigned char pass[32 + 1]; - SQLINTEGER passLength; - } setPassword; - - struct { - SQLINTEGER attribute; - } deleteAttrFromMandatory; - - struct { - SQLINTEGER attribute; - } deleteAttrFromOptional; - - struct { - SQLINTEGER attribute; - } deleteAttrFromNaming; - - struct { - SQLINTEGER attribute; - } deleteAttrFromValues; - - struct { - SQLINTEGER attribute; - } deleteAttrFromRights; - - struct { - SQLINTEGER class; - } deleteClassFromContainment; - - struct { - SQLINTEGER class; - } deleteClassFromMandatory; - - struct { - SQLINTEGER class; - } deleteClassFromOptional; - - struct { - SQLINTEGER class; - } deleteClassFromNaming; - - struct { - SQLINTEGER class; - } deleteClass; - - struct { - SQLINTEGER object; - SQLINTEGER dn; - SQLINTEGER bool; - SQLINTEGER complete; - SQLINTEGER type; - unsigned char attribute[MDB_ODBC_NAME_SIZE + 1]; - unsigned long attributeLength; - unsigned char value[MDB_ODBC_PART_SIZE + 1]; - } readValue; - - /* getChildren is also used by getChildrenByClass */ - struct { - SQLINTEGER object; - SQLINTEGER container; - unsigned char class[MDB_ODBC_NAME_SIZE + 1]; - unsigned long classLength; - unsigned char child[MDB_ODBC_NAME_SIZE + 1]; - SQLINTEGER allContainers; - } getChildren; - - struct { - SQLINTEGER object; - SQLINTEGER child; - } getChildrenIDs; - } params; -} MDBValueStruct; - -typedef struct { - char *sql; - SQLHSTMT stmt; - - /* This buffer should be large enough for any enum response */ - unsigned char result[MDB_ODBC_PART_SIZE + 1]; - - /* Used for returning DN results where only the name changes from response to response */ - unsigned char dn[MDB_ODBC_PART_SIZE + 1]; - unsigned char class[MDB_ODBC_PART_SIZE + 1]; - SQLINTEGER classlen; - unsigned char *name; - - SQLINTEGER object; - - /* These are all included as possible responses */ - SQLINTEGER id; - SQLINTEGER bool; - SQLINTEGER complete; - SQLINTEGER type; - SQLINTEGER container; - SQLINTEGER allContainers; - - /* This should be used if MDBReadEx() reads a value alrger than MDB_ODBC_PART_SIZE */ - unsigned char *largeResult; -} MDBEnumStruct; - -/* - Do as much static setup as can be done here. Some things, such as setting the - admin password, or creating the tree entry will have to be done seperately since - they are dynamic. - - We attempt to create some of the tables twice. This is because mysql does not support - SERIAL. If we fail to create a table using SERIAL then we will try again with - INTEGER AUTO_INCREMENT UNIQUE, which as far as this driver is concerned is the same thing. - - The last line creates the root object. It can not be created with the regular - creation statement for objects because it has no parent object. -*/ -unsigned char *MDBodbcSQLPrepare[] = { - "CREATE TABLE treeinfo" \ - "(" \ - "name varchar(64)," \ - "defaultContainer INTEGER" \ - ");", - "CREATE TABLE objects" \ - "(" \ - "id SERIAL," \ - "name varchar(64)," \ - "class INTEGER," \ - "parent INTEGER," \ - "pass char(32)" \ - ");", - "CREATE TABLE objects" \ - "(" \ - "id INTEGER AUTO_INCREMENT UNIQUE," \ - "name varchar(64)," \ - "class INTEGER," \ - "parent INTEGER," \ - "pass char(32)" \ - ");", - "CREATE TABLE classes" \ - "(" \ - "id SERIAL," \ - "name varchar(64) UNIQUE," \ - "container INTEGER" \ - ");", - "CREATE TABLE classes" \ - "(" \ - "id INTEGER AUTO_INCREMENT UNIQUE," \ - "name varchar(64) UNIQUE," \ - "container INTEGER" \ - ");", - "CREATE TABLE superclasses" \ - "(" \ - "subclass INTEGER," \ - "superclass INTEGER" \ - ");", - "CREATE TABLE containment" \ - "(" \ - "container INTEGER," \ - "leaf INTEGER" \ - ");", - "CREATE TABLE attributes" \ - "(" \ - "id SERIAL," \ - "name varchar(64)," \ - "type INTEGER," \ - "single INTEGER," \ - "public INTEGER" \ - ");", - "CREATE TABLE attributes" \ - "(" \ - "id INTEGER AUTO_INCREMENT UNIQUE," \ - "name varchar(64)," \ - "type INTEGER," \ - "single INTEGER," \ - "public INTEGER" \ - ");", - "CREATE TABLE mandatory" \ - "(" \ - "attribute INTEGER," \ - "class INTEGER" \ - ");", - "CREATE TABLE optional" \ - "(" \ - "attribute INTEGER," \ - "class INTEGER" \ - ");", - "CREATE TABLE naming" \ - "(" \ - "attribute INTEGER," \ - "class INTEGER" \ - ");", - "CREATE TABLE data" \ - "(" \ - "id SERIAL," \ - "object INTEGER," \ - "attribute INTEGER," \ - "value VARCHAR(255)" \ - " DEFAULT ' '," \ - "dnvalue INTEGER DEFAULT -1," \ - "boolvalue INTEGER DEFAULT -1," \ - "complete INTEGER DEFAULT -1" \ - ");", - "CREATE TABLE data" \ - "(" \ - "id INTEGER AUTO_INCREMENT UNIQUE," \ - "object INTEGER," \ - "attribute INTEGER," \ - "value VARCHAR(255)" \ - " DEFAULT ' '," \ - "dnvalue INTEGER DEFAULT -1," \ - "boolvalue INTEGER DEFAULT -1," \ - "complete INTEGER DEFAULT -1" \ - ");", - "CREATE TABLE rights" \ - "(" \ - "object INTEGER DEFAULT -1," \ - "trustee INTEGER DEFAULT -1," \ - "provider INTEGER DEFAULT -1," \ - "r INTEGER DEFAULT -1," \ - "w INTEGER DEFAULT -1," \ - "d INTEGER DEFAULT -1," \ - "n INTEGER DEFAULT -1," \ - "parent INTEGER DEFAULT 0" \ - ");", - - "CREATE INDEX objects_index ON objects (id, parent, class, name);", - "CREATE INDEX classes_index ON classes (id, name);", - "CREATE INDEX superclasses_index ON superclasses (subclass);", - "CREATE INDEX containment_index ON containment (container, leaf);", - "CREATE INDEX attributes_index ON attributes (id, name);", - "CREATE INDEX mandatory_index ON mandatory (class);", - "CREATE INDEX optional_index ON optional (class);", - "CREATE INDEX naming_index ON naming (class);", - "CREATE INDEX values_index ON data (object, attribute);", - "CREATE INDEX rights_index ON rights (object, trustee);", - NULL -}; - -unsigned char *MDBodbcSQLCreateRoot[] = { - "DELETE FROM objects;", - "INSERT INTO objects (id, name, parent, class)" \ - " SELECT -1, ?, -1, id FROM classes WHERE UCASE(name)=UCASE('Top');", - NULL -}; - -/* - Set the rights to be such that anything is allowed by anyone while the setup - is being run. This will be changed after setup is complete. -*/ -unsigned char *MDBodbcSQLSetPrepareRights[] = { - "INSERT INTO objects (id, name, parent, class)" \ - " VALUES (-1, ?, -1, -1);", - "INSERT INTO rights (object, trustee, r, w, d, n)" \ - " VALUES(-1, -1, 1, 1, 1, 1);", - NULL -}; - -/* - Removes the temporary rights used during setup, and set the default rights - which are none. Also provide full rights to the root to the administrators - group, and to admin. -*/ -unsigned char *MDBodbcSQLSetInitialRights[] = { - "DELETE FROM rights;", - "INSERT INTO rights (object) VALUES (-1);", - "INSERT INTO rights (object, provider, trustee, r, w, d, n)" \ - " SELECT -1, objects.id, objects.id, 1, 1, 1, 1" \ - " FROM objects WHERE UCASE(objects.name)=UCASE('Administrators') OR" \ - " UCASE(objects.name)=UCASE('Admin');", - NULL -}; - -#define REMOVE_TABLES "DROP TABLE treeinfo; DROP TABLE objects;" \ - "DROP TABLE classes;DROP TABLE superclasses; DROP TABLE containment;" \ - "DROP TABLE attributes;DROP TABLE mandatory; DROP TABLE optional;" \ - "DROP TABLE data;DROP TABLE rights; DROP TABLE naming;" - -#define SQL_GET_TREE_INFO "SELECT name, defaultContainer FROM treeinfo LIMIT 1;" -#define SQL_SET_TREE_INFO "INSERT INTO treeinfo (name, defaultContainer) VALUES (?, ?);" -#define SQL_GET_ROOT_RIGHTS "SELECT r, w, d, n FROM rights WHERE trustee=? AND object=-1;" -#define SQL_DEL_RIGHTS_BY_PROVIDER_AND_OBJ "DELETE FROM rights WHERE provider=? AND object=?;" -#define SQL_DEL_RIGHTS_BY_OBJECT "DELETE FROM rights WHERE object=? AND trustee=?;" -#define SQL_GET_RIGHTS_PROVIDERS "SELECT provider FROM rights WHERE trustee=? AND parent=1;" -#define SQL_DEL_RIGHTS_BY_CHILD "DELETE FROM rights WHERE provider=? AND trustee=? AND parent=1;" -#define SQL_DEL_RIGHTS_BY_PROVIDER "DELETE FROM rights WHERE provider=? AND provider!=trustee;" - -#define SQL_SET_RIGHTS "INSERT INTO rights (object, trustee, provider, parent, r, w, d, n) VALUES (?, ?, ?, ?, ?, ?, ?, ?);" -#define SQL_GET_RIGHTS "SELECT provider, object, r, w, d, n FROM rights WHERE trustee=?;" - -#define SQL_GET_OBJECT_ID "SELECT objects.id, objects.class, rights.r, rights.w, rights.d, rights.n FROM objects, rights" \ - " WHERE UCASE(objects.name)=UCASE(?) AND objects.parent=? AND" \ - " ((rights.object=objects.id AND rights.trustee=?) OR (rights.object=-1 AND rights.trustee=-1))"\ - " ORDER BY rights.trustee DESC LIMIT 1;" -#define SQL_GET_ATTRIBUTE_BY_NAME "SELECT id FROM attributes WHERE UCASE(name)=UCASE(?);" -#define SQL_GET_CLASS_BY_NAME "SELECT id FROM classes WHERE UCASE(name)=UCASE(?);" - -#define SQL_GET_CHILDREN "SELECT objects.name, classes.container FROM objects, classes WHERE objects.parent=? AND objects.id>0 AND objects.class=classes.id;" -#define SQL_GET_CHILDREN_BY_CLASS "SELECT objects.name, classes.container FROM objects, classes WHERE objects.parent=? AND objects.id>0 AND objects.class=classes.id" \ - " AND (UCASE(classes.name)=UCASE(?) OR classes.container=?);" -#define SQL_HAS_CHILDREN "SELECT id FROM objects WHERE parent=? LIMIT 1;" -#define SQL_GET_CHILDREN_IDS "SELECT id FROM objects WHERE parent=? AND id > 0;" - - -/* - This really nasty bit of SQL will create an object with the specified name, and - specified class in the specified parent container, if that class is allowed in - that container class. -*/ -#define SQL_CREATE_OBJECT \ - "INSERT INTO objects (name, parent, class)" \ - " SELECT ?, ?, classes.id FROM classes, containment" \ - " WHERE UCASE(classes.name)=UCASE(?)" \ - " AND classes.id=containment.leaf" \ - " AND containment.container=?" \ - " LIMIT 1;" - -#define SQL_RENAME_OBJECT "UPDATE objects SET name=? WHERE id=?;" -#define SQL_MOVE_OBJECT "UPDATE objects SET parent=? WHERE id=?;" -#define SQL_VERIFY_CONTAINMENT "SELECT containment.leaf FROM containment, objects WHERE objects.id=? AND objects.class=containment.container AND containment.leaf=?;" -#define SQL_LIST_CONTAINMENT "SELECT classes.name FROM classes, containment, objects WHERE containment.leaf=classes.id AND containment.container=objects.class AND objects.id=?;" - -#define SQL_CREATE_ATTRIBUTE "INSERT INTO attributes (name, type, single, public) VALUES (?, ?, ?, ?);" -#define SQL_CREATE_CLASS "INSERT INTO classes (name, container) VALUES (?, ?);" -#define SQL_CREATE_SUPERCLASS "INSERT INTO superclasses (subclass, superclass) SELECT ?, id FROM classes where UCASE(name)=UCASE(?);" -#define SQL_CREATE_CONTAINMENT "INSERT INTO containment (leaf, container) SELECT ?, id FROM classes where UCASE(name)=UCASE(?);" -#define SQL_CREATE_MANDATORY "INSERT INTO mandatory (class, attribute) SELECT ?, id FROM attributes where UCASE(name)=UCASE(?);" -#define SQL_CREATE_OPTIONAL "INSERT INTO optional (class, attribute) SELECT ?, id FROM attributes where UCASE(name)=UCASE(?);" -#define SQL_CREATE_NAMING "INSERT INTO naming (class, attribute) SELECT ?, id FROM attributes where UCASE(name)=UCASE(?);" - -#define SQL_GET_OBJECT_CLASS "SELECT class FROM objects WHERE id=?;" -#define SQL_GET_OBJECT_CLASSNAME "SELECT classes.name FROM classes, objects WHERE objects.id=? AND objects.class=classes.id;" - - -#define SQL_GET_NAMING "SELECT attributes.name FROM attributes, naming WHERE attributes.id=naming.attribute and naming.class=?;" -#define SQL_GET_MANDATORY "SELECT attributes.name FROM attributes, mandatory WHERE attributes.id=mandatory.attribute and mandatory.class=?;" -#define SQL_GET_MANDATORY_BY_NAME "SELECT attributes.name FROM attributes, classes, mandatory WHERE" \ - " mandatory.attribute=attributes.id AND mandatory.class=classes.id" \ - " and UCASE(classes.name)=UCASE(?);" -#define SQL_GET_PARENT_INFO "SELECT parent, name FROM objects WHERE id=?;" - -/* If the specified attribute can be written to the specified object then a single row will be returned, with the attribute ID and a BOOL specifiying single or multi value */ -#define SQL_GET_OBJECT_ATTR_INFO "SELECT attributes.id, attributes.single, attributes.type FROM attributes, objects, optional WHERE objects.id=? AND objects.class=optional.class AND UCASE(attributes.name)=UCASE(?) AND attributes.id=optional.attribute LIMIT 1;" - -#define SQL_ADD_DN_VALUE "INSERT INTO data (object, attribute, dnvalue) VALUES (?, ?, ?);" -#define SQL_REMOVE_DN_VALUE "DELETE FROM data WHERE object=? AND attribute=? AND dnvalue=?;" -#define SQL_ADD_BOOL_VALUE "INSERT INTO data (object, attribute, boolvalue) VALUES (?, ?, ?);" -#define SQL_REMOVE_BOOL_VALUE "DELETE FROM data WHERE object=? AND attribute=? AND boolvalue=?;" -#define SQL_ADD_STRING_VALUE "INSERT INTO data (object, attribute, value, complete) VALUES (?, ?, ?, ?);" -#define SQL_REMOVE_STRING_VALUE "DELETE FROM data WHERE object=? AND attribute=? AND value=?;" - -#define SQL_READ_VALUE "SELECT data.value, data.dnvalue, data.boolvalue, data.complete, attributes.type FROM data, attributes WHERE data.object=? AND data.attribute=attributes.id AND UCASE(attributes.name)=UCASE(?) ORDER BY data.id;" - -/* Copy data from all superclasses to a new class */ -#define SQL_COPY_SUPERCLASSES "INSERT INTO superclasses (subclass, superclass) SELECT ?, superclasses.superclass FROM superclasses, classes WHERE superclasses.subclass=classes.id AND UCASE(classes.name)=UCASE(?);" -#define SQL_COPY_CONTAINMENT "INSERT INTO containment (container, leaf) SELECT containment.container, superclasses.subclass FROM containment, superclasses WHERE containment.leaf=superclasses.superclass and superclasses.subclass=?;" -#define SQL_COPY_MANDATORY "INSERT INTO mandatory (attribute, class) SELECT mandatory.attribute, superclasses.subclass FROM mandatory, superclasses WHERE mandatory.class=superclasses.superclass and superclasses.subclass=?;" -#define SQL_COPY_OPTIONAL "INSERT INTO optional (attribute, class) SELECT optional.attribute, superclasses.subclass FROM optional, superclasses WHERE optional.class=superclasses.superclass and superclasses.subclass=?;" -#define SQL_COPY_NAMING "INSERT INTO naming (attribute, class) SELECT naming.attribute, superclasses.subclass FROM naming, superclasses WHERE naming.class=superclasses.superclass and superclasses.subclass=?;" - -#define SQL_CLEAR_ATTRIBUTE "DELETE FROM data WHERE object=? AND attribute=?;" - -/* Delete an object */ -#define SQL_DELETE_OBJECT_VALUES "DELETE FROM data WHERE object=?;" -#define SQL_DELETE_OBJECT_RIGHTS "DELETE FROM rights WHERE provider=?;" -#define SQL_DELETE_OBJECT "DELETE FROM objects WHERE id=?;" - -/* Delete an attribute */ -#define SQL_DELETE_ATTRIBUTE "DELETE FROM attributes WHERE id=?;" -#define SQL_MANDATORY_DELETE_ATTR "DELETE FROM mandatory WHERE attribute=?;" -#define SQL_OPTIONAL_DELETE_ATTR "DELETE FROM optional WHERE attribute=?;" -#define SQL_NAMING_DELETE_ATTR "DELETE FROM naming WHERE attribute=?;" -#define SQL_VALUES_DELETE_ATTR "DELETE FROM data WHERE attribute=?;" - -/* Delete a class */ -#define SQL_GET_SUBCLASSES "SELECT subclass FROM superclasses WHERE superclass=?;" -#define SQL_GET_OBJECTS_BY_CLASS "SELECT id FROM objects WHERE class=?;" -#define SQL_CONTAINMENT_DEL_CLASS "DELETE FROM containment WHERE container=? OR leaf=?;" -#define SQL_MANDATORY_DEL_CLASS "DELETE FROM mandatory WHERE class=?;" -#define SQL_OPTIONAL_DEL_CLASS "DELETE FROM optional WHERE class=?;" -#define SQL_NAMING_DEL_CLASS "DELETE FROM naming WHERE class=?;" -#define SQL_DELETE_CLASS "DELETE FROM classes WHERE id=?;" - - -#define SQL_VERIFY_PASSWORD "SELECT id FROM objects WHERE id=? AND pass=?;" -#define SQL_SET_PASSWORD "UPDATE objects SET pass=? WHERE id=?;" - -/* - We need mdb.h for the types used below, but we have to make sure it is included after - we have defined our own ValueStruct, EnumStruct and Handle types. -*/ -#include - -typedef struct _MDBodbcBaseSchemaAttributes { - unsigned char *name; - unsigned long flags; - unsigned long type; -} MDBodbcBaseSchemaAttributes; - -MDBodbcBaseSchemaAttributes MDBodbcBaseSchemaAttributesList[] = { - { "Aliased Object Name", 69, MDB_ATTR_SYN_DIST_NAME }, - { "Back Link", 268, MDB_ATTR_SYN_DIST_NAME }, - { "CA Private Key", 93, MDB_ATTR_SYN_BINARY }, - { "CA Public Key", 205, MDB_ATTR_SYN_BINARY }, - { "CN", 102, MDB_ATTR_SYN_STRING }, - { "C", 103, MDB_ATTR_SYN_STRING }, - { "Description", 102, MDB_ATTR_SYN_STRING }, - { "Facsimile Telephone Number", 68, MDB_ATTR_SYN_STRING }, - { "Group Membership", 580, MDB_ATTR_SYN_DIST_NAME }, - { "L", 102, MDB_ATTR_SYN_STRING }, - { "Login Disabled", 69, MDB_ATTR_SYN_BOOL }, - { "Member", 68, MDB_ATTR_SYN_DIST_NAME }, - { "EMail Address", 228, MDB_ATTR_SYN_STRING }, - { "Internet EMail Address", 228, MDB_ATTR_SYN_STRING }, - { "departmentNumber", 228, MDB_ATTR_SYN_STRING }, - { "Notify", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Operator", 324, MDB_ATTR_SYN_DIST_NAME }, - { "OU", 102, MDB_ATTR_SYN_STRING }, - { "O", 102, MDB_ATTR_SYN_STRING }, - { "Owner", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Page Description Language", 102, MDB_ATTR_SYN_STRING }, - { "Path", 68, MDB_ATTR_SYN_STRING }, - { "Physical Delivery Office Name", 102, MDB_ATTR_SYN_STRING }, - { "Postal Address", 68, MDB_ATTR_SYN_STRING }, - { "Postal Code", 102, MDB_ATTR_SYN_STRING }, - { "Postal Office Box", 102, MDB_ATTR_SYN_STRING }, - { "Private Key", 93, MDB_ATTR_SYN_BINARY }, - { "Profile", 69, MDB_ATTR_SYN_DIST_NAME }, - { "Public Key", 205, MDB_ATTR_SYN_BINARY }, - { "Reference", 1052, MDB_ATTR_SYN_DIST_NAME }, - { "Resource", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Role Occupant", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Higher Privileges", 836, MDB_ATTR_SYN_DIST_NAME }, - { "Security Equals", 836, MDB_ATTR_SYN_DIST_NAME }, - { "See Also", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Serial Number", 102, MDB_ATTR_SYN_STRING }, - { "Server", 324, MDB_ATTR_SYN_DIST_NAME }, - { "S", 102, MDB_ATTR_SYN_STRING }, - { "Status", 197, MDB_ATTR_SYN_STRING }, - { "SA", 102, MDB_ATTR_SYN_STRING }, - { "Surname", 230, MDB_ATTR_SYN_STRING }, - { "Telephone Number", 100, MDB_ATTR_SYN_STRING }, - { "Title", 102, MDB_ATTR_SYN_STRING }, - { "Unknown", 4, MDB_ATTR_SYN_STRING }, - { "User", 324, MDB_ATTR_SYN_DIST_NAME }, - { "Version", 231, MDB_ATTR_SYN_STRING }, - { "Device", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Language", 69, MDB_ATTR_SYN_STRING }, - { "UID", 69, MDB_ATTR_SYN_STRING }, - { "GID", 69, MDB_ATTR_SYN_STRING }, - { "Unknown Base Class", 39, MDB_ATTR_SYN_STRING }, - { "Authority Revocation", 77, MDB_ATTR_SYN_BINARY }, - { "Certificate Revocation", 77, MDB_ATTR_SYN_BINARY }, - { "Cross Certificate Pair", 68, MDB_ATTR_SYN_BINARY }, - { "Full Name", 102, MDB_ATTR_SYN_STRING }, - { "Certificate Validity Interval", 71, MDB_ATTR_SYN_STRING }, - { "External Synchronizer", 68, MDB_ATTR_SYN_BINARY }, - { "Message Routing Group", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Postmaster", 68, MDB_ATTR_SYN_DIST_NAME }, - { "Mailbox Location", 197, MDB_ATTR_SYN_DIST_NAME }, - { "Mailbox ID", 231, MDB_ATTR_SYN_STRING }, - { "External Name", 69, MDB_ATTR_SYN_BINARY }, - { "Security Flags", 69, MDB_ATTR_SYN_STRING }, - { "Last Referenced Time", 1029, MDB_ATTR_SYN_STRING }, - { "Given Name", 230, MDB_ATTR_SYN_STRING }, - { "Initials", 230, MDB_ATTR_SYN_STRING }, - { "Generational Qualifier", 231, MDB_ATTR_SYN_STRING }, - { "Profile Membership", 580, MDB_ATTR_SYN_DIST_NAME }, - { "Equivalent To Me", 324, MDB_ATTR_SYN_DIST_NAME }, - { "Timezone", 133, MDB_ATTR_SYN_BINARY }, - { "T", 102, MDB_ATTR_SYN_STRING }, - { "Used By", 332, MDB_ATTR_SYN_STRING }, - { "Uses", 332, MDB_ATTR_SYN_STRING }, - { "GUID", 207, MDB_ATTR_SYN_BINARY }, - { "Other GUID", 198, MDB_ATTR_SYN_BINARY }, - { NULL, 0, 0 } -}; - -typedef struct _MDBodbcBaseSchemaClasses { - unsigned char *name; - unsigned long flags; - unsigned char *superClass; - unsigned char *containedBy; - unsigned char *namedBy; - unsigned char *mandatory; - unsigned char *optional; -} MDBodbcBaseSchemaClasses; - -MDBodbcBaseSchemaClasses MDBodbcBaseSchemaClassesList[] = { - { "[Nothing]", 3, NULL, NULL, NULL, NULL, NULL }, - { "Top", 3, NULL, NULL, "T", NULL, "CA Public Key,Private Key,Certificate Validity Interval,Authority Revocation,Last Referenced Time,Equivalent To Me,Back Link,Reference,Cross Certificate Pair,Certificate Revocation,Used By,GUID,Other GUID" }, - { "Alias", 2, "Top", NULL, NULL, "Aliased Object Name", NULL }, - { "Country", 3, "Top", "Top,Tree Root,[Nothing]", "C", "C", "Description" }, - { "Organization", 3, NULL, "Top,Tree Root,Country,Locality,[Nothing]", "O", "O","Description,Facsimile Telephone Number,L,EMail Address,Physical Delivery Office Name,Postal Address,Postal Code,Postal Office Box,See Also,S,SA,Telephone Number" }, - { "Organizational Unit", 3, NULL, "Locality,Organization,Organizational Unit", "OU", "OU","Description,Facsimile Telephone Number,L,EMail Address,Physical Delivery Office Name,Postal Address,Postal Code,Postal Office Box,See Also,S,SA,Telephone Number" }, - { "Locality", 3, "Top", "Locality,Country,Organizational Unit,Organization", "L,S", NULL,"Description,L,See Also,S,SA" }, - { "Organizational Role", 2, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,Facsimile Telephone Number,L,EMail Address,OU,Physical Delivery Office Name,Postal Address,Postal Code,Postal Office Box,Role Occupant,See Also,S,SA,Telephone Number,Mailbox Location,Mailbox ID" }, - { "Group", 2, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,L,Member,OU,O,Owner,See Also,GID,Full Name,EMail Address,Mailbox Location,Mailbox ID,Profile,Profile Membership" }, - { "Person", 2, NULL, "Organization,Organizational Unit", "CN", "CN", "Description,See Also,Telephone Number,Full Name,Given Name,Initials,Generational Qualifier" }, - { "Organizational Person", 2, "Person", NULL, "OU", NULL, "Facsimile Telephone Number,L,EMail Address,OU,Physical Delivery Office Name,Postal Address,Postal Code,Postal Office Box,S,SA,Title,Mailbox Location,Mailbox ID" }, - { "User", 2, "Organizational Person", NULL, NULL, NULL, "Group Membership,Login Disabled,Private Key,Profile,Public Key,Security Equals,Minimum Message Server,Language,UID,Type Creator Map,Higher Privileges,Security Flags,Profile Membership,Timezone,Surname,Internet EMail Address,departmentNumber" }, - { "Device", 2, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,L,OU,O,Owner,See Also,Serial Number" }, - { "Computer", 2, "Device", NULL, NULL, NULL, "Operator,Server,Status" }, - { "Resource", 0, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,L,OU,O,See Also,Uses" }, - { "Profile", 2, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,L,OU,O,See Also,Full Name" }, - { "Server", 0, "Top", "Organization,Organizational Unit", "CN", "CN", "Description,L,OU,O,Private Key,Public Key,Resource,See Also,Status,User,Version,Full Name,Security Equals,Security Flags,Timezone" }, - { "NCP Server", 2, "Server", NULL, NULL, NULL, "Operator" }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL } -}; - -#define ERR_NO_SUCH_ENTRY 0xFFFFFDA7 -#define ERR_NO_SUCH_VALUE 0xFFFFFDA6 -#define ERR_NO_SUCH_ATTRIBUTE 0xFFFFFDA5 -#define ERR_NO_SUCH_CLASS 0xFFFFFDA4 -#define ERR_NO_SUCH_PARTITION 0xFFFFFDA3 -#define ERR_ENTRY_ALREADY_EXISTS 0xFFFFFDA2 -#define ERR_NOT_EFFECTIVE_CLASS 0xFFFFFDA1 -#define ERR_ILLEGAL_ATTRIBUTE 0xFFFFFDA0 -#define ERR_MISSING_MANDATORY 0xFFFFFD9F -#define ERR_ILLEGAL_DS_NAME 0xFFFFFD9E -#define ERR_ILLEGAL_CONTAINMENT 0xFFFFFD9D -#define ERR_CANT_HAVE_MULTIPLE_VALUES 0xFFFFFD9C -#define ERR_SYNTAX_VIOLATION 0xFFFFFD9B -#define ERR_DUPLICATE_VALUE 0xFFFFFD9A -#define ERR_ATTRIBUTE_ALREADY_EXISTS 0xFFFFFD99 -#define ERR_MAXIMUM_ENTRIES_EXIST 0xFFFFFD98 -#define ERR_DATABASE_FORMAT 0xFFFFFD97 -#define ERR_INCONSISTENT_DATABASE 0xFFFFFD96 -#define ERR_INVALID_COMPARISON 0xFFFFFD95 -#define ERR_COMPARISON_FAILED 0xFFFFFD94 -#define ERR_TRANSACTIONS_DISABLED 0xFFFFFD93 -#define ERR_INVALID_TRANSPORT 0xFFFFFD92 -#define ERR_SYNTAX_INVALID_IN_NAME 0xFFFFFD91 -#define ERR_TRANSPORT_FAILURE 0xFFFFFD8F -#define ERR_ALL_REFERRALS_FAILED 0xFFFFFD8E -#define ERR_CANT_REMOVE_NAMING_VALUE 0xFFFFFD8D -#define ERR_OBJECT_CLASS_VIOLATION 0xFFFFFD8C -#define ERR_ENTRY_IS_NOT_LEAF 0xFFFFFD8B -#define ERR_DIFFERENT_TREE 0xFFFFFD8A -#define ERR_SYSTEM_FAILURE 0xFFFFFD88 -#define ERR_INVALID_ENTRY_FOR_ROOT 0xFFFFFD87 -#define ERR_NO_REFERRALS 0xFFFFFD86 -#define ERR_REMOTE_FAILURE 0xFFFFFD85 -#define ERR_UNREACHABLE_SERVER 0XFFFFFD84 -#define ERR_NO_CHARACTER_MAPPING 0XFFFFFD82 -#define ERR_INCOMPLETE_AUTHENTICATION 0XFFFFFD81 -#define ERR_INVALID_CERTIFICATE 0xFFFFFD80 -#define ERR_INVALID_REQUEST 0xFFFFFD7F -#define ERR_INVALID_ITERATION 0xFFFFFD7E -#define ERR_SCHEMA_IS_NONREMOVABLE 0xFFFFFD7D -#define ERR_SCHEMA_IS_IN_USE 0xFFFFFD7C -#define ERR_CLASS_ALREADY_EXISTS 0xFFFFFD7B -#define ERR_BAD_NAMING_ATTRIBUTES 0xFFFFFD7A -#define ERR_INSUFFICIENT_STACK 0xFFFFFD78 -#define ERR_INSUFFICIENT_BUFFER 0xFFFFFD77 -#define ERR_AMBIGUOUS_CONTAINMENT 0xFFFFFD76 -#define ERR_AMBIGUOUS_NAMING 0xFFFFFD75 -#define ERR_DUPLICATE_MANDATORY 0xFFFFFD74 -#define ERR_DUPLICATE_OPTIONAL 0xFFFFFD73 -#define ERR_RECORD_IN_USE 0xFFFFFD6C -#define ERR_ENTRY_NOT_CONTAINER 0xFFFFFD64 -#define ERR_FAILED_AUTHENTICATION 0xFFFFFD63 -#define ERR_INVALID_CONTEXT 0xFFFFFD62 -#define ERR_NO_SUCH_PARENT 0xFFFFFD61 -#define ERR_NO_ACCESS 0xFFFFFD60 -#define ERR_INVALID_NAME_SERVICE 0xFFFFFD5E -#define ERR_INVALID_TASK 0xFFFFFD5D -#define ERR_INVALID_CONN_HANDLE 0xFFFFFD5C -#define ERR_INVALID_IDENTITY 0xFFFFFD5B -#define ERR_DUPLICATE_ACL 0xFFFFFD5A -#define ERR_ALIAS_OF_AN_ALIAS 0xFFFFFD57 -#define ERR_INVALID_RDN 0xFFFFFD4E -#define ERR_INCORRECT_BASE_CLASS 0xFFFFFD4C -#define ERR_MISSING_REFERENCE 0xFFFFFD4B -#define ERR_LOST_ENTRY 0xFFFFFD4A -#define ERR_FATAL 0xFFFFFD45 - - - -#endif /* MDBODBCP_H */ diff --git a/src/libs/memmgr/Bongo.rules b/src/libs/memmgr/Bongo.rules index 05b6188..96e4504 100644 --- a/src/libs/memmgr/Bongo.rules +++ b/src/libs/memmgr/Bongo.rules @@ -1,12 +1,12 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongomemmgr.la -libbongomemmgr_la_SOURCES := \ +libbongomemmgr_la_SOURCES = \ src/libs/memmgr/memmgr.c \ src/libs/memmgr/memmgrp.h \ src/libs/memmgr/memstack.c -libbongomemmgr_la_LIBADD := libbongoxpl.la +libbongomemmgr_la_LIBADD = libbongoxpl.la src/libs/memmgr/all: libbongomemmgr.la src/libs/memmgr/clean: clean diff --git a/src/libs/msgapi/Bongo.rules b/src/libs/msgapi/Bongo.rules index b3993a1..23e8e9f 100644 --- a/src/libs/msgapi/Bongo.rules +++ b/src/libs/msgapi/Bongo.rules @@ -1,32 +1,73 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongomsgapi.la -libbongomsgapi_la_SOURCES := \ +libbongomsgapi_la_SOURCES = \ + src/libs/msgapi/cookie.c \ src/libs/msgapi/msgaddr.c \ src/libs/msgapi/msgapi.c \ src/libs/msgapi/msgapip.h \ + src/libs/msgapi/msgauth.c \ src/libs/msgapi/msgcollector.c \ src/libs/msgapi/msgdate.c \ src/libs/msgapi/msghttp.c \ + src/libs/msgapi/plugin-api.h \ + src/libs/msgapi/sqldb.c \ src/libs/msgapi/msghttp.h -libbongomsgapi_la_CPPFLAGS := $(AM_CPPFLAGS) \ - $(LIBCURL_CPPFLAGS) +libbongomsgapi_la_CPPFLAGS = $(AM_CPPFLAGS) \ + $(LIBCURL_CPPFLAGS) \ + $(SQLITE_CFLAGS) -libbongomsgapi_la_LIBADD := \ +libbongomsgapi_la_LIBADD = \ libbongocal.la \ libbongoconnio.la \ libbongoutil.la \ libbongo-json.la \ libbongomemmgr.la \ - libbongomdb.la \ libbongonmap.la \ libbongoxpl.la \ $(LIBCURL_LIBS) \ + $(SQLITE_LIBS) \ $(top_builddir)/import/libical/src/libical/libical-bongo.la \ $(DL_LIBS) -src/libs/msgapi/all: libbongomsgapi.la +# auth backends +authdir = $(libdir)/bongo-auth/ +auth_std_libadd = \ + $(top_builddir)/import/log4c/log4c/libbongolog4c.la \ + libbongomemmgr.la \ + $(PTHREAD_LIBS) \ + $(ALL_LIBS) + +auth_LTLIBRARIES = libauthsqlite3.la + +libauthsqlite3_la_SOURCES = \ + src/libs/msgapi/auth-backends/sqlite.h \ + src/libs/msgapi/auth-backends/sqlite.c + +libauthsqlite3_la_CPPFLAGS = $(AM_CPPFLAGS) $(SQLITE_CFLAGS) + +libauthsqlite3_la_LIBADD = \ + $(SQLITE_LIBS) \ + $(auth_std_libadd) + +if HAVE_LDAP +auth_LTLIBRARIES += libauthldap.la +endif + +libauthldap_la_SOURCES = src/libs/msgapi/auth-backends/ldap.c +libauthldap_la_CPPFLAGS = $(AM_CPPFLAGS) +libauthldap_la_LIBADD = $(LDAP_LIBS) + +if HAVE_ODBC +auth_LTLIBRARIES += libauthodbc.la +endif + +libauthodbc_la_SOURCES = src/libs/msgapi/auth-backends/odbc.c +libauthodbc_la_CPPFLAGS = $(AM_CPPFLAGS) +libauthodbc_la_LIBADD = $(ODBC_LIBS) + +src/libs/msgapi/all: libbongomsgapi.la $(auth_LTLIBRARIES) src/libs/msgapi/clean: clean src/libs/msgapi/install: @cd $(top_builddir) && $(MAKE) $(MFLAGS) lib_LTLIBRARIES=libbongomsgapi.la install-libLTLIBRARIES diff --git a/src/libs/msgapi/auth-backends/README.odbc b/src/libs/msgapi/auth-backends/README.odbc new file mode 100644 index 0000000..0a0e7cf --- /dev/null +++ b/src/libs/msgapi/auth-backends/README.odbc @@ -0,0 +1,30 @@ +### ODBC backend Options in bongo.conf + +# Any query can be overrided in the backend. +# Here are presented the query prototypes used by default. +# ? represents where the values are substituted. + +ODBC_SQL_Find_User = "SELECT count(username) FROM users WHERE username = ?;" +ODBC_SQL_Verify_Password = "SELECT count(username) FROM users WHERE username = ? AND password = ?;" +ODBC_SQL_Add_User = "INSERT INTO users (username) VALUES (?);" +ODBC_SQL_Set_Password = "UPDATE users SET password = ? WHERE username= ?;" + +#the odbc connection string +ODBC_connection=DRIVER=SQLite3;DATABASE=/usr/var/bongo/dbf/users.sqlite + +### other ODBC connection strings #### + +ODBC_connection=DRIVER={PostgreSQL Unicode};SERVER=localhost;PORT=5432;DATABASE=database_name;UID=db_username;PWD=db_user_password; + + +#### Debug of ODBC connections ##### + +a good way to debug odbc work, is to add this to the odbcinst.ini + +[ODBC] +Trace = Yes +TraceFile = /tmp/unixodbc.log +ForceTrace = Yes + + +this log file traces everything on the odbc connection and handles. diff --git a/src/libs/msgapi/auth-backends/ldap.c b/src/libs/msgapi/auth-backends/ldap.c new file mode 100644 index 0000000..f2c2e7f --- /dev/null +++ b/src/libs/msgapi/auth-backends/ldap.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +/* returns 0 on success */ +int +AuthODBC_Init(void) +{ + return -1; +} + +int +AuthLdap_Install(void) +{ + // TODO + return -1; +} + +int +AuthLdap_FindUser(const char *user) +{ + return -1; +} + +int +AuthLdap_VerifyPassword(const char *user, const char *password) +{ + return -1; +} + +/* "Write" functions below */ + +int +AuthLdap_AddUser(const char *user) +{ + return -1; +} + +int +AuthLdap_SetPassword(const char *user, const char *password) +{ + return -1; +} + +int +AuthLdap_InterfaceVersion(void) +{ + return 1; +} + +int +main (int argc, char *argv[]) +{ + printf("This cannot be run directly"); + return (-1); +} diff --git a/src/libs/msgapi/auth-backends/odbc.c b/src/libs/msgapi/auth-backends/odbc.c new file mode 100644 index 0000000..5d6ad29 --- /dev/null +++ b/src/libs/msgapi/auth-backends/odbc.c @@ -0,0 +1,542 @@ +/* Bongo Project licensing applies to this file, see COPYING + */ + + /** \file + * ODBC backend for user authentication + */ + +#include +#include +#include +#include +#include +#define LOGGERNAME "msgauth-odbc-backend" +#include + +#include +#include +#include +#include + +#include +#include + +/** Bongo msgapi compatibility version */ +#define BONGO_AUTH_PLUGIN_VERSION 1 + +/** default connection string prototype */ +#define CONNECTION_STRING_PROTOTYPE "DRIVER={SQLite3};DATABASE=%s;" +#define CONNECTION_STRING_PROTOTYPE_LEN strlen(CONNECTION_STRING_PROTOTYPE) + +/** default connection string lenght */ +#define CONNECTION_STRING_LEN (XPL_MAX_PATH + CONNECTION_STRING_PROTOTYPE_LEN +1) + +/* SQL prototypes */ + +/** Verify User and password sql query prototype */ +#define SQL_STATEMENT_AUTH_USER "SELECT count(username) FROM users WHERE username = ? AND password = ?;" + +/** Find User sql query prototype */ +#define SQL_STATEMENT_FIND_USER "SELECT count(username) FROM users WHERE username = ?;" + +/** Add User sql query prototype */ +#define SQL_STATEMENT_ADD_USER "INSERT INTO users (username) VALUES (?);" + +/** Set User password sql query prototype */ +#define SQL_STATEMENT_SET_PASSWORD "UPDATE users SET password = ? WHERE username= ?;" + +/** Definitions of the Database */ +typedef struct _ODBCAuthDatabase{ + char *connection_string; + char *sql_auth_user; + char *sql_find_user; + char *sql_add_user; + char *sql_set_password; +}ODBCAuthDatabase; + +ODBCAuthDatabase DatabaseDefine; + +/* Auxiliary Function Prototypes */ +void AuthODBC_ReturnErrorMessage(int retcode, const char *Message); +int AuthODBC_GetDbPath(char *path, size_t size); +int AuthODBC_GenerateHash(const char *username, const char *password, char *result, size_t result_len); + +/* backend functions */ +int AuthODBC_Init(void); +int AuthODBC_Install(void); +int AuthODBC_FindUser(const char *user); +int AuthODBC_VerifyPassword(const char *user, const char *password); +int AuthODBC_AddUser(const char *user); +int AuthODBC_SetPassword(const char *user, const char *password); +int AuthODBC_UserList(BongoArray **list); +int AuthODBC_InterfaceVersion(void); + +/** Backend initiation function. + * It reads the configuration and sets the database definitions. + * \return 0 if it has no errors. + */ +int +AuthODBC_Init(void) +{ + char path[XPL_MAX_PATH + 1]; + Log(LOG_DEBUG,"ODBC Auth Plugin: Init backend"); + + /* Build the default connection string */ + AuthODBC_GetDbPath(path, XPL_MAX_PATH + 1); + DatabaseDefine.connection_string=malloc(CONNECTION_STRING_LEN*sizeof(char)); + snprintf(DatabaseDefine.connection_string, CONNECTION_STRING_LEN, CONNECTION_STRING_PROTOTYPE , path); + //DatabaseDefine.connection_string = "DRIVER={PostgreSQL Unicode};SERVER=localhost;DATABASE=bongo;UID=gass;PWD=12345;PORT=5432;"; + + /* Define auth_user sql query */ + DatabaseDefine.sql_auth_user=SQL_STATEMENT_AUTH_USER; + + /* Define find_user sql query */ + DatabaseDefine.sql_find_user=SQL_STATEMENT_FIND_USER; + + /* Define add_user sql query */ + DatabaseDefine.sql_add_user=SQL_STATEMENT_ADD_USER; + + /* Define set_password sql query */ + DatabaseDefine.sql_set_password=SQL_STATEMENT_SET_PASSWORD; + + return 0; +} + + +/* returns 0 on success */ +int +AuthODBC_Install(void) +{ + /* removed all sqlite stuff */ + return 0; +} + +int +AuthODBC_FindUser(const char *user) +{ + SQLHENV env; + SQLHDBC handle; + SQLHSTMT stmt; + SQLSMALLINT users[1]; + SQLLEN users_len[1]; + SQLINTEGER user_buffer; + SQLSMALLINT * OutConnStrLen; + SQLCHAR OutConnectionString[1025]; + int retcode; + + Log(LOG_DEBUG,"ODBC Auth Plugin: Entered Find User"); + + /* Set Environment and Connect */ + Log(LOG_DEBUG, "connection string: %s", DatabaseDefine.connection_string); + /* Set the environment */ + retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3,0); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlAllocHandle ENV"); + + /* connection */ + retcode = SQLAllocHandle(SQL_HANDLE_DBC, env, &handle); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlAllocHandle ODBC HANDLE"); + + /* Connect to the database */ + retcode = SQLDriverConnect(handle, NULL,DatabaseDefine.connection_string, + SQL_NTS, OutConnectionString, 1024, OutConnStrLen, + SQL_DRIVER_COMPLETE); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - ODBC Connection"); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC environment"); + return 2; + } + + /* Prepare SQL Query */ + retcode = SQLAllocHandle(SQL_HANDLE_STMT, handle, &stmt); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlAllocHandle stmt"); + + Log(LOG_DEBUG, "Find_User - SQL statement: %s", DatabaseDefine.sql_find_user); + retcode = SQLPrepare (stmt, (SQLCHAR*) DatabaseDefine.sql_find_user, SQL_NTS); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - Sql Query preparation"); + + user_buffer=SQL_NTS; + retcode = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 100, 0, + (SQLPOINTER) user,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlBindParameter user"); + + users_len[0]=1; + retcode = SQLBindCol(stmt, 1, SQL_C_SSHORT, users, 1, users_len); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlBindCol user"); + + /* Query the Database */ + retcode = SQLExecute(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlExecute"); + retcode = SQLFetch(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - SqlFetch"); + SQLCancel(stmt); + + /* Closing and freeing */ + retcode = SQLFreeHandle(SQL_HANDLE_STMT, stmt); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - Free ODBC stmt"); + retcode = SQLDisconnect(handle); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - ODBC Disconnect"); + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Find_User - Free ODBC environment"); + + /* Processing OutPut */ + if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)) { + return 2; + } + Log(LOG_DEBUG, "Find_User - Number of users %d", users[0]); + // one and only one user - any other condition is 'bad'... + if (users[0] == 1) { + return 0; // user exists / password verified + } + if (users[0] == 0) { + Log(LOG_ERROR, "Find_User - User not in db", user); + return 1; // no such user or password wrong, not an error + } + + Log(LOG_ERROR, "Find_User - User %s exists multiple times in the user db", user); + return 3; +} + +int +AuthODBC_VerifyPassword(const char *user, const char *password) +{ + SQLHENV env; + SQLHDBC handle; + SQLHSTMT stmt; + SQLSMALLINT users[1]; + SQLLEN users_len[1]; + SQLINTEGER user_buffer; + char hash[XPLHASH_SHA1_LENGTH + 1]; + SQLSMALLINT * OutConnStrLen; + SQLCHAR OutConnectionString[1025]; + int retcode; + + Log(LOG_DEBUG,"ODBC Auth Plugin: Verify Password"); + + if (AuthODBC_GenerateHash(user, password, hash, XPLHASH_SHA1_LENGTH + 1) != 0) + return 1; + + /* Set Environment and Connect */ + Log(LOG_DEBUG, "Verify_password - connection string: %s", DatabaseDefine.connection_string); + /* Set the environment */ + retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3,0); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlAllocHandle ENV"); + + /* connection */ + retcode = SQLAllocHandle(SQL_HANDLE_DBC, env, &handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlAllocHandle ODBC HANDLE"); + + /* Connect to the database */ + retcode = SQLDriverConnect(handle, NULL,DatabaseDefine.connection_string, + SQL_NTS, OutConnectionString, 1024, OutConnStrLen, + SQL_DRIVER_COMPLETE); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - ODBC Connection"); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC environment"); + return 2; + } + + /* Prepare SQL Query */ + retcode = SQLAllocHandle(SQL_HANDLE_STMT, handle, &stmt); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlAllocHandle stmt"); + + Log(LOG_DEBUG, "Verify_password - SQL statement: %s", DatabaseDefine.sql_auth_user); + retcode = SQLPrepare (stmt, (SQLCHAR*) DatabaseDefine.sql_auth_user, SQL_NTS); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Sql Query preparation"); + + user_buffer=SQL_NTS; + retcode = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 100, 0, + (SQLPOINTER) user,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlBindParameter user"); + + user_buffer = SQL_NTS; + retcode = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, + XPLHASH_SHA1_LENGTH, 0, (SQLPOINTER) hash,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlBindParameter hash"); + + users_len[0]=1; + retcode = SQLBindCol(stmt, 1, SQL_C_SSHORT, users, 1, users_len); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlBindCol user"); + + /* Query the Database */ + retcode = SQLExecute(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlExecute"); + retcode = SQLFetch(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - SqlFetch"); + SQLCancel(stmt); + + /* Closing and freeing */ + retcode = SQLFreeHandle(SQL_HANDLE_STMT, stmt); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC stmt"); + retcode = SQLDisconnect(handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - ODBC Disconnect"); + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC environment"); + + /* Processing OutPut */ + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){ + return 2; + } + + Log(LOG_DEBUG, "Verify_Password - Number of users %d", users[0]); + // one and only one user - any other condition is 'bad'... + if (users[0] == 1) { + return 0; // user exists / password verified + } + if (users[0] == 0) { + Log(LOG_ERROR, "User not in db", user); + return 1; // no such user or password wrong, not an error + } + + Log(LOG_ERROR, "User %s exists multiple times in the user db", user); + return 3; +} + +/* "Write" functions below */ + +int +AuthODBC_AddUser(const char *user) +{ + SQLHENV env; + SQLHDBC handle; + SQLHSTMT stmt; + SQLINTEGER user_buffer; + SQLSMALLINT * OutConnStrLen; + SQLCHAR OutConnectionString[1025]; + int retcode; + + Log(LOG_DEBUG,"ODBC Auth Plugin: Entered Add User"); + + /* Set Environment and Connect */ + Log(LOG_DEBUG, "Add_User - connection string: %s", DatabaseDefine.connection_string); + /* Set the environment */ + retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3,0); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - SqlAllocHandle ENV"); + + /* connection */ + retcode = SQLAllocHandle(SQL_HANDLE_DBC, env, &handle); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - SqlAllocHandle ODBC HANDLE"); + + /* Connect to the database */ + retcode = SQLDriverConnect(handle, NULL,DatabaseDefine.connection_string, + SQL_NTS, OutConnectionString, 1024, OutConnStrLen, + SQL_DRIVER_COMPLETE); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - ODBC Connection"); + + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC environment"); + return 2; + } + + /* Prepare SQL Query */ + retcode = SQLAllocHandle(SQL_HANDLE_STMT, handle, &stmt); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - SqlAllocHandle stmt"); + + + retcode = SQLPrepare (stmt, (SQLCHAR*) DatabaseDefine.sql_add_user, SQL_NTS); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - Sql Query preparation"); + + user_buffer=SQL_NTS; + retcode = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 100, 0, + (SQLPOINTER) user,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - SqlBindParameter user"); + + /* Query the Database */ + retcode = SQLExecute(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - SqlExecute"); + + SQLCancel(stmt); + + /* Closing and freeing */ + retcode = SQLFreeHandle(SQL_HANDLE_STMT, stmt); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - Free ODBC stmt"); + retcode = SQLDisconnect(handle); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - ODBC Disconnect"); + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Add_User - Free ODBC environment"); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){ + return 2; + } + + return 0; +} + +int +AuthODBC_SetPassword(const char *user, const char *password) +{ + SQLHENV env; + SQLHDBC handle; + SQLHSTMT stmt; + SQLINTEGER user_buffer; + char hash[XPLHASH_SHA1_LENGTH + 1]; + SQLSMALLINT * OutConnStrLen; + SQLCHAR OutConnectionString[1025]; + int retcode; + + Log(LOG_DEBUG,"ODBC Auth Plugin: Entered Set Password"); + + if (AuthODBC_GenerateHash(user, password, hash, XPLHASH_SHA1_LENGTH + 1) != 0) + return 1; + + /* Set Environment and Connect */ + Log(LOG_DEBUG, "Set_Password - connection string: %s", DatabaseDefine.connection_string); + /* Set the environment */ + retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3,0); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlAllocHandle ENV"); + + /* connection */ + retcode = SQLAllocHandle(SQL_HANDLE_DBC, env, &handle); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlAllocHandle ODBC HANDLE"); + + /* Connect to the database */ + retcode = SQLDriverConnect(handle, NULL,DatabaseDefine.connection_string, + SQL_NTS, OutConnectionString, 1024, OutConnStrLen, + SQL_DRIVER_COMPLETE); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - ODBC Connection"); + + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Verify_password - Free ODBC environment"); + return 2; + } + + /* Prepare SQL Query */ + retcode = SQLAllocHandle(SQL_HANDLE_STMT, handle, &stmt); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlAllocHandle stmt"); + + retcode = SQLPrepare (stmt, (SQLCHAR*) DatabaseDefine.sql_set_password, SQL_NTS); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - Sql Query preparation"); + + user_buffer=SQL_NTS; + retcode = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 100, 0, + (SQLPOINTER) user,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlBindParameter user"); + + user_buffer = SQL_NTS; + retcode = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, + XPLHASH_SHA1_LENGTH, 0, (SQLPOINTER) &hash,0, &user_buffer); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlBindParameter hash"); + + /* Query the Database */ + retcode = SQLExecute(stmt); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - SqlExecute"); + SQLCancel(stmt); + + /* Closing and freeing */ + + retcode = SQLFreeHandle(SQL_HANDLE_STMT, stmt); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - Free ODBC stmt"); + retcode = SQLDisconnect(handle); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - ODBC Disconnect"); + retcode = SQLFreeHandle(SQL_HANDLE_DBC, handle); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - Free ODBC handle"); + retcode = SQLFreeHandle(SQL_HANDLE_ENV, env); + AuthODBC_ReturnErrorMessage(retcode, "Set_Password - Free ODBC environment"); + + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { + return 2; + } + return 0; +} + +int +AuthODBC_UserList(BongoArray **list) +{ + /* TODO + BongoArray *userlist; + + userlist = BongoArrayNew(sizeof (char *), 0); + + char *admin = strdup("admin"); + BongoArrayAppendValue(userlist, admin); + + *list = userlist; + */ + return TRUE; +} + +int +AuthODBC_InterfaceVersion(void) +{ + return BONGO_AUTH_PLUGIN_VERSION; +} + +/** Logs the error corresponding to the submitted error code. + * \param retcode error code from the odbc function. + * \param Message message shown before the error message. + * example: "Connection status" for the log "Connection status: SQL_SUCCESS. + */ +void +AuthODBC_ReturnErrorMessage(int retcode, const char *Message) +{ + switch (retcode) + { + case SQL_SUCCESS: + Log(LOG_DEBUG,"%s: SQL_SUCCESS", Message); + break; + case SQL_SUCCESS_WITH_INFO: + Log(LOG_DEBUG,"%s: SQL_SUCCESS_WITH_INFO", Message); + break; + case SQL_NO_DATA: + Log(LOG_ERROR,"%s: SQL_NO_DATA", Message); + break; + case SQL_ERROR: + Log(LOG_ERROR,"%s: SQL_ERROR", Message); + break; + case SQL_INVALID_HANDLE: + Log(LOG_ERROR,"%s: SQL_INVALID_HANDLE", Message); + break; + default: + return; + } +} +int +AuthODBC_GetDbPath(char *path, size_t size) +{ + return snprintf(path, size, "%s/%s", XPL_DEFAULT_DBF_DIR, "userdb.sqlite"); +} + +int +AuthODBC_GenerateHash(const char *username, const char *password, char *result, size_t result_len) +{ + xpl_hash_context ctx; + + if (result_len <= XPLHASH_SHA1_LENGTH) return -1; + + XplHashNew(&ctx, XPLHASH_SHA1); + XplHashWrite(&ctx, username, strlen(username)); + XplHashWrite(&ctx, password, strlen(password)); + XplHashFinal(&ctx, XPLHASH_UPPERCASE, result, XPLHASH_SHA1_LENGTH); + + result[XPLHASH_SHA1_LENGTH] = '\0'; + return 0; +} +int +main (int argc, char *argv[]) +{ + printf ("############ Bongo Project ############\n"); + printf (" Bongo MsgApiAuth plugin \n"); + printf (" ODBC Support Plugin \n"); + printf (" Compatibility Version: %d \n", BONGO_AUTH_PLUGIN_VERSION); + return 0; +} diff --git a/src/libs/msgapi/auth-backends/sqlite.c b/src/libs/msgapi/auth-backends/sqlite.c new file mode 100644 index 0000000..8a08b04 --- /dev/null +++ b/src/libs/msgapi/auth-backends/sqlite.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include +#include +#define LOGGERNAME "msgauth" +#include + +#include +#include +#include +#include + +#include "sqlite.h" + +typedef struct { + MsgSQLStatement find_user; + MsgSQLStatement auth_user; + MsgSQLStatement add_user; + MsgSQLStatement set_password; +} MsgAuthStatements; + +MsgAuthStatements msgauth_stmts; + +int +AuthODBC_Init(void) +{ + return 0; +} + +int +AuthSqlite_GetDbPath(char *path, size_t size) +{ + return snprintf(path, size, "%s/%s", XPL_DEFAULT_DBF_DIR, "userdb.sqlite"); +} + +int +AuthSqlite_GenerateHash(const char *username, const char *password, char *result, size_t result_len) +{ + xpl_hash_context ctx; + + if (result_len <= XPLHASH_SHA1_LENGTH) return -1; + + XplHashNew(&ctx, XPLHASH_SHA1); + XplHashWrite(&ctx, username, strlen(username)); + XplHashWrite(&ctx, password, strlen(password)); + XplHashFinal(&ctx, XPLHASH_UPPERCASE, result, XPLHASH_SHA1_LENGTH); + + result[XPLHASH_SHA1_LENGTH] = '\0'; + return 0; +} + +/* returns 0 on success */ +int +AuthSqlite_Install(void) +{ + int dcode; + char path[XPL_MAX_PATH + 1]; + MsgSQLHandle *handle; + struct stat buf; + + AuthSqlite_GetDbPath(path, XPL_MAX_PATH); + if (stat(path, &buf) == 0) { + // FIXME: db already exists - for now, remove, but could/should be more gentle + unlink(path); + } + + handle = MsgSQLOpen(path, NULL, 1000); + + if (NULL == handle) return -2; + + if (MsgSQLBeginTransaction(handle)) goto fail; + + dcode = sqlite3_exec (handle->db, + "PRAGMA user_version=0;" + "CREATE TABLE users (username TEXT DEFAULT NULL," + " password TEXT DEFAULT NULL" + ");" + "INSERT INTO users (username, password)" + " VALUES ('admin', '19E210D6CDA11A1CDED7D3B35E129514FB896B43'); ", + NULL, NULL, NULL); + if (SQLITE_OK != dcode) goto fail; + + if (MsgSQLCommitTransaction(handle)) goto fail; + + MsgSQLClose(handle); + return 0; + +fail: + Log(LOG_ERROR, "Error creating database: %s", sqlite3_errmsg(handle->db)); + + MsgSQLAbortTransaction(handle); + MsgSQLClose(handle); + return -1; +} + +int +AuthSqlite_FindUser(const char *user) +{ + MsgSQLStatement *stmt; + char path[XPL_MAX_PATH + 1]; + MsgSQLHandle *handle; + int users = -1; + + AuthSqlite_GetDbPath(path, XPL_MAX_PATH); + handle = MsgSQLOpen(path, NULL, 1000); + + // Log error? + if (NULL == handle) { + Log(LOG_ERROR, "Cannot open user db '%s'", path); + return 1; + } + + stmt = MsgSQLPrepare (handle, "SELECT count(username) FROM users WHERE username = ?;", + &msgauth_stmts.find_user); + if (NULL == stmt) { + Log(LOG_ERROR, "Unable to prepare SQL statement in FindUser"); + return 1; + } + MsgSQLBindString(stmt, 1, user, TRUE); + + if (MsgSQLResults(handle, stmt) >= 0) { + // should only have one result column + users = sqlite3_column_int(stmt->stmt, 0); + } + + MsgSQLFinalize(stmt); + MsgSQLClose(handle); + + if (users == 1) { + // found the user + return 0; + } + + LogAssertF(users == 0, "User %s defined more than once in the user db", user); + + return 1; +} + +int +AuthSqlite_VerifyPassword(const char *user, const char *password) +{ + MsgSQLStatement *stmt; + char path[XPL_MAX_PATH + 1]; + char hash[XPLHASH_SHA1_LENGTH + 1]; + MsgSQLHandle *handle; + int users = -1; + + if (AuthSqlite_GenerateHash(user, password, hash, XPLHASH_SHA1_LENGTH + 1) != 0) + return 1; + + AuthSqlite_GetDbPath(path, XPL_MAX_PATH); + handle = MsgSQLOpen(path, NULL, 1000); + + // Log error? + if (NULL == handle) { + Log(LOG_ERROR, "Cannot open user db '%s'", path); + return 2; + } + + stmt = MsgSQLPrepare (handle, "SELECT count(username) FROM users WHERE username = ? AND password = ?;", + &msgauth_stmts.auth_user); + if (NULL == stmt) { + Log(LOG_ERROR, "Unable to prepare SQL statement in VerifyPassword"); + return 1; + } + MsgSQLBindString(stmt, 1, user, TRUE); + MsgSQLBindString(stmt, 2, hash, TRUE); + + if (MsgSQLResults(handle, stmt) >= 0) { + // should only have one result column + users = sqlite3_column_int(stmt->stmt, 0); + } + + MsgSQLFinalize(stmt); + MsgSQLClose(handle); + + if (users == 1) { + return 0; // user exists / password verified + } + if (users == 0) { + return 1; // no such user or password wrong, not an error + } + + Log(LOG_ERROR, "User %s exists multiple times in the user db", user); + return 3; +} + +/* "Write" functions below */ + +int +AuthSqlite_AddUser(const char *user) +{ + MsgSQLStatement *stmt; + char path[XPL_MAX_PATH + 1]; + MsgSQLHandle *handle; + + AuthSqlite_GetDbPath(path, XPL_MAX_PATH); + handle = MsgSQLOpen(path, NULL, 1000); + if (NULL == handle) { + Log(LOG_ERROR, "Cannot open user db '%s'", path); + return -1; + } + + stmt = MsgSQLPrepare (handle, + "INSERT INTO users (username) VALUES (?);", + &msgauth_stmts.add_user); + + if (NULL == stmt) { + Log(LOG_ERROR, "Unable to prepare SQL statement in AddUser"); + return 1; + } + + if (MsgSQLBindString(stmt, 1, user, TRUE)) return -2; + if (MsgSQLExecute(handle, stmt)) return -3; + + MsgSQLFinalize(stmt); + MsgSQLClose(handle); + + return 0; +} + +int +AuthSqlite_SetPassword(const char *user, const char *password) +{ + MsgSQLStatement *stmt; + char path[XPL_MAX_PATH + 1]; + char hash[XPLHASH_SHA1_LENGTH + 1]; + MsgSQLHandle *handle; + + if (AuthSqlite_GenerateHash(user, password, hash, XPLHASH_SHA1_LENGTH + 1) != 0) + return -1; + AuthSqlite_GetDbPath(path, XPL_MAX_PATH); + handle = MsgSQLOpen(path, NULL, 1000); + if (NULL == handle) { + Log(LOG_ERROR, "Cannot open user db '%s'", path); + return -2; + } + + stmt = MsgSQLPrepare (handle, + "UPDATE users SET password = ? WHERE username= ?;", + &msgauth_stmts.set_password); + if (NULL == stmt) { + Log(LOG_ERROR, "Unable to prepare SQL in SetPassword()"); + return 1; + } + + if (MsgSQLBindString(stmt, 1, hash, TRUE)) return -3; + if (MsgSQLBindString(stmt, 2, user, TRUE)) return -3; + if (MsgSQLExecute(handle, stmt)) return -3; + + MsgSQLFinalize(stmt); + MsgSQLClose(handle); + + return 0; +} + +int +AuthSqlite_GetUserStore(const char *user, struct sockaddr_in *store) +{ + memset(store, 0, sizeof(store)); + store->sin_addr.s_addr = inet_addr("127.0.0.1"); + store->sin_family = AF_INET; + store->sin_port = htons(689); + return TRUE; +} + +int +AuthSqlite_UserList(BongoArray **list) +{ + /* TODO + BongoArray *userlist; + + userlist = BongoArrayNew(sizeof (char *), 0); + + char *admin = strdup("admin"); + BongoArrayAppendValue(userlist, admin); + + *list = userlist; + */ + return TRUE; +} + +int +AuthSqlite_InterfaceVersion(void) +{ + return 1; +} + +int +main (int argc, char *argv[]) +{ + printf("This cannot be run directly"); + return (-1); +} diff --git a/src/libs/msgapi/auth-backends/sqlite.h b/src/libs/msgapi/auth-backends/sqlite.h new file mode 100644 index 0000000..53aef21 --- /dev/null +++ b/src/libs/msgapi/auth-backends/sqlite.h @@ -0,0 +1,12 @@ + +int AuthSqlite_GetDbPath(char *path, size_t size); +int AuthSqlite_GenerateHash(const char *username, const char *password, char *result, size_t result_len); +int AuthSqlite_Install(void); +int AuthSqlite_FindUser(const char *user); +int AuthSqlite_VerifyPassword(const char *user, const char *password); +int AuthSqlite_AddUser(const char *user); +int AuthSqlite_SetPassword(const char *user, const char *password); +int AuthSqlite_GetUserStore(const char *user, struct sockaddr_in *store); +int AuthSqlite_UserList(BongoArray **list); +int AuthSqlite_InterfaceVersion(void); +int AuthODBC_Init(void); diff --git a/src/libs/msgapi/cookie.c b/src/libs/msgapi/cookie.c new file mode 100644 index 0000000..b18b760 --- /dev/null +++ b/src/libs/msgapi/cookie.c @@ -0,0 +1,188 @@ +/* Bongo Project licensing applies to this file, see COPYING + * (C) 2007 Alex Hudson + */ + +/** \file + * Single cookie implementation for all agents; this ensures any cookie + * is valid with any agent which recognises them. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Internal function: path to the cookie file for this user. +void +MsgAuthCookiePath(const char *username, char *path, size_t length) +{ + snprintf(path, length, "%s/%s", + MsgGetDir(MSGAPI_DIR_COOKIE, path, XPL_MAX_PATH), + username); +} + +/** + * Create a 'cookie': a password-substitute token, and an associated expiry + * SECURITY: We shouldn't create cookies for non-authenticated users + * \param user User whose token this will be + * \param cookie Reference to the MsgAuthCookie we're creating + * \param timeout When the token should expire + * \return Whether or not the cookie was created + */ +EXPORT BOOL +MsgAuthCreateCookie(const char *username, MsgAuthCookie *cookie, uint64_t timeout) +{ + char path[XPL_MAX_PATH+1]; + FILE *cookiefile = NULL; + long original_length; + size_t written; + xpl_hash_context context; + + // create the cookie + cookie->expiration = timeout; + + XplHashNew(&context, XPLHASH_MD5); + snprintf(cookie->token, sizeof(cookie->token), "%x%x", + (unsigned int) XplGetThreadID(), + (unsigned int) time(NULL)); + XplHashWrite(&context, cookie->token, strlen(cookie->token)); + XplRandomData(cookie->token, 8); + XplHashWrite(&context, cookie->token, strlen(cookie->token)); + XplHashFinal(&context, XPLHASH_LOWERCASE, cookie->token, XPLHASH_MD5_LENGTH); + + // save it to our cookie list + MsgAuthCookiePath(username, path, XPL_MAX_PATH); + cookiefile = fopen(path, "a"); + if (! cookiefile) + return FALSE; + + original_length = ftell(cookiefile); + + written = fwrite(cookie, 1, sizeof(MsgAuthCookie), cookiefile); + if ((fclose(cookiefile) != 0) || (sizeof(MsgAuthCookie) != written)) { + truncate(path, original_length); + return FALSE; + } + + return TRUE; +} + +/** + * Find a cookie based on the token. If it exists, it's as good as auth'ing + * SECURITY: This is much like authentication. Be careful to timeout on bad auth? + * \param username User who claims this token is theirs + * \param token Token we want to look for + * \return 0 = bad auth, 1 = good auth, 2 = internal error + */ +EXPORT int +MsgAuthFindCookie(const char *username, const char *token) +{ + char path[XPL_MAX_PATH+1]; + FILE *cookiefile = NULL; + MsgAuthCookie cookie; + int result = 0; + BOOL expired_tokens = FALSE; + uint64_t now; + + now = time(NULL); + + MsgAuthCookiePath(username, path, XPL_MAX_PATH); + + cookiefile = fopen(path, "r"); + if (! cookiefile) return 2; + + while (fread(&cookie, 1, sizeof(MsgAuthCookie), cookiefile) == sizeof(MsgAuthCookie)) { + if (cookie.expiration < now) { + expired_tokens = TRUE; + continue; + } + if (!strncmp (cookie.token, token, MSGAUTH_COOKIE_LEN)) { + result = 1; + break; + } + } + + if (ferror(cookiefile)) + result = 2; + + fclose(cookiefile); + + if (expired_tokens) + // call this function with no token to remove expired tokens + MsgAuthDeleteCookie(username, ""); + + return result; +} + +/** + * Remove a token from the user's cookie store. Removes expired tokens as a side-effect. + * \param username User whose token this should be + * \param token Token we want rid of. + * \return Whether or not we succeeded. + */ +EXPORT BOOL +MsgAuthDeleteCookie(const char *username, const char *token) +{ + char path[XPL_MAX_PATH + 1]; + FILE *cookiefile = NULL; + long filelen; + int cookiecount, i; + MsgAuthCookie **cookieset; + uint64_t now; + + now = time(NULL); + + MsgAuthCookiePath(username, path, XPL_MAX_PATH); + + // first, read cookies into memory + cookiefile = fopen(path, "w"); + if (! cookiefile) return FALSE; + + if (fseek(cookiefile, 0, SEEK_END) != 0) { + fclose(cookiefile); + return FALSE; + } + + filelen = ftell(cookiefile); + cookiecount = filelen / sizeof(MsgAuthCookie); + cookieset = MemMalloc(filelen + 1); + if (fread(cookieset, 1, filelen, cookiefile) != filelen) { + fclose(cookiefile); + return FALSE; + } + + // next, clear the existing file + rewind(cookiefile); + ftruncate((int)cookiefile, 0); + + // now, go through memory writing out only the cookies we want to keep + for (i = 0; i < cookiecount; i++) { + MsgAuthCookie *cookie = cookieset[i]; + if (! strncmp(cookie->token, token, MSGAUTH_COOKIE_LEN)) { + // we want to delete this token + cookie->expiration = 0; + } + if (cookie->expiration < now) { + // this token is expired, so we don't want this. + cookie->expiration = 0; + } + if (cookie->expiration != 0) { + // we want to keep this token, so write it out + size_t written; + written = fwrite(cookie, 1, sizeof(MsgAuthCookie), cookiefile); + if (written != sizeof(MsgAuthCookie)) { + // ooops, this is pretty bad... + fclose(cookiefile); + return FALSE; + } + } + } + + fclose(cookiefile); + return TRUE; +} diff --git a/src/libs/msgapi/msgaddr.c b/src/libs/msgapi/msgaddr.c index 455d0c3..3ef02cb 100644 --- a/src/libs/msgapi/msgaddr.c +++ b/src/libs/msgapi/msgaddr.c @@ -17,8 +17,8 @@ * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * + * (C) 2007 Patrick Felt ****************************************************************************/ - #include #include #include @@ -398,6 +398,23 @@ MsgIsComment(unsigned char *base, unsigned char *limit, unsigned char **out) return(FALSE); } +EXPORT BOOL +MsgParseAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char **local_part, unsigned char **domain ) { + /*TODO: this is a terribly simple parser of an email address into the local_part and the domain. this needs to be better */ + unsigned char *at = strchr(addressLine, '@'); + if (at) { + *at = '\0'; + (*local_part)= MemStrdup(addressLine); + (*domain) = MemStrdup(at+1); + *at = '@'; + return TRUE; + } + (*local_part) = MemStrdup(addressLine); + (*domain) = NULL; + return TRUE; +} +#if 0 +TODO: this is going to get replaced later with something better!! /* RFC 2822 - 3.4.1 Addr-spec specification * addr-spec = local-part"@"domain * local-part = dot-atom / quoted-string / obs-local-part @@ -413,15 +430,16 @@ MsgIsComment(unsigned char *base, unsigned char *limit, unsigned char **out) * FWS = ([*WSP CRLF] 1*WSP) / obs-FWS * CFWS = *([FWS] comment) (([FWS] comment) / FWS) */ EXPORT BOOL -MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char *delimiters, unsigned char **out) +MsgParseAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char *delimiters, unsigned char **local_part, unsigned char **domain ) { unsigned char *ptr; unsigned char *ptrLimit; + unsigned char *p_local_part = *local_part; + unsigned char *p_domain = *domain; ptr = addressLine; ptrLimit = addressLine + MAXEMAILNAMESIZE; -#if defined(PROCESS_CFWS) /* Validation step: Handle [CFWS] */ if (MSG_IS_WSP(ptr[0])) { if (MSG_IS_CRLF(++ptr)) { @@ -430,10 +448,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } @@ -444,15 +458,17 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MsgIsComment(ptr, ptrLimit, &ptr)) { ; } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } -#endif +#ifndef PROCESS_ADL + if (ptr[0] == '@') { + /* this is an adl address. right now we want to skip this, but we don't just want to drop the code in case we need it later. + rfc 2821 specifically states that we should accept but ignore the adl formatted address. */ + return (FALSE); + } +#else /* Address could posibly have an A-d-l defined in RFC2821 */ if (ptr[0] != '@') { ; @@ -478,10 +494,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char goto HandleADL; } - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } else if (ptr[0] == '[') { @@ -507,33 +519,37 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char ptr++; break; } - - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } +#endif /* process adl */ /* Validation step: Handle 1*atext*("."1*atext) Validation step: Handle DQUOTE */ if (MSG_IS_ATEXT(ptr[0])) { /* Specification: dot-atom-text Validation step: Handle dot-atom-text */ + if (local_part) { + *p_local_part = *ptr; + p_local_part++; + } while (++ptr < ptrLimit) { if (MSG_IS_ATEXT(ptr[0])) { /* Specification: 1*atext */ + if (local_part) { + *p_local_part = *ptr; + p_local_part++; + } continue; } else if (ptr[0] == '.') { /* Specification: ("."1*atext) */ + if (local_part) { + *p_local_part = *ptr; + p_local_part++; + } continue; } else if ((ptr[0] == ';') && (XplStrNCaseCmp(addressLine, "rfc822;", 7) == 0) && ((ptr - addressLine) == 6)) { /* RFC 1891 - Additional parameters for RCPT and MAIL commands @@ -544,23 +560,14 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char ptr++; if (MsgIsXText(ptr, ptrLimit, &ptr)) { - if (out != NULL) { - *out = ptr; - } return(TRUE); } - - if (out != NULL) { - *out = ptr; - } - return(FALSE); } break; } } else if (ptr[0] == '"') { -#if defined(PROCESS_FWS) /* Specification: *([FWS]qcontent)[FWS]DQUOTE Validation step: Handle [FWS] */ if (MSG_IS_WSP(ptr[0])) { @@ -570,15 +577,10 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } } -#endif /* Validation step: Handle qtext Handle quoted-pair @@ -590,7 +592,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char } else if ((ptr[0] == '\\') && (MSG_IS_TEXT(ptr[1]))) { ptr++; continue; -#if defined(PROCESS_FWS) } else if (MSG_IS_WSP(ptr[0])) { if (MSG_IS_CRLF(++ptr)) { ptr +=2; @@ -599,34 +600,20 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char continue; } - if (out != NULL) { - *out = ptr; - } - return(FALSE); } -#endif } else if (ptr[0] == '"') { ptr++; break; } - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } if (ptr < ptrLimit) { -#if defined(PROCESS_CFWS) /* Specification: [CFWS] Validation step: Handle [CFWS] Handle [FWS] */ @@ -637,10 +624,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } @@ -651,14 +634,9 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MsgIsComment(ptr, ptrLimit, &ptr)) { ; } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } -#endif if (ptr[0] == '@') { /* RFC 2822 - 3.4.1 Addr-spec specification @@ -677,7 +655,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char Validation step: Handle [CFWS] */ ptr++; -#if defined(PROCESS_CFWS) /* Specification: [CFWS] Validation step: Handle [CFWS] Handle [FWS] */ @@ -688,10 +665,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } @@ -702,24 +675,32 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MsgIsComment(ptr, ptrLimit, &ptr)) { ; } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } -#endif if (MSG_IS_ATEXT(ptr[0])) { /* Specification: dot-atom-text Validation step: Handle dot-atom-text */ + if (domain) { + *p_domain = *ptr; + p_domain++; + } + while (++ptr < ptrLimit) { if (MSG_IS_ATEXT(ptr[0])) { /* Specification: 1*atext */ + if (domain) { + *p_domain = *ptr; + p_domain++; + } continue; } else if (ptr[0] == '.') { /* Specification: ("."1*atext) */ + if (domain) { + *p_domain = *ptr; + p_domain++; + } continue; } @@ -728,7 +709,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char } else if (ptr[0] == '[') { ptr++; -#if defined(PROCESS_FWS) /* Specification: *([FWS]dcontent)[FWS]"]" Validation step: Handle [FWS] */ if (MSG_IS_WSP(ptr[0])) { @@ -738,20 +718,20 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } } -#endif /* Validation step: Handle dtext Handle quoted-pair */ while (ptr < ptrLimit) { if (MSG_IS_DTEXT(ptr[0])) { + if (domain) { + *p_domain = *ptr; + p_domain++; + } + ptr++; continue; } else if ((ptr[0] == '\\') && (MSG_IS_TEXT(ptr[1]))) { @@ -760,7 +740,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char } else if (ptr[0] == ']') { ptr++; break; -#if defined(PROCESS_FWS) } else if (MSG_IS_WSP(ptr[0])) { /* Validation step: Handle [FWS] */ if (MSG_IS_CRLF(++ptr)) { @@ -770,24 +749,14 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char continue; } } -#endif - } - - if (out != NULL) { - *out = ptr; } return(FALSE); } } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } -#if defined(PROCESS_CFWS) /* Specification: [CFWS] Validation step: Handle [CFWS] Handle [FWS] */ @@ -798,10 +767,6 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MSG_IS_WSP(ptr[0])) { ptr++; } else { - if (out) { - *out = ++ptr; - } - return(FALSE); } } @@ -812,28 +777,15 @@ MsgIsAddress(unsigned char *addressLine, size_t addressLineLength, unsigned char if (MsgIsComment(ptr, ptrLimit, &ptr)) { ; } else { - if (out != NULL) { - *out = ptr; - } - return(FALSE); } } -#endif } if ((strchr(delimiters, ptr[0]) != NULL) || (ptr[0] == '\0')) { - if (out != NULL) { - *out = ptr; - } - return(TRUE); } } - - if (out != NULL) { - *out = ptr; - } - return(FALSE); } +#endif diff --git a/src/libs/msgapi/msgapi.c b/src/libs/msgapi/msgapi.c index c5006c7..d6376fa 100644 --- a/src/libs/msgapi/msgapi.c +++ b/src/libs/msgapi/msgapi.c @@ -79,8 +79,6 @@ enum LibraryStates { struct { unsigned long flags; - MDBHandle directoryHandle; - XplThreadID groupID; struct { @@ -89,62 +87,16 @@ struct { XplMutex uid; } sem; - struct { - unsigned char dn[MDB_MAX_OBJECT_CHARS + 1]; - } server; - - struct { - MDBValueStruct *storePaths; - MDBValueStruct *storeDNs; - - struct { - MDBValueStruct *names; - MDBValueStruct *contexts; - struct sockaddr_in *addr; - } server; - -#ifdef PARENTOBJECT_STORE - struct { - MDBValueStruct *objects; - MDBValueStruct *stores; - MDBValueSTruct *indices; - } parent; -#endif - } vs; - unsigned long connManager; XplRWLock configLock; - - struct { - unsigned char work[XPL_MAX_PATH + 1]; - unsigned char nls[XPL_MAX_PATH + 1]; - unsigned char dbf[XPL_MAX_PATH + 1]; - unsigned char bin[XPL_MAX_PATH + 1]; - unsigned char lib[XPL_MAX_PATH + 1]; - unsigned char certificate[XPL_MAX_PATH + 1]; - unsigned char key[XPL_MAX_PATH + 1]; - } paths; - + struct { unsigned long local; unsigned char string[16]; } address; - struct { - unsigned char moduleName[XPL_MAX_PATH + 1]; - unsigned char fileName[XPL_MAX_PATH + 1]; - - XplPluginHandle handle; - - FindObjectCacheInitType init; - FindObjectCacheShutdownType shutdown; - FindObjectCacheType find; - FindObjectCacheExType findEx; - FindObjectStoreCacheType store; - } cache; - struct { unsigned char domain[MAXEMAILNAMESIZE + 1]; unsigned long domainLength; @@ -174,23 +126,10 @@ MsgNmapChallenge(const unsigned char *response, unsigned char *reply, size_t len { unsigned char *ptr; unsigned char *salt; - static unsigned char access[NMAP_HASH_SIZE] = { '\0' }; - MDBValueStruct *v; + static unsigned char access[NMAP_HASH_SIZE] = { '\0' }; xpl_hash_context ctx; - if (access[0] == '\0') { - if (MsgGlobal.directoryHandle) { - v = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - if (v) { - MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, v); - if (v->Used) { - HashCredential(MsgGlobal.server.dn, v->Value[0], access); - } - - MDBDestroyValueStruct(v); - } - } - } + MsgGetServerCredential(&access); if (access[0] && reply && (length > 32) && ((ptr = strchr(response, '<')) != NULL)) { salt = ++ptr; @@ -213,1027 +152,16 @@ MsgNmapChallenge(const unsigned char *response, unsigned char *reply, size_t len EXPORT const unsigned char * MsgGetServerDN(unsigned char *buffer) { - if (buffer) { - return(strcpy(buffer, MsgGlobal.server.dn)); - } - return(MsgGlobal.server.dn); -} - -EXPORT BOOL -MsgFindUserNmap(const unsigned char *user, unsigned char *nmap, int nmap_len, unsigned short *port) -{ - struct sockaddr_in nmap_tmp; - - BOOL retVal = FALSE; - retVal = MsgFindObject(user, NULL, NULL, &nmap_tmp, NULL); - - if (retVal) { - strncpy(nmap, inet_ntoa(nmap_tmp.sin_addr), nmap_len); - *port = ntohs(nmap_tmp.sin_port); - return retVal; - } - - return retVal; -} - -EXPORT BOOL -MsgFindObject(const unsigned char *user, unsigned char *dn, unsigned char *userType, struct sockaddr_in *nmap, MDBValueStruct *v) -{ - BOOL retVal = FALSE; - - if (MsgGlobal.cache.find == NULL) { - MDBValueStruct *userCtx; - MDBValueStruct *types; - unsigned long i, j; - unsigned char rdn[MDB_MAX_OBJECT_CHARS + 1]; - - BOOL isUser = FALSE; - BOOL isGroup = FALSE; - BOOL isResource = FALSE; - BOOL isOrgRole = FALSE; - BOOL isDynGroup = FALSE; - - /* FIXME: handle failure to create ValueStructs */ - userCtx = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - types = MDBShareContext(userCtx); - - XplRWReadLockAcquire(&MsgGlobal.configLock); - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], userCtx); - if (MDBGetObjectDetailsEx(user, types, rdn, dn, userCtx)) { - - /* determine relevant types now so we don't have to loop - throught the list everytime. */ - for (j = 0; j < types->Used; j++) { - if (strcmp(types->Value[j], C_USER) == 0) { - isUser = TRUE; - } else if (strcmp(types->Value[j], - MSGSRV_C_RESOURCE) == 0) { - isResource = TRUE; - } else if (strcmp(types->Value[j], MSGSRV_C_GROUP) == 0 || - strcmp(types->Value[j], C_GROUP) == 0) { - isGroup = TRUE; - } else if (strcmp(types->Value[j], - MSGSRV_C_ORGANIZATIONAL_ROLE) == 0 || - strcmp(types->Value[j], - C_ORGANIZATIONAL_ROLE) == 0) { - isOrgRole = TRUE; - } else if (strcmp(types->Value[j], "dynamicGroup") == 0) { - isDynGroup = TRUE; - } - } - - if (MsgGetUserSetting(user, MSGSRV_A_MESSAGING_DISABLED, - userCtx) > 0) { - if (userCtx->Value[userCtx->Used-1][0] == '1') { - break; - } else { - MDBFreeValue(userCtx->Used - 1, userCtx); - } - } - - if (isUser || isResource) { - if (v) { - MDBAddValue(rdn, v); - } - if (nmap) { - memcpy(nmap, &MsgGlobal.vs.server.addr[i], sizeof(struct sockaddr_in)); - } - if (userType) { - if (isUser) { - strcpy(userType, C_USER); - } else if (isResource) { - strcpy(userType, MSGSRV_C_RESOURCE); - } - } - retVal = TRUE; - } else if (isGroup) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_MEMBER, v); - - /* This removes any context from a group member's name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr = strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, C_GROUP); - } - retVal = TRUE; - } else if (isOrgRole) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_ROLE_OCCUPANT, v); - - /* This removes any context from a the roles name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr = strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, C_ORGANIZATIONAL_ROLE); - } - retVal = TRUE; - } else if (isDynGroup) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_MEMBER, v); - - /* This removes any context from a group member's name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr=strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, "dynamicGroup"); - } - retVal = TRUE; - } - break; - } - } - XplRWReadLockRelease(&MsgGlobal.configLock); - - MDBDestroyValueStruct(userCtx); - MDBDestroyValueStruct(types); - } else { - retVal = MsgGlobal.cache.find(user, dn, userType, nmap, v); - } - - return(retVal); -} - -EXPORT BOOL -MsgFindObjectEx(const unsigned char *user, unsigned char *dn, unsigned char *userType, struct sockaddr_in *nmap, BOOL *disabled, MDBValueStruct *v) -{ - BOOL retVal = FALSE; - - if (MsgGlobal.cache.findEx == NULL) { - MDBValueStruct *userCtx; - MDBValueStruct *types; - unsigned long i, j; - unsigned char rdn[MDB_MAX_OBJECT_CHARS + 1]; - - BOOL isUser = FALSE; - BOOL isGroup = FALSE; - BOOL isResource = FALSE; - BOOL isOrgRole = FALSE; - BOOL isDynGroup = FALSE; - - userCtx = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - types = MDBShareContext(userCtx); - - XplRWReadLockAcquire(&MsgGlobal.configLock); - - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], userCtx); - - if (MDBGetObjectDetailsEx(user, types, rdn, dn, userCtx)) { - for (j = 0; j < types->Used; j++) { - if (strcmp(types->Value[j], C_USER) == 0) { - isUser = TRUE; - } else if (strcmp(types->Value[j], - MSGSRV_C_RESOURCE) == 0) { - isResource = TRUE; - } else if (strcmp(types->Value[j], MSGSRV_C_GROUP) == 0 || - strcmp(types->Value[j], C_GROUP) == 0) { - isGroup = TRUE; - } else if (strcmp(types->Value[j], - MSGSRV_C_ORGANIZATIONAL_ROLE) == 0 || - strcmp(types->Value[j], - C_ORGANIZATIONAL_ROLE) == 0) { - isOrgRole = TRUE; - } else if (strcmp(types->Value[j], "dynamicGroup") == 0) { - isDynGroup = TRUE; - } - } - - if (MsgGetUserSetting(user, MSGSRV_A_MESSAGING_DISABLED, - userCtx) > 0) { - if (userCtx->Value[userCtx->Used - 1][0] == '1') { - *disabled = TRUE; - } else { - *disabled = FALSE; - } - MDBFreeValue(userCtx->Used - 1, userCtx); - } else { - *disabled = FALSE; - } - - if (isUser || isResource) { - if (v) { - MDBAddValue(rdn, v); - } - if (nmap) { - memcpy(nmap, &MsgGlobal.vs.server.addr[i], sizeof(struct sockaddr_in)); - } - if (userType) { - if (isUser) { - strcpy(userType, C_USER); - } else if (isResource) { - strcpy(userType, MSGSRV_C_RESOURCE); - } - } - retVal = TRUE; - } else if (isGroup) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_MEMBER, v); - - /* This removes any context from a group member's name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr = strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, C_GROUP); - } - retVal = TRUE; - } else if (isOrgRole) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_ROLE_OCCUPANT, v); - - /* This removes any context from a the roles name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr = strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, C_ORGANIZATIONAL_ROLE); - } - retVal = TRUE; - } else if (isDynGroup) { - if (v) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], v); - MDBRead(user, A_MEMBER, v); - - /* This removes any context from a group member's name */ - for (j = 0; j < v->Used; j++) { - unsigned char *ptr; - ptr = strrchr(v->Value[j], '\\'); - if (ptr) { - memmove(v->Value[j], ptr + 1, strlen(ptr + 1) + 1); - } - } - } - if (userType) { - strcpy(userType, "dynamicGroup"); - } - retVal = TRUE; - } - break; - } - } - XplRWReadLockRelease(&MsgGlobal.configLock); - - MDBDestroyValueStruct(userCtx); - } else { - retVal = MsgGlobal.cache.findEx(user, dn, userType, nmap, disabled, v); - } - - return(retVal); -} - -EXPORT const unsigned char * -MsgFindUserStore(const unsigned char *user, const unsigned char *defaultPath) -{ - if (MsgGlobal.cache.store == NULL) { - MDBValueStruct *context; - unsigned long i; - - XplRWReadLockAcquire(&MsgGlobal.configLock); - context = MDBCreateValueStruct(MsgGlobal.directoryHandle, MsgGlobal.vs.server.contexts->Value[0]); - - i = 0; - do { - if (MDBIsObject(user, context)) { - MDBDestroyValueStruct(context); - if (MsgGlobal.vs.storePaths->Value[i][0] != EMPTY_CHAR) { - XplRWReadLockRelease(&MsgGlobal.configLock); - return(MsgGlobal.vs.storePaths->Value[i]); - } else { - XplRWReadLockRelease(&MsgGlobal.configLock); - return(defaultPath); - } - } else { - i++; - if (i != MsgGlobal.vs.server.contexts->Used) { - MDBSetValueStructContext(MsgGlobal.vs.server.contexts->Value[i], context); - } - } - } while (i != MsgGlobal.vs.server.contexts->Used); - XplRWReadLockRelease(&MsgGlobal.configLock); - - MDBDestroyValueStruct(context); - return(defaultPath); - } - - return MsgGlobal.cache.store(user, defaultPath); -} - -EXPORT BOOL -MsgReadIP(const unsigned char *object, unsigned char *type, MDBValueStruct *v) -{ - int first,last, i; - unsigned char *ptr; - - if (!v || !type) { - return(FALSE); - } - - first=v->Used; - - if (!object) { - if (!MDBReadDN(MsgGlobal.server.dn, type, v)) { - return(FALSE); - } - } else { - if (!MDBReadDN(object, type, v)) { - return(FALSE); - } - } - - last = v->Used; - - for (i = first; i < last; i++) { - if ((ptr = strrchr(v->Value[i], '\\')) != NULL) { - *ptr = '\0'; - } - MDBRead(v->Value[i], MSGSRV_A_IP_ADDRESS, v); - } - - /* The following loop removes the names read by the ReadDN above, - * but keeps the IP addresses added afterwards :-) */ - for (i = first; i < last; i++) { - MDBFreeValue(0, v); - } - - if (v->Used > 0) { - return(TRUE); - } else { - return(FALSE); - } + // DEPRECATED + return(NULL); } EXPORT BOOL MsgDomainExists(const unsigned char *domain, unsigned char *domainObjectDN) { - MDBValueStruct *domains; - unsigned long i; - unsigned long j; - + // DEPRECATED ? /* FIXME later; when we handle parent objects */ return(FALSE); - - domains = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - - XplRWReadLockAcquire(&MsgGlobal.configLock); - - for (i = 0; i < MsgGlobal.vs.server.names->Used; i++) { - MDBSetValueStructContext(MsgGlobal.vs.server.names->Value[i], domains); - if(MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_DOMAIN, domains) > 0) { - for (j = 0; j < domains->Used; j++) { - if (XplStrCaseCmp(domain, domains->Value[j])==0) { - XplRWReadLockRelease(&MsgGlobal.configLock); - MDBDestroyValueStruct(domains); - - return(TRUE); - } - } - } - MDBFreeValues(domains); - } - MDBDestroyValueStruct(domains); - XplRWReadLockRelease(&MsgGlobal.configLock); - - return(FALSE); -} - -EXPORT int -MsgGetParentAttribute(const unsigned char *userDN, unsigned char *attribute, MDBValueStruct *vOut) -{ - char configDn[MDB_MAX_OBJECT_CHARS + 1]; - unsigned long index; - int result = 0; - - configDn[0] = '\0'; - - if (MsgGetUserSettingsDN(userDN, configDn, vOut, FALSE)) { - if (MDBRead(configDn, MSGSRV_A_PARENT_OBJECT, vOut) > 0) { - index = vOut->Used - 1; - if (MDBRead(vOut->Value[index], attribute, vOut)>0) { - MDBFreeValue(index, vOut); - result = vOut->Used; - } else { - MDBFreeValue(index, vOut); - result = MDBRead(userDN, attribute, vOut); - } - } else { - result = MDBRead(userDN, attribute, vOut); - } - } - - return result; -} - -EXPORT unsigned char * -MsgGetUserEmailAddress(const unsigned char *userDNin, MDBValueStruct *userData, unsigned char *buffer, unsigned long bufLen) -{ - unsigned char *emailAddress = NULL; - unsigned long originalValueCount = userData->Used; - unsigned long lastValueCount = originalValueCount; - unsigned char *user = NULL; - unsigned char userDN[MDB_MAX_OBJECT_CHARS + 1]; - unsigned char configDn[MDB_MAX_OBJECT_CHARS + 1]; - unsigned char *delim; - - /* Make a copy so we don't edit the const string */ - strcpy(userDN, userDNin); - - if (!(MsgGlobal.flags & MSGAPI_FLAG_INTERNET_EMAIL_ADDRESS)) { - MDBRead(userDN, A_INTERNET_EMAIL_ADDRESS, userData); - if (userData->Used > lastValueCount) { - - if (strchr(userData->Value[userData->Used - 1], '@')) { - /* The user object has a value in the Internet Email Address Attribute */ - if (buffer) { - if (bufLen > strlen(userData->Value[userData->Used - 1])) { - emailAddress = buffer; - strcpy(emailAddress, userData->Value[userData->Used - 1]); - } - } else { - emailAddress = MemStrdup(userData->Value[userData->Used - 1]); - } - - while (originalValueCount < userData->Used){ - MDBFreeValue(userData->Used - 1, userData); - } - return(emailAddress); - } else { - user = userData->Value[userData->Used - 1]; - lastValueCount++; - } - } - } - - /* The value in the Internet Email Address Attribute still needs a domain */ - - delim = strrchr(userDN, '\\' ); - if (delim) { - if (strchr(delim + 1, '@')) { - /* The username is an address */ - if (buffer) { - if (bufLen > strlen(delim + 1)) { - emailAddress = buffer; - strcpy(emailAddress, delim + 1); - } - } else { - emailAddress = MemStrdup(delim + 1); - } - - while (originalValueCount < userData->Used) { - MDBFreeValue(userData->Used - 1, userData); - } - - return(emailAddress); - } - - if (!user) { - user = delim + 1; - } - - - if (MsgGetParentAttribute(userDN, MSGSRV_A_DOMAIN, userData)) { - /* The user or parent has a domain defined */ - if (buffer) { - if (bufLen > (strlen(user) + strlen(userData->Value[userData->Used - 1]) + 1)) { - emailAddress = buffer; - sprintf(emailAddress, "%s@%s", user, userData->Value[userData->Used - 1]); - } - } else { - emailAddress = MemMalloc(strlen(user) + strlen(userData->Value[userData->Used - 1]) + 2); - if (emailAddress) { - sprintf(emailAddress, "%s@%s", user, userData->Value[userData->Used - 1]); - } - } - - while (originalValueCount < userData->Used){ - MDBFreeValue(userData->Used - 1, userData); - } - - return(emailAddress); - } - - *delim = '\0'; - if (MsgGetUserSettingsDN(userDN, configDn, userData, FALSE)) { - MDBRead(configDn, MSGSRV_A_DOMAIN, userData); - } - - if (userData->Used > lastValueCount) { - /* The container has a domain defined */ - if (buffer) { - if (bufLen > (strlen(user) + strlen(userData->Value[userData->Used - 1]) + 1)) { - emailAddress = buffer; - sprintf(emailAddress, "%s@%s", user, userData->Value[userData->Used - 1]); - } - } else { - emailAddress = MemMalloc(strlen(user) + strlen(userData->Value[userData->Used - 1]) + 2); - if (emailAddress) { - sprintf(emailAddress, "%s@%s", user, userData->Value[userData->Used - 1]); - } - } - } else { - /* Default user@official */ - if (buffer) { - if (bufLen > (strlen(user) + MsgGlobal.official.domainLength + 1)) { - emailAddress = buffer; - sprintf(emailAddress, "%s@%s", user, MsgGlobal.official.domain); - } - } else { - emailAddress = MemMalloc(strlen(user) + MsgGlobal.official.domainLength + 2); - if (emailAddress) { - sprintf(emailAddress, "%s@%s", user, MsgGlobal.official.domain); - } - } - } - - *delim = '\\'; - - for (;originalValueCount < userData->Used;){ - MDBFreeValue(userData->Used - 1, userData); - } - return(emailAddress); - } - - /* The dn does not appear valid. Treat it as rdn and do our best */ - if (buffer) { - if (bufLen > (strlen(userDN) + MsgGlobal.official.domainLength + 1)) { - emailAddress = buffer; - sprintf(emailAddress, "%s@%s", userDN, MsgGlobal.official.domain); - } - } else { - emailAddress = MemMalloc(strlen(userDN) + MsgGlobal.official.domainLength + 2); - if (emailAddress) { - sprintf(emailAddress, "%s@%s", userDN, MsgGlobal.official.domain); - } - } - - while (originalValueCount < userData->Used) { - MDBFreeValue(userData->Used - 1, userData); - } - return(emailAddress); -} - -EXPORT unsigned char * -MsgGetUserDisplayName(const unsigned char *userDN, MDBValueStruct *userData) -{ - unsigned char *displayName = NULL; - unsigned long index = userData->Used; - unsigned char *rdn; - - /* Read the Display Name */ - if ((MDBRead(userDN, A_FULL_NAME, userData) > 0) && (userData->Value[index][0] != '\0')) { - displayName = MemStrdup(userData->Value[index]); - while (index < userData->Used){ - MDBFreeValue(index, userData); - } - return(displayName); - } - - /* Create full name using First and Last */ - MDBRead(userDN, A_GIVEN_NAME, userData); - MDBRead(userDN, A_SURNAME, userData); - if (userData->Used == (index + 2)) { - if ((userData->Value[index][0] != '\0') && (userData->Value[index + 1][0] != '\0')) { - displayName = MemMalloc (strlen (userData->Value[index]) + strlen (userData->Value[index + 1]) + 2); - sprintf(displayName, "%s %s", userData->Value[index], userData->Value[index + 1]); - } else if (userData->Value[index][0] != '\0') { - displayName = MemStrdup(userData->Value[index]); - } else if (userData->Value[index + 1][0] != '\0') { - displayName = MemStrdup(userData->Value[index + 1]); - } else { - if ((rdn = strrchr(userDN, '\\'))) { - displayName = MemStrdup(rdn + 1); - } else { - - displayName = MemStrdup(""); - } - } - } else if (userData->Used == (index + 1)) { - if (!(userData->Value[index][0] == ' ' && userData->Value[index][1] == '\0')) { - displayName = MemStrdup(userData->Value[index]); - } else { - /* FIXME: is this right? */ - if ((rdn = strrchr (userDN, '\\'))) { - displayName = MemStrdup(rdn + 1); - } else { - displayName = MemStrdup(""); - } - } - } else { - if ((rdn = strrchr(userDN, '\\'))) { - displayName = MemStrdup(rdn + 1); - } else { - displayName = MemStrdup(""); - } - - } - - while (index < userData->Used) { - MDBFreeValue(index, userData); - } - - - return(displayName); - -} - -/* Get the container DN where a given user's settings object should exist. - This function is responsible for sorting BongoUserSettings objects into - various partitions under the root BongoUserSettingsContainer. */ -EXPORT BOOL -MsgGetUserSettingsContainerDN(const unsigned char *userDn, - unsigned char *containerDn, MDBValueStruct *v, - BOOL create) -{ - MDBValueStruct *attr, *data; - char servicesDn[MDB_MAX_OBJECT_CHARS + 1]; - char dn[MDB_MAX_OBJECT_CHARS + 1]; - BOOL result = FALSE; - char *bucket; - - /* Use the first letter of the user's name to sort them into containers. - This is not the most optimal solution, but it should allow admins to - find corresponding config objects more easily. */ - - if (MsgGetConfigProperty(servicesDn, MSGSRV_CONFIG_PROP_BONGO_SERVICES)) { - bucket = strrchr(userDn, '\\'); - - if (bucket) { - bucket++; - } else { - bucket = userDn; - } - - sprintf(dn, "%s\\%s\\%c", servicesDn, MSGSRV_USER_SETTINGS_ROOT, - *bucket); - - if (MDBIsObject(dn, v)) { - result = TRUE; - } else if (create) { - attr = MDBShareContext(v); - data = MDBShareContext(v); - - if (attr && data) { - result = MDBCreateObject(dn, MSGSRV_C_USER_SETTINGS_CONTAINER, - attr, data, v); - MDBDestroyValueStruct(attr); - MDBDestroyValueStruct(data); - } - } - } - - if (result) { - strcpy(containerDn, dn); - } - - return result; -} - -/* - * User settings are stored on a corresponding BongoUserSettings object that - * can be discovered by following the SeeAlso attribute on the User. - * This function is for convenience in discovering the config object DN. - */ -EXPORT BOOL -MsgGetUserSettingsDN(const unsigned char *userDn, unsigned char *configDn, - MDBValueStruct *v, BOOL create) -{ - int i; - char type[MDB_MAX_ATTRIBUTE_VALUE_CHARS + 1]; - char containerDn[MDB_MAX_OBJECT_CHARS + 1]; - char *cn; - MDBValueStruct *vTmp, *attr, *data; - BOOL result = FALSE; - - vTmp = MDBShareContext(v); - - if (vTmp) { - if (MDBReadDN(userDn, A_SEE_ALSO, vTmp)) { - for (i = 0; i < vTmp->Used; i++) { - if (!MDBGetObjectDetails(vTmp->Value[i], type, NULL, NULL, - vTmp)) { - break; - } - - if (!strcasecmp(type, MSGSRV_C_USER_SETTINGS)) { - strcpy(configDn, vTmp->Value[i]); - result = TRUE; - break; - } - } - } - - if (!result && create) { - cn = strrchr(userDn, '\\'); - attr = MDBShareContext(vTmp); - data = MDBShareContext(vTmp); - - if (cn && attr && data && - MsgGetUserSettingsContainerDN(userDn, containerDn, vTmp, - TRUE)) { - sprintf(configDn, "%s\\%s", containerDn, ++cn); - - if (MDBCreateObject(configDn, MSGSRV_C_USER_SETTINGS, - attr, data, vTmp) && - MDBAddDN(userDn, A_SEE_ALSO, configDn, vTmp)) { - result = TRUE; - } else { - configDn[0] = '\0'; - } - - MDBDestroyValueStruct(attr); - MDBDestroyValueStruct(data); - } - } - - MDBDestroyValueStruct(vTmp); - } - - return result; -} - -/* - * Try to get the setting first from the user object, then from the user's - * settings object. Parent object may override values on settings object. - */ -EXPORT long -MsgGetUserSetting(const unsigned char *userDn, unsigned char *attribute, - MDBValueStruct *vOut) -{ - char configDn[MDB_MAX_OBJECT_CHARS + 1]; - char parentDn[MDB_MAX_OBJECT_CHARS + 1]; - MDBValueStruct *v; - long result = 0; - - configDn[0] = '\0'; - parentDn[0] = '\0'; - v = MDBShareContext(vOut); - - if (v) { - if (MsgGetUserSettingsDN(userDn, configDn, v, FALSE)) { - if (MDBReadDN(configDn, MSGSRV_A_PARENT_OBJECT, v)) { - strcpy(parentDn, v->Value[0]); - MDBFreeValues(v); - - if (MDBRead(parentDn, MSGSRV_A_FEATURE_INHERITANCE, v)) { - if (v->Value[0][0] != FEATURE_PARENT_FIRST) { - /* child takes precedence */ - parentDn[0] = '\0'; - } - } - } - } - - - /* try parent object */ - if (*parentDn) { - result = MDBRead(parentDn, attribute, vOut); - } - - /* try user object */ - if (!result) { - result = MDBRead(userDn, attribute, vOut); - } - - /* try settings object */ - if (!result && *configDn) { - result = MDBRead(configDn, attribute, vOut); - } - MDBDestroyValueStruct(v); - } - - return result; -} - -/* - * Use these functions to ensure that the correct MDB function is used - * for strings or DNs. - */ -static BOOL -MsgMdbWriteAny(const unsigned char *dn, const unsigned char *attribute, - MDBValueStruct *v) -{ - if (v->Used > 0 && strchr(v->Value[0], '\\')) { - return MDBWriteDN(dn, attribute, v); - } - - return MDBWrite(dn, attribute, v); -} - -static BOOL -MsgMdbAddAny(const unsigned char *dn, const unsigned char *attribute, - const unsigned char *value, MDBValueStruct *v) -{ - if (v->Used > 0 && strchr(v->Value[0], '\\')) { - return MDBAddDN(dn, attribute, value, v); - } - - return MDBAdd(dn, attribute, value, v); -} - -/* - * Try to apply changes to the user object first then the config object. If - * the config object doesn't exist, create it. - */ -EXPORT BOOL -MsgSetUserSetting(const unsigned char *userDn, unsigned char *attribute, - MDBValueStruct *v) -{ - char configDn[MDB_MAX_OBJECT_CHARS + 1]; - BOOL result = FALSE; - - if (MDBIsObject(userDn, v) && - !(result = MsgMdbWriteAny(userDn, attribute, v))) { - if (MsgGetUserSettingsDN(userDn, configDn, v, TRUE)) { - /* config objects are created on demand */ - result = MsgMdbWriteAny(configDn, attribute, v); - } - } - - return result; -} - -EXPORT BOOL -MsgAddUserSetting(const unsigned char *userDn, unsigned char *attribute, - unsigned char *value, MDBValueStruct *v) -{ - char configDn[MDB_MAX_OBJECT_CHARS + 1]; - BOOL result = FALSE; - - if (MDBIsObject(userDn, v) && - !(result = MsgMdbAddAny(userDn, attribute, value, v))) { - /* config objects are created on demand */ - if (!MsgGetUserSettingsDN(userDn, configDn, v, TRUE)) { - result = MsgMdbAddAny(configDn, attribute, value, v); - } - } - - return result; -} - -/* - * Here's the logic: - * - * Step 1: We get the DN from the caller; we check if there's a parent DN, - * Step 2: If we have inheritance DN, so we read the inheritance configuration of the parent, if not, go to step 4c - * Step 3a: Inheritance is Parent->User; read features attribute from parent - * Step 3b: Inheritance is User->Parent; read features attribute from user - * Step 4a: If feature disabled return disabled state - * Step 4b: If feature from parent, read parent data attribute - * Step 4c: If feature from user, read user data attribute - * Step 5: If data attribute empty, try opposite DN attribute - * - */ -EXPORT BOOL -MsgGetUserFeature(const unsigned char *userDN, unsigned char featureRow, unsigned long featureCol, unsigned char *attribute, MDBValueStruct *vOut) -{ - MDBValueStruct *v; - unsigned char inheritance = '\0'; - unsigned char parentDN[MDB_MAX_OBJECT_CHARS+1]; - unsigned char configDN[MDB_MAX_OBJECT_CHARS+1]; - const unsigned char *objectDN; - unsigned long i; - BOOL looped; - - v = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - - configDN[0] = '\0'; - MsgGetUserSettingsDN(userDN, configDN, v, FALSE); - - /* Step 1 */ - if (configDN && MDBRead(configDN, MSGSRV_A_PARENT_OBJECT, v) > 0) { - /* We have a parent */ - - /* Step 2 */ - strcpy(parentDN, v->Value[0]); - - if (MDBRead(v->Value[0], MSGSRV_A_FEATURE_INHERITANCE, v) > 0) { - /* We have a configured inheritance */ - if ((inheritance = v->Value[1][0]) == FEATURE_PARENT_FIRST) { - objectDN = parentDN; - } else { - objectDN = configDN; - } - } else { - /* No inheritance configured */ - objectDN = configDN; - } - MDBFreeValues(v); - } else { - parentDN[0] = '\0'; - objectDN = configDN; - } - - /* objectDN now contains the DN we have determined we need to read first */ - - looped=FALSE; - - /* Step 3 */ - ReadFeatureAttribute: - if (MDBRead(objectDN, MSGSRV_A_FEATURE_SET, v) > 0) { - /* We have features defined on the object */ - for (i = 0; i < v->Used; i++) { - /* Find our feature */ - if (v->Value[i][0] == featureRow) { - switch (v->Value[i][featureCol]) { - case FEATURE_NOT_AVAILABLE: { - /* Feature disabled; return */ - MDBDestroyValueStruct(v); - - return(FALSE); - } - - case FEATURE_AVAILABLE: { - /* Feature enabled */ - i = v->Used; - break; - } - - case FEATURE_USE_PARENT: - /* Feature enabled via parent */ - case FEATURE_USE_USER: { - /* Feature enabled via user */ - if (!looped && (parentDN[0] != '\0')) { - if (objectDN == parentDN) { - objectDN = configDN; - } else { - objectDN = parentDN; - } - - MDBFreeValues(v); - looped=TRUE; - goto ReadFeatureAttribute; - } else { - /* If loop exists, use user object */ - objectDN = configDN; - i = v->Used; - } - break; - } - } - } - } - - /* We now have the DN of the object we need to read the data attribute from in ObjectDN */ - MDBFreeValues(v); - } else { - /* We didn't find a feature set configuration */ - if (inheritance == FEATURE_PARENT_FIRST) { - /* We read the parent, didn't have feature config, let's read the user's feature set */ - inheritance = FEATURE_USER_FIRST; - objectDN = configDN; - goto ReadFeatureAttribute; - } else { - /* We read the user, don't have inheritance and don't have a feature set -> return enabled feature! */ - goto ReadDataAttribute; - } - } - - ReadDataAttribute: - /* Beyond this point, we can return success; we returned failure above */ - - /* Clean up */ - MDBDestroyValueStruct(v); - - /* If Attribute NULL we just check if feature disabled */ - if (!attribute) { - return(TRUE); - } - - return MsgGetUserSetting(configDN, attribute, vOut); } EXPORT BOOL @@ -1310,66 +238,89 @@ MsgMakePath(unsigned char *path) } EXPORT const unsigned char * -MsgGetDBFDir(char *directory) +MsgGetDir(MsgApiDirectory directory, char *buffer, size_t buffer_size) { - if (directory) { - strcpy(directory, MsgGlobal.paths.dbf); - } - return(MsgGlobal.paths.dbf); + const unsigned char *path; + switch(directory) { + case MSGAPI_DIR_BIN: + path = XPL_DEFAULT_BIN_DIR; + break; + case MSGAPI_DIR_CACHE: + path = XPL_DEFAULT_CACHE_DIR; + break; + case MSGAPI_DIR_COOKIE: + path = XPL_DEFAULT_COOKIE_DIR; + break; + case MSGAPI_DIR_CERT: + path = XPL_DEFAULT_DBF_DIR; + break; + case MSGAPI_DIR_DATA: + path = XPL_DEFAULT_DATA_DIR; + break; + case MSGAPI_DIR_DBF: + path = XPL_DEFAULT_DBF_DIR; + break; + case MSGAPI_DIR_LIB: + path = XPL_DEFAULT_LIB_DIR; + break; + case MSGAPI_DIR_MAIL: + path = XPL_DEFAULT_MAIL_DIR; + break; + case MSGAPI_DIR_SCMS: + path = XPL_DEFAULT_SCMS_DIR; + break; + case MSGAPI_DIR_SPOOL: + path = XPL_DEFAULT_SPOOL_DIR; + break; + case MSGAPI_DIR_STATE: + path = XPL_DEFAULT_STATE_DIR; + break; + case MSGAPI_DIR_STORESYSTEM: + path = XPL_DEFAULT_STORE_SYSTEM_DIR; + break; + case MSGAPI_DIR_WORK: + path = XPL_DEFAULT_WORK_DIR; + break; + default: + if (buffer && buffer_size) + buffer[0] = '\0'; + return NULL; + } + if (buffer) { + strncpy(buffer, path, buffer_size - 1); + } + return path; } EXPORT const unsigned char * -MsgGetWorkDir(char *directory) +MsgGetFile(MsgApiFile file, char *buffer, size_t buffer_size) { - if (directory) { - strcpy(directory, MsgGlobal.paths.work); - } - return(MsgGlobal.paths.work); -} - -EXPORT const unsigned char * -MsgGetNLSDir(char *directory) -{ - if (directory) { - strcpy(directory, MsgGlobal.paths.nls); - } - return(MsgGlobal.paths.nls); -} - -EXPORT const unsigned char * -MsgGetBinDir(char *directory) -{ - if (directory) { - strcpy(directory, MsgGlobal.paths.bin); - } - return(MsgGlobal.paths.bin); -} - -EXPORT const unsigned char * -MsgGetLibDir(char *directory) -{ - if (directory) { - strcpy(directory, MsgGlobal.paths.lib); - } - return(MsgGlobal.paths.bin); -} - -EXPORT const unsigned char * -MsgGetTLSCertPath(char *path) -{ - if (path) { - strcpy(path, MsgGlobal.paths.certificate); - } - return(MsgGlobal.paths.certificate); -} - -EXPORT const unsigned char * -MsgGetTLSKeyPath(char *path) -{ - if (path) { - strcpy(path, MsgGlobal.paths.key); - } - return(MsgGlobal.paths.key); + const unsigned char *path; + switch(file) { + case MSGAPI_FILE_PUBKEY: + path = XPL_DEFAULT_CERT_PATH; + break; + case MSGAPI_FILE_PRIVKEY: + path = XPL_DEFAULT_KEY_PATH; + break; + case MSGAPI_FILE_DHPARAMS: + path = XPL_DEFAULT_DHPARAMS_PATH; + break; + case MSGAPI_FILE_RSAPARAMS: + path = XPL_DEFAULT_RSAPARAMS_PATH; + break; + case MSGAPI_FILE_RANDSEED: + path = XPL_DEFAULT_RANDSEED_PATH; + break; + default: + if (buffer && buffer_size) + buffer[0] = '\0'; + return NULL; + } + if (buffer) { + strncpy(buffer, path, buffer_size - 1); + } + return path; } EXPORT unsigned long @@ -1398,253 +349,6 @@ MsgGetUnprivilegedUser(void) } } -static BOOL -LoadContextList(MDBValueStruct *config) -{ - unsigned char emptyString[] = " "; - unsigned char storeObjectDn[MDB_MAX_OBJECT_CHARS + 1]; - MDBValueStruct *ports; - MDBValueStruct *addresses; - char storePortText[6]; - unsigned long i; - unsigned long j; - unsigned long count; - unsigned long realUsed; - - ports = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - if (!ports) { - return(FALSE); - } - - addresses = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - if (!addresses) { - MDBDestroyValueStruct(ports); - return(FALSE); - } - - MDBFreeValues(MsgGlobal.vs.server.names); - MDBFreeValues(MsgGlobal.vs.server.contexts); - MDBFreeValues(MsgGlobal.vs.storePaths); - MDBFreeValues(MsgGlobal.vs.storeDNs); - if (MsgGlobal.vs.server.addr) { - MemFree(MsgGlobal.vs.server.addr); - MsgGlobal.vs.server.addr = NULL; - } - - /* This puts the local context always first */ - sprintf(storeObjectDn, "%s\\%s", MsgGlobal.server.dn, MSGSRV_AGENT_STORE); - if(MDBIsObject(storeObjectDn, MsgGlobal.vs.server.contexts)) { - MDBReadDN(MsgGlobal.server.dn, MSGSRV_A_CONTEXT, MsgGlobal.vs.server.contexts); - if (MDBRead(storeObjectDn, MSGSRV_A_PORT, config)) { - strcpy(storePortText, config->Value[0]); - MDBFreeValues(config); - } else { - sprintf(storePortText, "%d", (BONGO_STORE_DEFAULT_PORT)); - } - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - MDBRead(MsgGlobal.server.dn, MSGSRV_A_IP_ADDRESS, addresses); - MDBAddValue(storePortText, ports); - MDBAddValue(MsgGlobal.server.dn, MsgGlobal.vs.storeDNs); - } - } - -#ifdef PARENTOBJECT_STORE - /* Read the parent object store configuration */ - if (MDBEnumerateObjects(MSGSRV_ROOT"\\"MSGSRV_PARENT_ROOT, MSGSRV_C_PARENTOBJECT, &MsgGlobal.vs.parent.objects)) { - for (i=0; iUsed; i++) { - /* MsgGlobal.server.dn is absolute, MsgGlobal.vs.server.names->Value isn't */ - if (XplStrCaseCmp(MsgGlobal.server.dn + strlen(MsgGlobal.server.dn) - strlen(MsgGlobal.vs.server.names->Value[i]), MsgGlobal.vs.server.names->Value[i]) != 0) { - count = MsgGlobal.vs.server.contexts->Used; - if ((MDBRead(MsgGlobal.vs.server.names->Value[i], MSGSRV_A_IP_ADDRESS, addresses) > 0) && - (MDBReadDN(MsgGlobal.vs.server.names->Value[i], MSGSRV_A_CONTEXT, MsgGlobal.vs.server.contexts) > 0)) { - sprintf(storeObjectDn, "%s\\%s", MsgGlobal.vs.server.names->Value[i], MSGSRV_AGENT_STORE); - if (MDBRead(storeObjectDn, MSGSRV_A_PORT, config)) { - strcpy(storePortText, config->Value[0]); - MDBFreeValues(config); - } else { - sprintf(storePortText, "%d", (BONGO_STORE_DEFAULT_PORT)); - } - MDBAddValue(MsgGlobal.vs.server.names->Value[i], MsgGlobal.vs.storeDNs); - for (j = count + 1; j < MsgGlobal.vs.server.contexts->Used; j++) { - MDBAddValue(addresses->Value[count], addresses); - MDBAddValue(storePortText, ports); - MDBAddValue(MsgGlobal.vs.server.names->Value[i], MsgGlobal.vs.storeDNs); - } - } - } - } - } - - /* Now check any aliases that might be in the Internet Services container */ - realUsed = MsgGlobal.vs.server.names->Used; - if (MDBEnumerateObjects(MSGSRV_ROOT, C_ALIAS, NULL, MsgGlobal.vs.server.names)) { - unsigned char realDn[MDB_MAX_OBJECT_CHARS + 1]; - unsigned char realType[MDB_MAX_ATTRIBUTE_CHARS + 1]; - - /* Put the local context(s) first */ - for (i = realUsed; i < MsgGlobal.vs.server.names->Used; i++) { - MDBGetObjectDetails(MsgGlobal.vs.server.names->Value[i], realType, NULL, realDn, MsgGlobal.vs.server.names); - - /* MsgGlobal.server.dn is absolute, MsgGlobal.vs.server.names->Value isn't */ - if ((XplStrCaseCmp(realType, MSGSRV_C_SERVER) == 0) && (XplStrCaseCmp(MsgGlobal.server.dn + strlen(MsgGlobal.server.dn) - strlen(realDn), realDn) != 0)) { - count = MsgGlobal.vs.server.contexts->Used; - if ((MDBRead(MsgGlobal.vs.server.names->Value[i], MSGSRV_A_IP_ADDRESS, addresses) > 0) && - (MDBReadDN(MsgGlobal.vs.server.names->Value[i], MSGSRV_A_CONTEXT, MsgGlobal.vs.server.contexts) > 0)) { - sprintf(storeObjectDn, "%s\\%s", MsgGlobal.vs.server.names->Value[i], MSGSRV_AGENT_STORE); - if (MDBRead(storeObjectDn, MSGSRV_A_PORT, config)) { - strcpy(storePortText, config->Value[0]); - MDBFreeValues(config); - } else { - sprintf(storePortText, "%d", BONGO_STORE_DEFAULT_PORT); - } - MDBAddValue(MsgGlobal.vs.server.names->Value[i], MsgGlobal.vs.storeDNs); - for (j = count + 1; j < MsgGlobal.vs.server.contexts->Used; j++) { - MDBAddValue(addresses->Value[count], addresses); - MDBAddValue(storePortText, ports); - MDBAddValue(MsgGlobal.vs.server.names->Value[i], MsgGlobal.vs.storeDNs); - } - } - } - } - } - } - - /* MDBAddValue doesn't add empty values, so fake it */ - /* with a ^A in the string */ - emptyString[0]=EMPTY_CHAR; - /* Now read all the store path values */ - - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - if (MDBRead(MsgGlobal.vs.server.contexts->Value[i], MSGSRV_A_MESSAGE_STORE, MsgGlobal.vs.storePaths) == 0) { - /* Add an empty string, no context store specified */ - MDBAddValue(emptyString, MsgGlobal.vs.storePaths); - } else { - MsgCleanPath(MsgGlobal.vs.storePaths->Value[i]); - } - } - - /* Initialize addr structure for each context */ - MsgGlobal.vs.server.addr = MemMalloc0(MsgGlobal.vs.server.contexts->Used * sizeof(struct sockaddr_in)); - if (!MsgGlobal.vs.server.addr) { - MDBDestroyValueStruct(ports); - return(FALSE); - } - - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - MsgGlobal.vs.server.addr[i].sin_addr.s_addr = inet_addr(addresses->Value[i]); - MsgGlobal.vs.server.addr[i].sin_port = htons(atol(ports->Value[i])); - MsgGlobal.vs.server.addr[i].sin_family = AF_INET; - } - - -#if 0 - for (i = 0; i < MsgGlobal.vs.server.contexts->Used; i++) { - XplConsolePrintf("\rCtx:%-35s IP:%-15s Path:%s\n", MsgGlobal.vs.server.contexts->Value[i], addresses->Value[i], MsgGlobal.vs.storePaths->Value[i]); - XplConsolePrintf("\rDN :%-35s\n\n", MsgGlobal.vs.storeDNs->Value[i]); - } -#endif - - MDBDestroyValueStruct(addresses); - MDBDestroyValueStruct(ports); - return(TRUE); - } - -static void -MsgConfigMonitor(void) -{ - MDBValueStruct *config; - unsigned long i; - long prevConfigNumber = 0; - struct tm *timeStruct; - time_t utcTime; - long tmp; - - MsgGlobal.flags |= MSGAPI_FLAG_MONITOR_RUNNING; - - XplRenameThread(XplGetThreadID(), "MsgAPI Config Monitor"); - - config = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - if (!config) { - printf("WARNING: MsgConfigMonitor() couldn't create value struct: directory handle %p\n", - MsgGlobal.directoryHandle); - return; - } - - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_CONFIG_CHANGED, config) > 0) { - prevConfigNumber = atol(config->Value[0]); - } - - while (!(MsgGlobal.flags & MSGAPI_FLAG_EXITING)) { - for (i = 0; (i < 300) && !(MsgGlobal.flags & MSGAPI_FLAG_EXITING); i++) { - XplDelay(1000); - } - - /* Get Server Time Zone Offset */ - tzset(); - utcTime = time(NULL); - timeStruct = localtime(&utcTime); - if (timeStruct) { - tmp = (((((((timeStruct->tm_year - 70) * 365) + timeStruct->tm_yday) * 24) + timeStruct->tm_hour) * 60) + timeStruct->tm_min) * 60; - timeStruct = gmtime(&utcTime); - tmp -= (((((((timeStruct->tm_year - 70) * 365) + timeStruct->tm_yday) * 24) + timeStruct->tm_hour) * 60) + timeStruct->tm_min) * 60; - MsgDateSetUTCOffset(tmp); - } - - MDBFreeValues(config); - - if (!(MsgGlobal.flags & MSGAPI_FLAG_EXITING) && (MDBRead(MSGSRV_ROOT, MSGSRV_A_CONFIG_CHANGED, config)>0) && (atol(config->Value[0]) != prevConfigNumber)) { - /* Clear what we just read */ - prevConfigNumber = atol(config->Value[0]); - MDBFreeValues(config); - - /* Acquire Write Lock */ - XplRWWriteLockAcquire(&MsgGlobal.configLock); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_CONNMGR_CONFIG, config)) { - if (atoi(config->Value[0]) == 1) { - MsgGlobal.flags |= MSGAPI_FLAG_SUPPORT_CONNMGR; - } - } - MDBFreeValues(config); - - if (MsgReadIP(MsgGlobal.server.dn, MSGSRV_A_CONNMGR, config)) { - MsgGlobal.connManager = inet_addr(config->Value[0]); - } - MDBFreeValues(config); - - LoadContextList(config); - - XplRWWriteLockRelease(&MsgGlobal.configLock); - } - } - MDBDestroyValueStruct(config); - - MsgGlobal.flags &= ~MSGAPI_FLAG_MONITOR_RUNNING; - - XplExitThread(TSR_THREAD, 0); -} - static BOOL MsgLibraryStop(void) { @@ -1652,37 +356,12 @@ MsgLibraryStop(void) XplDelay(1000); } - MDBDestroyValueStruct(MsgGlobal.vs.storeDNs); - MDBDestroyValueStruct(MsgGlobal.vs.storePaths); - MDBDestroyValueStruct(MsgGlobal.vs.server.contexts); - MDBDestroyValueStruct(MsgGlobal.vs.server.names); - if (MsgGlobal.vs.server.addr) { - MemFree(MsgGlobal.vs.server.addr); - MsgGlobal.vs.server.addr = NULL; - } - - -#ifdef PARENTOBJECT_STORE - MDBDestroyValueStruct(MsgGlobal.vs.parent.stores); - MDBDestroyValueStruct(MsgGlobal.vs.parent.objects); -#endif - - if (MsgGlobal.cache.handle) { - MsgGlobal.cache.shutdown(); - - XplReleaseDLLFunction(MsgGlobal.cache.fileName, "MsgGlobal.cache.init", MsgGlobal.cache.handle); - XplReleaseDLLFunction(MsgGlobal.cache.fileName, "MsgGlobal.cache.shutdown", MsgGlobal.cache.handle); - XplReleaseDLLFunction(MsgGlobal.cache.fileName, "FindObjectCache", MsgGlobal.cache.handle); - XplReleaseDLLFunction(MsgGlobal.cache.fileName, "FindObjectStoreCache", MsgGlobal.cache.handle); - - XplUnloadDLL(MsgGlobal.cache.fileName, MsgGlobal.cache.handle); - } - XplRWLockDestroy(&MsgGlobal.configLock); return(TRUE); } +#if 0 /** * Get a config property from global configuration file. Removes dependency * on NCPServer object in the directory (as well as others). See msgapi.h for @@ -1698,8 +377,7 @@ MsgGetConfigProperty(unsigned char *Buffer, unsigned char *Property) int len; char conf_path[FILENAME_MAX]; - snprintf(conf_path, FILENAME_MAX, "%s/%s", XPL_DEFAULT_CONF_DIR, - MSGSRV_CONFIG_FILENAME); + snprintf(conf_path, FILENAME_MAX, "%s/bongo.conf", XPL_DEFAULT_CONF_DIR); if (!(fh = fopen(conf_path, "r"))) { return result; @@ -1729,6 +407,7 @@ MsgGetConfigProperty(unsigned char *Buffer, unsigned char *Property) fclose(fh); return result; } +#endif void MsgGetUid(char *buffer, int buflen) @@ -1763,195 +442,29 @@ MsgLibraryStart(void) unsigned long i; struct sockaddr_in server_sockaddr; unsigned char path[XPL_MAX_PATH + 1]; - MDBValueStruct *config; XplThreadID ID; /* Prepare later config updates */ XplRWLockInit(&MsgGlobal.configLock); /* Read generic configuration info */ - config = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_CONNMGR_CONFIG, config)) { - if (atoi(config->Value[0]) == 1) { - MsgGlobal.flags |= MSGAPI_FLAG_SUPPORT_CONNMGR; - } - } - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_CERTIFICATE_LOCATION, config)) { - strcpy(MsgGlobal.paths.certificate, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.certificate); - } else { - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_CERTIFICATE_LOCATION, config)) { - strcpy(MsgGlobal.paths.certificate, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.certificate); - } else { - strcpy(MsgGlobal.paths.certificate, XPL_DEFAULT_CERT_PATH); - } - } - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_PRIVATE_KEY_LOCATION, config)) { - strcpy(MsgGlobal.paths.key, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.key); - } else { - if (MDBRead(MSGSRV_ROOT, MSGSRV_A_PRIVATE_KEY_LOCATION, config)) { - strcpy(MsgGlobal.paths.key, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.key); - } else { - strcpy(MsgGlobal.paths.key, XPL_DEFAULT_KEY_PATH); - } - } - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_CLUSTERED, config)>0) { - if (atol (config->Value[0])) { - MsgGlobal.flags |= MSGAPI_FLAG_CLUSTERED; - } - } - MDBFreeValues(config); - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_FORCE_BIND, config)>0) { - if (atol (config->Value[0])) { - MsgGlobal.flags |= MSGAPI_FLAG_BOUND; - } - } - MDBFreeValues(config); - if (!(MsgGlobal.flags & MSGAPI_FLAG_CLUSTERED)) { - MsgGlobal.flags &= ~MSGAPI_FLAG_BOUND; - } - /* Config is free'd further down */ - MDBFreeValues(config); - - /* Read "context" related stuff */ - - MsgGlobal.vs.server.names = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - MsgGlobal.vs.server.contexts = MDBShareContext(MsgGlobal.vs.server.names); - MsgGlobal.vs.storePaths = MDBShareContext(MsgGlobal.vs.server.names); - MsgGlobal.vs.storeDNs = MDBShareContext(MsgGlobal.vs.server.names); - MsgGlobal.vs.server.addr = NULL; - -#ifdef PARENTOBJECT_STORE - MsgGlobal.vs.parent.objects = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - MsgGlobal.vs.parent.stores = MDBShareContext(MsgGlobal.vs.parent.objects); -#endif - - server_sockaddr.sin_addr.s_addr=XplGetHostIPAddress(); - sprintf(MsgGlobal.address.string,"%d.%d.%d.%d", - server_sockaddr.sin_addr.s_net, - server_sockaddr.sin_addr.s_host, - server_sockaddr.sin_addr.s_lh, - server_sockaddr.sin_addr.s_impno); - - MDBAddValue(MsgGlobal.address.string, MsgGlobal.vs.server.names); - if (!(MsgGlobal.flags & MSGAPI_FLAG_CLUSTERED)) { - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_IP_ADDRESS, MsgGlobal.vs.server.names); - } else { - MDBFreeValues(MsgGlobal.vs.server.names); - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_IP_ADDRESS, MsgGlobal.vs.server.names)>0) { - strcpy(MsgGlobal.address.string, MsgGlobal.vs.server.names->Value[0]); - } - } - - MDBFreeValues(MsgGlobal.vs.server.names); + MsgGlobal.flags |= MSGAPI_FLAG_SUPPORT_CONNMGR; + // MsgGlobal.flags |= MSGAPI_FLAG_CLUSTERED; + // 'BOUND' conflicts with 'CLUSTERED' ? + // MsgGlobal.flags |= MSGAPI_FLAG_BOUND; + + /* set the ip address up correctly */ + server_sockaddr.sin_addr.s_addr = XplGetHostIPAddress(); + sprintf(MsgGlobal.address.string, "%d.%d.%d.%d", + server_sockaddr.sin_addr.s_net, + server_sockaddr.sin_addr.s_host, + server_sockaddr.sin_addr.s_lh, + server_sockaddr.sin_addr.s_impno); MsgGlobal.address.local = inet_addr(MsgGlobal.address.string); - /* This stuff is here to prevent a catch-22 with the IP address configuration above */ - if (MsgReadIP(MsgGlobal.server.dn, MSGSRV_A_CONNMGR, config)) { - MsgGlobal.connManager = inet_addr(config->Value[0]); - } - MDBFreeValues(config); - - LoadContextList(config); - - MDBDestroyValueStruct(config); - - XplBeginThread(&ID, MsgConfigMonitor, 32767, NULL, i); - - /* Attempt to load the plugable cache mechanism */ - sprintf(MsgGlobal.cache.fileName, "%s%s", MsgGlobal.cache.moduleName, XPL_DLL_EXTENSION); - sprintf(path, "%s/%s", XPL_DEFAULT_BIN_DIR, MsgGlobal.cache.fileName); - - MsgGlobal.cache.handle = XplLoadDLL(path); - if (MsgGlobal.cache.handle != NULL) { - MsgGlobal.cache.init = (FindObjectCacheInitType)XplGetDLLFunction(MsgGlobal.cache.fileName, "MsgGlobal.cache.init", MsgGlobal.cache.handle); - MsgGlobal.cache.shutdown = (FindObjectCacheShutdownType)XplGetDLLFunction(MsgGlobal.cache.fileName, "MsgGlobal.cache.shutdown", MsgGlobal.cache.handle); - MsgGlobal.cache.find = (FindObjectCacheType)XplGetDLLFunction(MsgGlobal.cache.fileName, "FindObjectCache", MsgGlobal.cache.handle); - MsgGlobal.cache.findEx = (FindObjectCacheExType)XplGetDLLFunction(MsgGlobal.cache.fileName, "FindObjectExCache", MsgGlobal.cache.handle); - MsgGlobal.cache.store = (FindObjectStoreCacheType)XplGetDLLFunction(MsgGlobal.cache.fileName, "FindObjectStoreCache", MsgGlobal.cache.handle); - - if (!MsgGlobal.cache.init || !MsgGlobal.cache.shutdown || !MsgGlobal.cache.find || !MsgGlobal.cache.findEx || !MsgGlobal.cache.store) { - MsgGlobal.cache.init = NULL; - MsgGlobal.cache.shutdown = NULL; - MsgGlobal.cache.find = NULL; - MsgGlobal.cache.findEx = NULL; - MsgGlobal.cache.store = NULL; - } - - if (MsgGlobal.cache.init) { - MSGCacheInitStruct initData; - - initData.DirectoryHandle = MsgGlobal.directoryHandle; - initData.ServerContexts = MsgGlobal.vs.server.contexts; - initData.ServerAddr = MsgGlobal.vs.server.addr; - initData.StorePath = MsgGlobal.vs.storePaths; - initData.ConfigLock = &MsgGlobal.configLock; - initData.DefaultFindObject = MsgFindObject; - initData.DefaultFindObjectEx = MsgFindObjectEx; - initData.DefaultFindObjectStore = MsgFindUserStore; - initData.DefaultPathChar = EMPTY_CHAR; - - if (!MsgGlobal.cache.init(&initData, path)) { - MsgGlobal.cache.init = NULL; - MsgGlobal.cache.shutdown = NULL; - MsgGlobal.cache.find = NULL; - MsgGlobal.cache.findEx = NULL; - MsgGlobal.cache.store = NULL; - } - - } - } - return(TRUE); } -MDBHandle -MsgGetSystemDirectoryHandle(void) -{ - MDBHandle systemHandle; - unsigned char buffer[XPL_MAX_PATH + 1]; - unsigned char credential[128]; - FILE *eclients; - - memset(credential, 0, sizeof(credential)); - - sprintf(buffer, "%s/eclients.dat", XPL_DEFAULT_DBF_DIR); - eclients = fopen(buffer, "rb"); - if (eclients) { - fread(credential, sizeof(unsigned char), sizeof(credential), eclients); - - fclose(eclients); - eclients = NULL; - } else { - XplConsolePrintf("Insufficient privileges; shutting down.\n"); - return(NULL); - } - - if (!MsgGetConfigProperty(MsgGlobal.server.dn, - MSGSRV_CONFIG_PROP_MESSAGING_SERVER)) { - XplConsolePrintf("Messaging server not configured. Shutdown.\n"); - return(NULL); - } - - systemHandle = MDBAuthenticate("Bongo", MsgGlobal.server.dn, credential); - if (systemHandle == NULL) { - XplConsolePrintf("Messaging server credentials are invalid; shutting down.\n"); - return(NULL); - } - - return(systemHandle); -} - BOOL MsgGetBuildVersion(int *version, BOOL *custom) { @@ -2016,7 +529,6 @@ MsgGetUpdateStatus(char *record, int record_length) static BOOL MsgReadConfiguration(void) { - MDBValueStruct *config; unsigned long i; struct tm *timeStruct; time_t utcTime; @@ -2034,128 +546,6 @@ MsgReadConfiguration(void) MsgDateSetUTCOffset(tmp); } - /* Read operating parameters, this is so complicated because in version 2.5 - * we changed the configuration of directories - before 2.5 we would always - * append novonyx/mail to any given path, now we don't. The code tries to - * automatically detect pre2.5 installs and change the DS attribute... - */ - - config = MDBCreateValueStruct(MsgGlobal.directoryHandle, NULL); - - if (!config) { - XplConsolePrintf("Messaging server out of memory; shutting down.\n"); - MDBRelease(MsgGlobal.directoryHandle); - MsgGlobal.directoryHandle = NULL; - return(FALSE); - } - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_NLS_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.nls, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.nls); - MsgMakePath(MsgGlobal.paths.nls); - MDBFreeValues(config); - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_DBF_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.dbf, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.dbf); - MsgMakePath(MsgGlobal.paths.dbf); - MDBFreeValues(config); - } else { - strcpy(MsgGlobal.paths.dbf, XPL_DEFAULT_DBF_DIR); - MsgMakePath(MsgGlobal.paths.dbf); - } - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_BIN_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.bin, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.bin); - MsgMakePath(MsgGlobal.paths.bin); - MDBFreeValues(config); - } else { - strcpy(MsgGlobal.paths.bin, XPL_DEFAULT_BIN_DIR); - MsgMakePath(MsgGlobal.paths.bin); - } - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_LIB_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.lib, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.lib); - MsgMakePath(MsgGlobal.paths.lib); - MDBFreeValues(config); - } else { - strcpy(MsgGlobal.paths.lib, XPL_DEFAULT_LIB_DIR); - MsgMakePath(MsgGlobal.paths.lib); - } - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_WORK_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.work, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.work); - MsgMakePath(MsgGlobal.paths.work); - MDBFreeValues(config); - } else { - strcpy(MsgGlobal.paths.work, XPL_DEFAULT_WORK_DIR); - MsgMakePath(MsgGlobal.paths.work); - } - } else { - strcpy(MsgGlobal.paths.dbf, XPL_DEFAULT_DBF_DIR); - MsgMakePath(MsgGlobal.paths.dbf); - MDBAddValue(MsgGlobal.paths.dbf, config); - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_DBF_DIRECTORY, config); - MDBFreeValues(config); - - strcpy(MsgGlobal.paths.nls, XPL_DEFAULT_NLS_DIR); - MsgMakePath(MsgGlobal.paths.nls); - MDBAddValue(MsgGlobal.paths.nls, config); - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_NLS_DIRECTORY, config); - MDBFreeValues(config); - - strcpy(MsgGlobal.paths.bin, XPL_DEFAULT_BIN_DIR); - MsgMakePath(MsgGlobal.paths.bin); - MDBAddValue(MsgGlobal.paths.bin, config); - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_BIN_DIRECTORY, config); - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_WORK_DIRECTORY, config)) { - strcpy(MsgGlobal.paths.work, config->Value[0]); - MsgCleanPath(MsgGlobal.paths.work); - strcat(MsgGlobal.paths.work, "/novonyx/mail"); - MsgMakePath(MsgGlobal.paths.work); - MDBFreeValues(config); - - MDBAddValue(MsgGlobal.paths.work, config); - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_WORK_DIRECTORY, config); - MDBFreeValues(config); - } else { - strcpy(MsgGlobal.paths.work, XPL_DEFAULT_WORK_DIR); - MsgMakePath(MsgGlobal.paths.work); - MDBAddValue(MsgGlobal.paths.work, config); - MDBWrite(MsgGlobal.server.dn, MSGSRV_A_WORK_DIRECTORY, config); - MDBFreeValues(config); - } - } - - /* Official Name */ - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_OFFICIAL_NAME, config)) { - strcpy(MsgGlobal.official.domain, config->Value[0]); - MsgGlobal.official.domainLength = strlen(MsgGlobal.official.domain); - } - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_CONFIGURATION, config)) { - for (i = 0; i < config->Used; i++) { - if (XplStrNCaseCmp(config->Value[i], "FindObjectModule=", 17) == 0) { - strcpy(MsgGlobal.cache.moduleName, config->Value[i]+17); - } else if (XplStrNCaseCmp(config->Value[i], "IgnoreInternetEmailAddressAttribute", 35) == 0) { - MsgGlobal.flags |= MSGAPI_FLAG_INTERNET_EMAIL_ADDRESS; - } - } - } - MDBFreeValues(config); - - if (MDBRead(MsgGlobal.server.dn, MSGSRV_A_SERVER_STANDALONE, config)) { - if (config->Value[0][0]=='1') { - MsgGlobal.flags |= MSGAPI_FLAG_STANDALONE; - } - } - MDBDestroyValueStruct(config); - return(TRUE); } @@ -2168,17 +558,8 @@ MsgLibraryInit(void) MsgGlobal.groupID = XplGetThreadGroupID(); - MsgGlobal.directoryHandle = NULL; - MsgGlobal.connManager = 0x0100007F; - strcpy(MsgGlobal.cache.moduleName, "msgcache"); - MsgGlobal.cache.init = NULL; - MsgGlobal.cache.shutdown = NULL; - MsgGlobal.cache.find = NULL; - MsgGlobal.cache.findEx = NULL; - MsgGlobal.cache.store = NULL; - MsgGlobal.official.domain[0] = '\0'; MsgGlobal.official.domainLength = 0; @@ -2187,17 +568,6 @@ MsgLibraryInit(void) MemoryManagerOpen(NULL); - if (!MDBInit()) { - MemoryManagerClose(NULL); - return 0; - } - - MsgGlobal.directoryHandle = MsgGetSystemDirectoryHandle(); - if (!(MsgGlobal.directoryHandle)) { - MemoryManagerClose(NULL); - return 0; - } - if (!MsgReadConfiguration()) { XplConsolePrintf("Cannot read configuration. Shutting down.\n"); @@ -2206,7 +576,6 @@ MsgLibraryInit(void) return(0); } - MsgResolveStart(); MsgLibraryStart(); MsgDateStart(); @@ -2232,7 +601,6 @@ MsgLibraryShutdown(void) oldGid = XplSetThreadGroupID(MsgGlobal.groupID); - MsgResolveStop(); MsgLibraryStop(); MemoryManagerClose(NULL); @@ -2245,52 +613,6 @@ MsgLibraryShutdown(void) return; } -MDBHandle -MsgDirectoryHandle(void) -{ - return(MsgGlobal.directoryHandle); -} - -BOOL -MsgResolveStart(void) -{ - MDBValueStruct *config; - unsigned long i; - - if (!XplResolveStart()) { - return FALSE; - } - - config = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - if (MDBRead(MsgGetServerDN(NULL), MSGSRV_A_RESOLVER, config) > 0) { - for (i = 0; i < config->Used; i++) { - XplDnsAddResolver(config->Value[i]); -/* XplConsolePrintf("[%04d] MSGSRV_A_RESOLVER:%s", __LINE__, config->Value[i]);*/ - } - } else { - MDBSetValueStructContext(MsgGetServerDN(NULL), config); - if (MDBRead(MSGSRV_AGENT_SMTP, MSGSRV_A_RESOLVER, config)>0) { - for (i = 0; i < config->Used; i++) { - XplDnsAddResolver(config->Value[i]); -/* XplConsolePrintf("[%04d] MSGSRV_A_RESOLVER:%s", __LINE__, config->Value[i]);*/ - } - MDBSetValueStructContext(NULL, config); - MDBWrite(MsgGetServerDN(NULL), MSGSRV_A_RESOLVER, config); - } - } - MDBDestroyValueStruct(config); - - return(TRUE); -} - -BOOL -MsgResolveStop(void) -{ - return XplResolveStop(); -} - - - BOOL MsgExiting(void) { @@ -2315,15 +637,13 @@ MsgShutdown(void) return(TRUE); } -EXPORT MDBHandle +EXPORT void MsgInit(void) { if (MSGAPIState == LIBRARY_LOADED) { MSGAPIState = LIBRARY_INITIALIZING; - if (!MsgLibraryInit()) { - return NULL; - } + if (!MsgLibraryInit()) return; } while (MSGAPIState < LIBRARY_RUNNING) { @@ -2333,6 +653,106 @@ MsgInit(void) if (MSGAPIState == LIBRARY_RUNNING) { XplSafeIncrement(MsgGlobal.useCount); } - - return((MSGAPIState == LIBRARY_RUNNING) ? MsgGlobal.directoryHandle : NULL); +} + +void +MsgRecoveryFlagFile(char *agent, char *buffer, size_t buffer_len) +{ + snprintf(buffer, buffer_len - 1, "%s/%s.pid", XPL_DEFAULT_WORK_DIR, agent); +} + +EXPORT BOOL +MsgSetRecoveryFlag(unsigned char *agent_name) +{ + FILE *flag; + unsigned char flagfile[XPL_MAX_PATH]; + unsigned char pidstr[20]; + + MsgRecoveryFlagFile(agent_name, flagfile, XPL_MAX_PATH); + + flag = fopen(flagfile, "w"); + if (flag == NULL) { + return FALSE; + } + + snprintf(pidstr, 18, "%u\n", getpid()); + fwrite(pidstr, strlen(pidstr), sizeof(unsigned char), flag); + + fclose(flag); + + return TRUE; +} + +EXPORT BOOL +MsgGetRecoveryFlag(unsigned char *agent_name) +{ + unsigned char flagfile[XPL_MAX_PATH]; + struct stat filestat; + + MsgRecoveryFlagFile(agent_name, flagfile, XPL_MAX_PATH); + if (stat(flagfile, &filestat) == 0) { + return TRUE; + } else { + return FALSE; + } +} + +EXPORT BOOL +MsgClearRecoveryFlag(unsigned char *agent_name) +{ + unsigned char flagfile[XPL_MAX_PATH]; + + MsgRecoveryFlagFile(agent_name, flagfile, XPL_MAX_PATH); + unlink(flagfile); + return TRUE; +} + +EXPORT BOOL +MsgGetServerCredential(char *buffer) +{ + unsigned char credential[4097]; + unsigned char file[120]; + FILE *credfile; + + memset(credential, 0, sizeof(credential)); + + sprintf(file, "%s/credential.dat", XPL_DEFAULT_DBF_DIR); + credfile = fopen(file, "rb"); + if (credfile) { + fread(credential, sizeof(unsigned char), sizeof(credential), credfile); + fclose(credfile); + credfile = NULL; + HashCredential(credential, buffer); + return TRUE; + } + return FALSE; +} + +EXPORT BOOL +MsgSetServerCredential() +{ + unsigned char credential[4097]; + unsigned char path[XPL_MAX_PATH]; + FILE *credfile; + const char *posschars = + "abcdefghijlkmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWYXZ" + "0123456890"; + int i, range; + + range = strlen(posschars); + for (i=0; i<4097; i++) { + int ran = rand() % range; + credential[i] = posschars[ran]; + } + credential[4096] = '\0'; + + snprintf(path, XPL_MAX_PATH, "%s/credential.dat", XPL_DEFAULT_DBF_DIR); + credfile = fopen(path, "wb"); + if (credfile) { + fwrite(credential, sizeof(char), sizeof(credential), credfile); + fclose(credfile); + return TRUE; + } + return FALSE; } diff --git a/src/libs/msgapi/msgapip.h b/src/libs/msgapi/msgapip.h index c852531..32c5af3 100644 --- a/src/libs/msgapi/msgapip.h +++ b/src/libs/msgapi/msgapip.h @@ -23,22 +23,15 @@ #define MSGAPIP_H #include -#include #include /* msgapi.c */ -int MsgGetParentAttribute(const unsigned char *userDn, unsigned char *attribute, MDBValueStruct *v); -BOOL MsgGetUserSettingsContainerDN(const unsigned char *userDn, unsigned char *containerDn, MDBValueStruct *v, BOOL create); -MDBHandle MsgDirectoryHandle(void); BOOL MsgExiting(void); /* msgdate.c */ void MsgDateSetUTCOffset(long offset); BOOL MsgDateStart(void); -/* resolver.c */ -BOOL MsgResolveStart(void); -BOOL MsgResolveStop(void); #endif /* MSGAPIP_H */ diff --git a/src/libs/msgapi/msgauth.c b/src/libs/msgapi/msgauth.c new file mode 100644 index 0000000..30c24eb --- /dev/null +++ b/src/libs/msgapi/msgauth.c @@ -0,0 +1,266 @@ +/* Bongo Project licensing applies to this file, see COPYING + * (C) 2007 Alex Hudson + */ + +/** \file + * User authentication API + */ + +#include +#include +#include +#include + +#define LOGGERNAME "msgauth" +#include + +#include "plugin-api.h" + +// returns 0 on success +int +MsgAuthLoadBackend(const char *name, const char *file) +{ + char path[XPL_MAX_PATH]; + XplPluginHandle *auth; + char function[101]; + AuthPlugin_InterfaceVersion *version_func; + AuthPlugin_Init *init_func; + MsgAuthAPIFunction *func; + + snprintf(path, XPL_MAX_PATH, "%s/bongo-auth/%s", XPL_DEFAULT_LIB_DIR, file); + auth = XplLoadDLL(path); + if (! auth) { + Log(LOG_FATAL, "Unable to load auth backend '%s'", file); + return 1; + } + + func = &pluginapi[0]; + while (func->name) { + snprintf(function, 100, "%s_%s", name, func->name); + dlerror(); + func->func = dlsym(auth, function); + // XplGetDLLFunction("foo", function, auth); + if (! dlerror()) { + func->available = TRUE; + } else { + func->available = FALSE; + if (! func->optional) { + Log(LOG_ERROR, "Non-optional API call %s missing in backend %s", + func->name, file); + goto fail; + } + } + func++; + } + + func = &pluginapi[Func_InterfaceVersion]; + if (func->available) { + int ver; + version_func = (AuthPlugin_InterfaceVersion *)&func->func; + ver = (*version_func)(); + if (ver >= 2) { + // too new for us. + Log(LOG_ERROR, "Auth backend %s implements version %d, we want %d", + ver, 1); + return 2; + } + } + + /* check if backend needs to be initialized */ + func = &pluginapi[Func_Init]; + if (func->available) { + Log(LOG_INFO, "Initializing authentication backend"); + init_func = (AuthPlugin_Init *)&func->func; + if ((*init_func)()) { + Log(LOG_FATAL, "Couldn't initialize authentication backend"); + goto fail; + } + } + + return 0; + +fail: + // XplUnloadDLL(auth); + return 3; +} + +int +MsgAuthInit(void) +{ + //return MsgAuthLoadBackend("AuthODBC", "libauthodbc.so"); + return MsgAuthLoadBackend("AuthSqlite", "libauthsqlite3.so"); +} + +/* returns 0 on success */ +int +MsgAuthInitDB(void) +{ + return 0; +} + +int +MsgAuthInstall(void) +{ + MsgAuthAPIFunction *function; + AuthPlugin_Install *f; + + function = &pluginapi[Func_Install]; + if (! function->available) return 1; + + f = (AuthPlugin_Install *)&function->func; + return (*f)(); +} + +/** + * Determine whether or not a user exists in our user database + * SECURITY: We don't want to disclose this to unknown people + * Do we need this function? Often gets called before trying a + * password, which is unnecessary - might be this can be removed. + * This an MsgAuthVerifyPassword() are basically the same. + * \param user The username to check + * \return Whether or not the user exists + */ +int +MsgAuthFindUser(const char *user) +{ + MsgAuthAPIFunction *function; + AuthPlugin_FindUser *f; + int result; + + function = &pluginapi[Func_FindUser]; + if (! function->available) return FALSE; + + f = (AuthPlugin_FindUser *)&function->func; + result = (*f)(user); + return result; +} + +/** + * Verify that the password we're given actually belongs to the user + * \param user User whose password we're checking + * \param password The password we're giving + * \return Whether or not the username matches the password + */ +int +MsgAuthVerifyPassword(const char *user, const char *password) +{ + MsgAuthAPIFunction *function; + AuthPlugin_VerifyPassword *f; + int result; + + function = &pluginapi[Func_VerifyPassword]; + if (! function->available) return FALSE; + + f = (AuthPlugin_VerifyPassword *)&function->func; + result = (*f)(user, password); + return result; +} + +/* "Write" functions below */ + +/** + * Add a user to the database. + * \param user Username to add + * \return True if the addition was successful + */ +int +MsgAuthAddUser(const char *user) +{ + MsgAuthAPIFunction *function; + AuthPlugin_AddUser *f; + int result; + + function = &pluginapi[Func_AddUser]; + if (! function->available) return FALSE; + + f = (AuthPlugin_AddUser *)&function->func; + result = (*f)(user); + return result; +} + +/** + * Change the user's password from an old one to a new one + * \param user User whose password we're resetting + * \param oldpassword Their old password + * \param newpassword The new password we want to have + * \return Whether or not we successfully changed the password + */ +int +MsgAuthChangePassword(const char *user, const char *oldpassword, const char *newpassword) +{ + MsgAuthAPIFunction *function; + AuthPlugin_ChangePassword *f; + int result; + + function = &pluginapi[Func_ChangePassword]; + if (function->available) { + f = (AuthPlugin_ChangePassword *)&function->func; + result = (*f)(user, oldpassword, newpassword); + return result; + } else { + if (! MsgAuthVerifyPassword(user, oldpassword)) return FALSE; + + return MsgAuthSetPassword(user, newpassword); + } +} + +/** + * Set the user's password. SECURITY: We should make sure we're + * authorised to do this. + * \param user User whose password we're setting. + * \param password New password we want to set + * \return Whether or not the password got changed + */ +int +MsgAuthSetPassword(const char *user, const char *password) +{ + MsgAuthAPIFunction *function; + AuthPlugin_SetPassword *f; + int result; + + function = &pluginapi[Func_SetPassword]; + if (! function->available) return FALSE; + + f = (AuthPlugin_SetPassword *)&function->func; + result = (*f)(user, password); + return result; +} + +/** + * Find the IP address of the user's store + * \param user User whose store we want + * \param store Structure we can write the connection info to + * \return Whether this was successful + */ +int +MsgAuthGetUserStore(const char *user, struct sockaddr_in *store) +{ + MsgAuthAPIFunction *function; + AuthPlugin_GetUserStore *f; + int result; + + function = &pluginapi[Func_GetUserStore]; + if (function->available) { + f = (AuthPlugin_GetUserStore *)&function->func; + result = (*f)(user, store); + } else { + memset(store, 0, sizeof(store)); + store->sin_addr.s_addr = inet_addr("127.0.0.1"); + store->sin_family = AF_INET; + store->sin_port = htons(689); + result = 0; + } + return result; +} + +/** + * Get a complete list of usernames on the system + * \param list A pointer we will set to the BongoArray of users + * \return Whether this was successful + */ +int +MsgAuthUserList(BongoArray **list) +{ + return -1; +} + diff --git a/src/libs/msgapi/msgcollector.c b/src/libs/msgapi/msgcollector.c index 222a1c2..75f8202 100644 --- a/src/libs/msgapi/msgcollector.c +++ b/src/libs/msgapi/msgcollector.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -129,17 +128,11 @@ static Connection * ConnectToStore(const char *user) { char buffer[CONN_BUFSIZE + 1]; - char dn[MDB_MAX_OBJECT_CHARS + 1]; struct sockaddr_in addr; Connection *conn; int ret; - if (!MsgFindObject(user, dn, NULL, &addr, NULL)) { - printf("bongocollector: couldn't find user object for '%s'\n", user); - return NULL; - } - - if ((conn = NMAPConnect(NULL, &addr)) == NULL) { + if ((conn = NMAPConnect("127.0.0.1", NULL)) == NULL) { printf("bongocollector: couldn't connect to nmap\n"); return NULL; } @@ -661,31 +654,18 @@ MsgCollectUser(const char *user) void MsgCollectAllUsers(void) { - MDBValueStruct *vs; - MDBEnumStruct *es; - const unsigned char *name; - char context[MDB_MAX_OBJECT_CHARS + 1]; + BongoArray *users; + int i; - vs = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - if (!vs) { + if (MsgAuthUserList(&users) < 0) return; + + for(i = 0; i < BongoArrayCount(users); i++) { + char *user = BongoArrayIndex(users, char *, i); + MsgCollectUser(user); } - es = MDBCreateEnumStruct(vs); - if (!es) { - MDBDestroyValueStruct(vs); - return; - } - - if (MsgGetConfigProperty(context, MSGSRV_CONFIG_PROP_DEFAULT_CONTEXT)) { - while ((name = MDBEnumerateObjectsEx(context, C_USER, NULL, 0, es, vs)) != NULL) { - unsigned char *user = strrchr(name, '\\'); - MsgCollectUser(user ? user + 1 : name); - } - } - - MDBDestroyEnumStruct(es, vs); - MDBDestroyValueStruct(vs); + BongoArrayFree(users, TRUE); } size_t diff --git a/src/libs/msgapi/msgdate.c b/src/libs/msgapi/msgdate.c index c36ba90..c085ff3 100644 --- a/src/libs/msgapi/msgdate.c +++ b/src/libs/msgapi/msgdate.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/src/libs/msgapi/plugin-api.h b/src/libs/msgapi/plugin-api.h new file mode 100644 index 0000000..9e903ae --- /dev/null +++ b/src/libs/msgapi/plugin-api.h @@ -0,0 +1,45 @@ +// Plugin API definition + +typedef struct { + BOOL available; + BOOL optional; + const char *name; + void *func; +} MsgAuthAPIFunction; + +typedef int (* AuthPlugin_InterfaceVersion)(void); +typedef int (* AuthPlugin_FindUser)(const char *user); +typedef int (* AuthPlugin_VerifyPassword)(const char *user, const char *password); +typedef int (* AuthPlugin_AddUser)(const char *user); +typedef int (* AuthPlugin_ChangePassword)(const char *user, const char *oldpassword, const char *newpassword); +typedef int (* AuthPlugin_SetPassword)(const char *user, const char *password); +typedef int (* AuthPlugin_GetUserStore)(const char *user, struct sockaddr_in *store); +typedef int (* AuthPlugin_Install)(void); +typedef int (* AuthPlugin_Init)(void); + +enum { + Func_InterfaceVersion = 0, + Func_FindUser = 1, + Func_UserList = 2, + Func_VerifyPassword = 3, + Func_AddUser = 4, + Func_ChangePassword = 5, + Func_SetPassword = 6, + Func_GetUserStore = 7, + Func_Install = 8, + Func_Init = 9 +}; + +static MsgAuthAPIFunction pluginapi[] = { + {0, 0, "InterfaceVersion", NULL}, + {0, 0, "FindUser", NULL}, + {0, 0, "UserList", NULL}, + {0, 0, "VerifyPassword", NULL}, + {0, 1, "AddUser", NULL}, + {0, 1, "ChangePassword", NULL}, + {0, 0, "SetPassword", NULL}, + {0, 1, "GetUserStore", NULL}, + {0, 0, "Install", NULL}, + {0, 1, "Init", NULL}, + {0, 0, NULL, NULL} +}; diff --git a/src/libs/msgapi/sqldb.c b/src/libs/msgapi/sqldb.c new file mode 100644 index 0000000..bfa6c63 --- /dev/null +++ b/src/libs/msgapi/sqldb.c @@ -0,0 +1,300 @@ +/* Bongo Project licensing applies to this file, see COPYING + * (C) 2006 Novell + * (C) 2007 Alex Hudson + */ + +/** \file + * SQLite Helper API + */ + +/* This code all adapted from the Store, but made generic. + * Eventually, the store should probably use this + */ + +#include +#include +#include + +MsgSQLHandle * +MsgSQLOpen(char *path, BongoMemStack *memstack, int locktimeoutms) +{ + MsgSQLHandle *handle = NULL; + int create = 0; + + create = access(path, 0); + + if (!(handle = MemMalloc(sizeof(MsgSQLHandle))) || + memset(handle, 0, sizeof(MsgSQLHandle)), 0 || + SQLITE_OK != sqlite3_open(path, &handle->db)) { + // FIXME Logging + XplConsolePrintf("msgapi: Failed to open database \"%s\".\r\n", path); + goto fail; + } + + handle->memstack = memstack; + handle->lockTimeoutMs = locktimeoutms; + +// FIXME +/* if (create && DStoreCreateDB(handle)) { + printf("Couldn't open db"); + goto fail; + } + + if (UpgradeDB(handle)) { + goto fail; + } +*/ + return handle; + +fail: + if (handle) { + if (handle->db) { + sqlite3_close(handle->db); + } + + MemFree(handle); + } + return NULL; +} + +void +MsgSQLClose(MsgSQLHandle *handle) +{ + MsgSQLReset(handle); + if (SQLITE_BUSY == sqlite3_close(handle->db)) { + // FIXME logging + XplConsolePrintf ("msgapi: couldn't close database\r\n"); + } + + MemFree(handle); +} + +void +MsgSQLFinalize(MsgSQLStatement *stmt) +{ + if (stmt->stmt) { + sqlite3_finalize(stmt->stmt); + stmt->stmt = NULL; + } +} + +void +MsgSQLReset(MsgSQLHandle *handle) +{ + MsgSQLStatement *stmt; + + for (stmt = &handle->stmts.begin; + stmt <= &handle->stmts.end; + stmt++) + { + if (stmt->stmt) { + sqlite3_finalize(stmt->stmt); + stmt->stmt = NULL; + } + } +} + +BongoMemStack * +MsgSQLGetMemStack(MsgSQLHandle *handle) +{ + return handle->memstack; +} + +void +MsgSQLSetMemStack(MsgSQLHandle *handle, BongoMemStack *memstack) +{ + handle->memstack = memstack; +} + + +void +MsgSQLSetLockTimeout(MsgSQLHandle *handle, int timeoutms) +{ + handle->lockTimeoutMs = timeoutms; +} + +// returns 0 on success, -2 db busy, -1 on error +int +MsgSQLBeginTransaction(MsgSQLHandle *handle) +{ + MsgSQLStatement *stmt; + int result; + int count = 1 + handle->lockTimeoutMs / MSGSQL_STMT_SLEEP_MS; + + if (handle->transactionDepth) { + /* FIXME: ensure it's an exclusive transaction */ + abort (); + return 0; + } + + stmt = MsgSQLPrepare(handle, "BEGIN EXCLUSIVE TRANSACTION;", &handle->stmts.begin); + if (!stmt) { + //DStoreStmtError(handle, stmt); + return -1; + } + + do { + result = sqlite3_step(stmt->stmt); + sqlite3_reset(stmt->stmt); + } while (SQLITE_BUSY == result && --count && (XplDelay(MSGSQL_STMT_SLEEP_MS), 1)); + + switch (result) { + case SQLITE_DONE: + ++handle->transactionDepth; + return 0; + case SQLITE_BUSY: + return -2; + default: + //DStoreStmtError(handle, stmt); + return -1; + } +} + +// returns 0 on success, -1 on error +int +MsgSQLCommitTransaction(MsgSQLHandle *handle) +{ + MsgSQLStatement *stmt; + int result; + int count = 1 + handle->lockTimeoutMs / MSGSQL_STMT_SLEEP_MS; + + stmt = MsgSQLPrepare(handle, "END TRANSACTION;", &handle->stmts.end); + if (!stmt) { + // DStoreStmtError(handle, stmt); + return -1; + } + + do { + result = sqlite3_step(stmt->stmt); + sqlite3_reset(stmt->stmt); + } while (SQLITE_BUSY == result && --count && (XplDelay(MSGSQL_STMT_SLEEP_MS), 1)); + + --handle->transactionDepth; + + if (SQLITE_DONE != result) { + // DStoreStmtError(handle, stmt); + return -1; + } + return 0; +} + +// returns 0 on success, -1 on error +int +MsgSQLAbortTransaction(MsgSQLHandle *handle) +{ + MsgSQLStatement *stmt; + int result; + + stmt = MsgSQLPrepare(handle, "ROLLBACK TRANSACTION;", &handle->stmts.abort); + if (!stmt) { + // DStoreStmtError(handle, stmt); + return -1; + } + + result = sqlite3_step(stmt->stmt); + if (SQLITE_DONE != result) { + // DStoreStmtError(handle, stmt); + } + sqlite3_reset(stmt->stmt); + --handle->transactionDepth; + return SQLITE_DONE == result ? 0 : -1; +} + +int +MsgSQLCancelTransactions(MsgSQLHandle *handle) +{ + while (handle->transactionDepth) { + if (MsgSQLAbortTransaction(handle)) { + return -1; + } + } + return 0; +} + +MsgSQLStatement * +MsgSQLPrepare(MsgSQLHandle *handle, const char *statement, MsgSQLStatement *stmt) +{ + int count = 1 + handle->lockTimeoutMs / MSGSQL_STMT_SLEEP_MS; + + // stmt->filter = NULL; + if (stmt->stmt) { + return stmt; + } + + while (count--) { + switch (sqlite3_prepare(handle->db, statement, -1, &stmt->stmt, NULL)) { + case SQLITE_OK: + return stmt; + case SQLITE_BUSY: + XplDelay(MSGSQL_STMT_SLEEP_MS); + continue; + default: + // FIXME: should be logging here. + XplConsolePrintf("SQL Prepare statement \"%s\" failed; %s\r\n", + statement, sqlite3_errmsg(handle->db)); + return NULL; + } + } + + return NULL; +} + +int +MsgSQLBindString(MsgSQLStatement *stmt, int var, const char *str, BOOL nullify) +{ + if (str) { + return sqlite3_bind_text(stmt->stmt, var, str, strlen(str), SQLITE_STATIC); + } else { + if (nullify) { + return sqlite3_bind_null(stmt->stmt, var); + } else { + return sqlite3_bind_text(stmt->stmt, var, "", 0, SQLITE_STATIC); + } + } +} + +int +MsgSQLExecute(MsgSQLHandle *handle, MsgSQLStatement *_stmt) +{ + + sqlite3_stmt *stmt = _stmt->stmt; + int result; + + result = sqlite3_step(stmt); + if (SQLITE_DONE == result) { + return 0; + } else { + XplConsolePrintf("Sql (%d): %s\r\n", result, sqlite3_errmsg(handle->db)); + return -1; + } +} + +int +MsgSQLResults(MsgSQLHandle *handle, MsgSQLStatement *_stmt) +{ + sqlite3_stmt *stmt = _stmt->stmt; + int result; + int count = 1 + handle->lockTimeoutMs / MSGSQL_STMT_SLEEP_MS; + + while (count--) { + result = sqlite3_step(stmt); + switch (result) { + case SQLITE_DONE: + return 0; // no more results + break; + case SQLITE_ROW: + return 1; + break; + case SQLITE_BUSY: + XplDelay(MSGSQL_STMT_SLEEP_MS); + continue; + default: + // FIXME + //XplConsolePrintf("SQL Prepare statement \"%s\" failed; %s\r\n", + // statement, sqlite3_errmsg(handle->db)); + return -1; + } + } + + return -1; +} diff --git a/src/libs/nmap/Bongo.rules b/src/libs/nmap/Bongo.rules index cee3e5f..2737646 100644 --- a/src/libs/nmap/Bongo.rules +++ b/src/libs/nmap/Bongo.rules @@ -1,14 +1,14 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongonmap.la -#libbongonmap_la_LDFLAGS := -static -libbongonmap_la_SOURCES := \ +#libbongonmap_la_LDFLAGS = -static +libbongonmap_la_SOURCES = \ src/libs/nmap/bongoagent.c \ src/libs/nmap/nmap.c \ src/libs/nmap/hashcred.c \ src/libs/nmap/mime.c -libbongonmap_la_LIBADD := \ +libbongonmap_la_LIBADD = \ libbongologger.la \ libbongocal.la \ libbongostreamio.la \ diff --git a/src/libs/nmap/bongoagent.c b/src/libs/nmap/bongoagent.c index 66b99bb..9722a98 100644 --- a/src/libs/nmap/bongoagent.c +++ b/src/libs/nmap/bongoagent.c @@ -34,6 +34,8 @@ #define MONITOR_SLEEP_INTERVAL 5000 +struct _BongoGlobals BongoGlobals; + void BongoAgentHandleSignal(BongoAgent *agent, int sigtype) @@ -204,8 +206,8 @@ SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node) { } /** - * Read a configuration document from the Bongo Store, and bring information - * from that document into the agent + * Read a configuration document from the Bongo Store. This is a conveniance wrapper + * around ParseBongoConfiguration() * \param config BongoConfigItem array which defines configuration variables * \param filename Filename we wish to read from the store * \return Whether or not we were successful @@ -214,37 +216,47 @@ SetBongoConfigItem(BongoConfigItem *schema, BongoJsonNode *node) { BOOL ReadBongoConfiguration(BongoConfigItem *config, char *filename) { unsigned char *pconfig; - BOOL retcode = FALSE; BongoJsonNode *node = NULL; + BOOL retcode; if (! NMAPReadConfigFile(filename, &pconfig)) { XplConsolePrintf("config: couldn't read config '%s' from store\r\n", filename); return FALSE; } - if (BongoJsonParseString(pconfig, &node) != BONGO_JSON_OK) { - XplConsolePrintf("config: couldn't parse JSON content in '%s'\r\n", filename); - goto finish; + retcode = FALSE; + } else { + retcode = ProcessBongoConfiguration(config, node); } + if (node) BongoJsonNodeFree(node); + return retcode; +} + +/** + * Process a configuration definition + * \param config BongoConfigItem array which defines configuration variables + * \param JSON node tree we want to look in + * \return Whether or not we were successful + */ + +BOOL +ProcessBongoConfiguration(BongoConfigItem *config, const BongoJsonNode *node) +{ while (config->type != BONGO_JSON_NULL) { BongoJsonNode *result = BongoJsonJPath(node, config->source); if (!result) { XplConsolePrintf("config: JSON tree for schema source %s not found\r\n", config->source); - goto finish; + return FALSE; } if (!SetBongoConfigItem(config, result)) { - // can't set item + // can't set item - should return FALSE here? XplConsolePrintf("config: schema source %s not found\r\n", config->source); } config++; } - retcode = TRUE; - -finish: - if (node) BongoJsonNodeFree(node); - return retcode; + return TRUE; } int @@ -264,18 +276,17 @@ BongoAgentInit(BongoAgent *agent, if (startupResources & BA_STARTUP_CONNIO) ConnStartup(timeOut, TRUE); - if (startupResources & BA_STARTUP_MDB) { - MDBInit(); - - agent->directoryHandle = (MDBHandle)MsgInit(); - if (agent->directoryHandle == NULL) { - XplConsolePrintf("%s: Invalid directory credentials; exiting!\r\n", agentName); - MemoryManagerClose(agentDn); - return -1; + if (startupResources & BA_STARTUP_MSGLIB) { + MsgInit(); + if (startupResources & BA_STARTUP_MSGAUTH) { + if (MsgAuthInit()) { + XplConsolePrintf("%s: Could not initialize auth subsystem\r\n", agentName); + return -1; + } } } - if ((startupResources & BA_STARTUP_NMAP) && !NMAPInitialize(agent->directoryHandle)) { + if ((startupResources & BA_STARTUP_NMAP) && !NMAPInitialize()) { XplConsolePrintf("%s: Could not initialize nmap library\r\n", agentName); return -1; } else { @@ -283,9 +294,6 @@ BongoAgentInit(BongoAgent *agent, NMAPSetEncryption(agent->sslContext); } - SetCurrentNameSpace(NWOS2_NAME_SPACE); - SetTargetNameSpace(NWOS2_NAME_SPACE); - if (startupResources & BA_STARTUP_LOGGER) { agent->loggingHandle = LoggerOpen(agentDn); if (!agent->loggingHandle) { @@ -294,12 +302,7 @@ BongoAgentInit(BongoAgent *agent, } agent->name = MemStrdup(agentName); - agent->dn = MemStrdup(agentDn); - - if (startupResources & BA_STARTUP_MDB) { - /* Read general agent configuration */ - ReadConfiguration(agent); - } + // agent->dn = MemStrdup(agentDn); CONN_TRACE_INIT((char *)MsgGetWorkDir(NULL), agentName); return 0; @@ -615,7 +618,7 @@ BongoQueueConnectionInit(BongoAgent *agent, return NULL; } - reg = NMAPRegister(agent->dn, + reg = QueueRegister(agent->dn, queue, conn->socketAddress.sin_port); diff --git a/src/libs/nmap/nmap.c b/src/libs/nmap/nmap.c index 1d3fa62..294a32d 100644 --- a/src/libs/nmap/nmap.c +++ b/src/libs/nmap/nmap.c @@ -39,8 +39,6 @@ struct { unsigned char access[NMAP_HASH_SIZE]; - MDBHandle directoryHandle; - bongo_ssl_context *context; BOOL debug; @@ -48,7 +46,6 @@ struct { REGISTRATION_LOADING, { '\0' }, NULL, - NULL, FALSE }; @@ -129,7 +126,7 @@ FindEndOfLine(Connection *conn) if (count < CONN_TCP_MTU) { if (count == 0) { - CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count); + ConnTcpRead(c, c->receive.buffer, CONN_TCP_MTU, &count); if (count > 0) { c->receive.read = c->receive.buffer; c->receive.write = c->receive.buffer + count; @@ -146,7 +143,7 @@ FindEndOfLine(Connection *conn) c->receive.read = c->receive.buffer; c->receive.write = c->receive.buffer + count; c->receive.remaining = CONN_TCP_MTU - count; - CONN_TCP_RECEIVE(c, c->receive.write, c->receive.remaining, count); + ConnTcpRead(c, c->receive.write, c->receive.remaining, &count); if (count > 0) { c->receive.write += count; c->receive.remaining -= count; @@ -1309,7 +1306,7 @@ NMAPReadConfigFile(const unsigned char *file, unsigned char **output) goto nmapfinish; } - *output = malloc(sizeof(unsigned char) * (count+1)); + *output = MemMalloc(sizeof(unsigned char) * (count+1)); written = NMAPReadCount(conn, *output, count); NMAPReadCrLf(conn); if (written != count) { @@ -1608,13 +1605,13 @@ NMAPQuit(Connection *conn) { ConnWrite(conn, "QUIT\r\n", 6); - CONN_TCP_CLOSE(conn); + ConnTcpClose(conn); return; } __inline static RegistrationStates -RegisterWithQueueServer(char *queueServerIpAddress, unsigned short queueServerPort, unsigned long queueNumber, const char *queueAgentServerDn, const char *queueAgentCn, unsigned long queueAgentPort) +RegisterWithQueueServer(char *queueServerIpAddress, unsigned short queueServerPort, unsigned long queueNumber, const char *queueAgentCn, unsigned long queueAgentPort) { unsigned long j; Connection *conn = NULL; @@ -1636,7 +1633,7 @@ RegisterWithQueueServer(char *queueServerIpAddress, unsigned short queueServerPo if (NMAPLibrary.state == REGISTRATION_REGISTERING) { if (NMAPAuthenticate(conn, response, CONN_BUFSIZE)) { - if (ConnWriteF(conn, "QWAIT %lu %d %s%s%lu\r\n", queueNumber, ntohs(queueAgentPort), queueAgentServerDn, queueAgentCn, queueNumber) > 0) { + if (ConnWriteF(conn, "QWAIT %lu %d %s %lu\r\n", queueNumber, ntohs(queueAgentPort), queueAgentCn, queueNumber) > 0) { if (ConnFlush(conn) > -1) { if (NMAPReadAnswer(conn, response, CONN_BUFSIZE, TRUE) == 1000) { NMAPLibrary.state = REGISTRATION_COMPLETED; @@ -1656,14 +1653,8 @@ RegisterWithQueueServer(char *queueServerIpAddress, unsigned short queueServerPo } RegistrationStates -NMAPRegister(const unsigned char *queueAgentCn, unsigned long queueNumber, unsigned short queueAgentPort) +QueueRegister(const unsigned char *queueAgentCn, unsigned long queueNumber, unsigned short queueAgentPort) { - unsigned long i; - MDBValueStruct *queueServerDns = NULL; - MDBValueStruct *details = NULL; - unsigned short queueServerPort; - char *ptr; - if (!queueAgentCn) { NMAPLibrary.state = REGISTRATION_FAILED; return(NMAPLibrary.state); @@ -1671,59 +1662,10 @@ NMAPRegister(const unsigned char *queueAgentCn, unsigned long queueNumber, unsig NMAPLibrary.state = REGISTRATION_ALLOCATING; - queueServerDns = MDBCreateValueStruct(NMAPLibrary.directoryHandle, MsgGetServerDN(NULL)); - if (queueServerDns == NULL) { - NMAPLibrary.state = REGISTRATION_FAILED; - return(NMAPLibrary.state); - } - - MDBReadDN(queueAgentCn, MSGSRV_A_MONITORED_QUEUE, queueServerDns); - if ((queueServerDns->Used == 0) || (details = MDBCreateValueStruct(NMAPLibrary.directoryHandle, NULL)) == NULL) { - /* Failed to find a configuration object, use default connection information */ - MDBDestroyValueStruct(queueServerDns); - XplConsolePrintf("Couldn't find configuration object for %s, attempting to connect to NMAP on 127.0.0.1\n", queueAgentCn); - RegisterWithQueueServer("127.0.0.1", BONGO_QUEUE_PORT, queueNumber, MsgGetServerDN(NULL), queueAgentCn, queueAgentPort); - if (NMAPLibrary.state != REGISTRATION_COMPLETED) { - NMAPLibrary.state = REGISTRATION_FAILED; - } - return(NMAPLibrary.state); - } - - NMAPLibrary.state = REGISTRATION_CONNECTING; - - for (i = 0; (i < queueServerDns->Used) && (NMAPLibrary.state == REGISTRATION_CONNECTING); i++) { - /* check for a non-standard port */ - MDBRead(queueServerDns->Value[i], MSGSRV_A_PORT, details); - if (details->Used == 0) { - queueServerPort = BONGO_QUEUE_PORT; - } else { - queueServerPort = (unsigned short)atol(details->Value[0]); - MDBFreeValues(details); - } - - /* find the ip address on the host server object */ - if ((ptr = strrchr(queueServerDns->Value[i], '\\')) != NULL) { - *ptr = '\0'; - MDBRead(queueServerDns->Value[i], MSGSRV_A_IP_ADDRESS, details); - *ptr = '\\'; - } else { - MDBRead(queueServerDns->Value[i], MSGSRV_A_IP_ADDRESS, details); - } - - if (details->Used > 0) { - RegisterWithQueueServer(details->Value[0], queueServerPort, queueNumber, MsgGetServerDN(NULL), queueAgentCn, queueAgentPort); - MDBFreeValues(details); - } else { - RegisterWithQueueServer("127.0.0.1", queueServerPort, queueNumber, MsgGetServerDN(NULL), queueAgentCn, queueAgentPort); - } - } - + RegisterWithQueueServer("127.0.0.1", BONGO_QUEUE_PORT, queueNumber, queueAgentCn, queueAgentPort); if (NMAPLibrary.state != REGISTRATION_COMPLETED) { NMAPLibrary.state = REGISTRATION_FAILED; } - - MDBDestroyValueStruct(queueServerDns); - MDBDestroyValueStruct(details); return(NMAPLibrary.state); } @@ -1740,33 +1682,18 @@ NMAPSSLContextAlloc(void) { ConnSSLConfiguration config; - config.certificate.file = MsgGetTLSCertPath(NULL); + config.certificate.file = MsgGetFile(MSGAPI_FILE_PUBKEY, NULL, 0); + config.key.file = MsgGetFile(MSGAPI_FILE_PRIVKEY, NULL, 0); + config.key.type = GNUTLS_X509_FMT_PEM; - config.key.file = MsgGetTLSKeyPath(NULL); return ConnSSLContextAlloc(&config); } BOOL -NMAPInitialize(MDBHandle directoryHandle) +NMAPInitialize(void) { - BOOL result = FALSE; - MDBValueStruct *v; - - if (directoryHandle) { - NMAPLibrary.directoryHandle = directoryHandle; - - v = MDBCreateValueStruct(NMAPLibrary.directoryHandle, NULL); - if (v) { - MDBRead(MSGSRV_ROOT, MSGSRV_A_ACL, v); - if (v->Used) { - result = HashCredential(MsgGetServerDN(NULL), v->Value[0], NMAPLibrary.access); - } - - MDBDestroyValueStruct(v); - - } - } - - return(result); + // single cred for both store and queue atm... + MsgGetServerCredential(NMAPLibrary.access); + return TRUE; } diff --git a/src/libs/python/Bongo.rules b/src/libs/python/Bongo.rules index 4db1d91..51c3031 100644 --- a/src/libs/python/Bongo.rules +++ b/src/libs/python/Bongo.rules @@ -16,7 +16,7 @@ pkgpythonexternalvobjectdir = $(pythondir)/bongo/external/vobject pkgpythonnmapdir = $(pythondir)/bongo/nmap pkgpythonstoredir = $(pythondir)/bongo/store -pkgpython_PYTHON := \ +pkgpython_PYTHON = \ src/libs/python/bongo/__init__.py \ src/libs/python/bongo/CalCmd.py \ src/libs/python/bongo/cmdparse.py \ @@ -29,10 +29,10 @@ pkgpython_PYTHON := \ src/libs/python/bongo/StreamIO.py \ src/libs/python/bongo/table.py -nodist_pkgpython_PYTHON := \ +nodist_pkgpython_PYTHON = \ src/libs/python/bongo/Xpl.py -pkgpythonadmin_PYTHON := \ +pkgpythonadmin_PYTHON = \ src/libs/python/bongo/admin/__init__.py \ src/libs/python/bongo/admin/Addressbook.py \ src/libs/python/bongo/admin/Alias.py \ @@ -60,10 +60,10 @@ pkgpythonadmin_PYTHON := \ src/libs/python/bongo/admin/Webservices.py \ src/libs/python/bongo/admin/bongoutil.py -pkgpythonexternal_PYTHON := \ +pkgpythonexternal_PYTHON = \ src/libs/python/bongo/external/__init__.py -pkgpythonexternaldateutil_PYTHON := \ +pkgpythonexternaldateutil_PYTHON = \ src/libs/python/bongo/external/dateutil/__init__.py \ src/libs/python/bongo/external/dateutil/easter.py \ src/libs/python/bongo/external/dateutil/parser.py \ @@ -72,10 +72,10 @@ pkgpythonexternaldateutil_PYTHON := \ src/libs/python/bongo/external/dateutil/tz.py \ src/libs/python/bongo/external/dateutil/tzwin.py -pkgpythonexternaldateutilzoneinfo_PYTHON := \ +pkgpythonexternaldateutilzoneinfo_PYTHON = \ src/libs/python/bongo/external/dateutil/zoneinfo/__init__.py -pkgpythonexternalemail_PYTHON := \ +pkgpythonexternalemail_PYTHON = \ src/libs/python/bongo/external/email/feedparser.py \ src/libs/python/bongo/external/email/_parseaddr.py \ src/libs/python/bongo/external/email/parser.py \ @@ -93,7 +93,7 @@ pkgpythonexternalemail_PYTHON := \ src/libs/python/bongo/external/email/errors.py \ src/libs/python/bongo/external/email/utils.py -pkgpythonexternalemailmime_PYTHON := \ +pkgpythonexternalemailmime_PYTHON = \ src/libs/python/bongo/external/email/mime/audio.py \ src/libs/python/bongo/external/email/mime/message.py \ src/libs/python/bongo/external/email/mime/nonmultipart.py \ @@ -104,14 +104,14 @@ pkgpythonexternalemailmime_PYTHON := \ src/libs/python/bongo/external/email/mime/__init__.py \ src/libs/python/bongo/external/email/mime/application.py -pkgpythonexternalsimplejson_PYTHON := \ +pkgpythonexternalsimplejson_PYTHON = \ src/libs/python/bongo/external/simplejson/__init__.py \ src/libs/python/bongo/external/simplejson/decoder.py \ src/libs/python/bongo/external/simplejson/encoder.py \ src/libs/python/bongo/external/simplejson/jsonfilter.py \ src/libs/python/bongo/external/simplejson/scanner.py -pkgpythonexternalsimpletal_PYTHON := \ +pkgpythonexternalsimpletal_PYTHON = \ src/libs/python/bongo/external/simpletal/DummyLogger.py \ src/libs/python/bongo/external/simpletal/__init__.py \ src/libs/python/bongo/external/simpletal/simpleElementTree.py \ @@ -122,7 +122,7 @@ pkgpythonexternalsimpletal_PYTHON := \ src/libs/python/bongo/external/simpletal/simpleTALUtils.py -pkgpythonexternalvobject_PYTHON := \ +pkgpythonexternalvobject_PYTHON = \ src/libs/python/bongo/external/vobject/__init__.py \ src/libs/python/bongo/external/vobject/base.py \ src/libs/python/bongo/external/vobject/behavior.py \ @@ -130,14 +130,14 @@ pkgpythonexternalvobject_PYTHON := \ src/libs/python/bongo/external/vobject/vcard.py \ src/libs/python/bongo/external/vobject/win32tz.py -pkgpythonnmap_PYTHON := \ +pkgpythonnmap_PYTHON = \ src/libs/python/bongo/nmap/__init__.py \ src/libs/python/bongo/nmap/CommandStream.py \ src/libs/python/bongo/nmap/NmapClient.py \ src/libs/python/bongo/nmap/NmapConnection.py \ src/libs/python/bongo/nmap/QueueClient.py -pkgpythonstore_PYTHON := \ +pkgpythonstore_PYTHON = \ src/libs/python/bongo/store/__init__.py \ src/libs/python/bongo/store/CommandStream.py \ src/libs/python/bongo/store/QueueClient.py \ @@ -151,9 +151,6 @@ CLEANFILES += \ src/libs/python/bongo/nmap/*.pyc \ src/libs/python/bongoy/store/*.pyc -src/libs/python/bongo/Xpl.py: $(top_builddir)/config.status $(srcdir)/src/libs/python/bongo/Xpl.py.in - cd $(top_builddir) && $(SHELL) ./config.status $@ - src/libs/python/bongo-python-wrapper: $(top_builddir)/config.status $(srcdir)/src/libs/python/bongo-python-wrapper.in cd $(top_builddir) && $(SHELL) ./config.status $@ diff --git a/src/libs/python/bongo/admin/ManagedSlapd.py b/src/libs/python/bongo/admin/ManagedSlapd.py index 43fa5d1..b5446a6 100644 --- a/src/libs/python/bongo/admin/ManagedSlapd.py +++ b/src/libs/python/bongo/admin/ManagedSlapd.py @@ -12,6 +12,7 @@ import signal import socket import string import sys +import tempfile import time from bongo import Xpl, Privs @@ -110,7 +111,7 @@ class ConfigSlapd: "-f", confFile, "-h", "ldap://127.0.0.1:%d" % self.port, "-n", "bongo-slapd"] - if Privs.HaveBongoUser(): + if Xpl.BONGO_USER is not None: args.extend(("-u", Xpl.BONGO_USER)) self.preDaemonize() @@ -152,52 +153,28 @@ class ConfigSlapd: self.slapdPid = None - def initSlapd(self, confFile): - if not os.path.exists(self.binary): - print "Slapd path doesn't exist: %s" % self.binary - return None - - readfd, writefd = os.pipe() - - pid = os.fork() - - if not pid: - Privs.DropPrivs() - os.close(writefd) - os.dup2(readfd, sys.stdin.fileno()) - sys.stdin.close() - - args = ["slapadd", - "-f", confFile] - - os.execv(self.binary, args) - sys.exit(1) - - os.close(readfd) - - os.write(writefd, """\ + def initSlapd(self): + fd, tmpname = tempfile.mkstemp(".ldif") + os.write(fd, """\ dn: %(suffix)s -objectClass: dcObject -objectClass: organization +objectclass: dcObject +objectclass: organization o: Example, Inc. dc: example dn: %(rootdn)s +objectclass: inetOrgPerson +surname: Admin cn: admin -objectClass: inetOrgPerson -sn: Admin -userPassword: %(userpw)s +userpassword: %(userpw)s """ % {"suffix" : self.suffix, "rootdn" : self.rootdn, "userpw" : self.encodePassword("bongo")}) - os.close(writefd) + os.close(fd) - pid, status = os.waitpid(pid, 0) - - if (status >> 8) != 0: - return None - - return pid + os.system("ldapadd -h 127.0.0.1 -p %d -x -D %s -w %s -f %s" % + (self.port, self.rootdn, self.password, tmpname)) + os.unlink(tmpname) def writeSlapdConf(self, file, writeRootpw=True): ldapdir = "%s/ldap" % Xpl.DEFAULT_STATE_DIR @@ -205,10 +182,9 @@ userPassword: %(userpw)s if not os.path.exists(ldapdir): os.makedirs(ldapdir) - Privs.Chown(ldapdir) - - for file in os.listdir(ldapdir): - Privs.Chown(os.path.join(ldapdir, file)) + if Xpl.BONGO_USER is not None: + pw = pwd.getpwnam(Xpl.BONGO_USER) + os.chown(ldapdir, pw[2], pw[3]) config = """\ include %(sysschemadir)s/core.schema diff --git a/src/libs/python/bongo/store/CommandStream.py b/src/libs/python/bongo/store/CommandStream.py index 62556a3..cae6dba 100644 --- a/src/libs/python/bongo/store/CommandStream.py +++ b/src/libs/python/bongo/store/CommandStream.py @@ -6,6 +6,8 @@ __all__ = ["CommandError", "CommandStream", "Item", "ItemIterator", + "Collection", + "CollectionIterator", "MimeItem", "Response", "ResponseIterator"] @@ -36,6 +38,17 @@ class Item: self.props = {} +class Collection: + def __init__(self, response): + ret = re.split(r"(? -#include #include #include @@ -54,7 +53,6 @@ PyMethodDef MsgApiMethods[] = { PyMODINIT_FUNC initbootstrap() { - MDBHandle directoryHandle=NULL; char dbfdir[PATH_MAX]; /* Initialize the various bongo libraries */ @@ -68,7 +66,6 @@ initbootstrap() PyObject *module = Py_InitModule("bootstrap", ModuleMethods); /* Add the Bongo libs */ - AddLibrary(module, "mdb", MdbMethods, MdbEnums); AddLibrary(module, "msgapi", MsgApiMethods, MsgApiEnums); } diff --git a/src/libs/python/libbongo/cal.c b/src/libs/python/libbongo/cal.c index 1cac30d..cf8a449 100644 --- a/src/libs/python/libbongo/cal.c +++ b/src/libs/python/libbongo/cal.c @@ -180,7 +180,8 @@ cal_JsonToIcal(PyObject *self, PyObject *args) if (comp) { PyObject *ret; - ret = Py_BuildValue("s", icalcomponent_as_ical_string(comp)); + char *data = icalcomponent_as_ical_string(comp); + ret = PyUnicode_Decode(data, strlen(data), "utf-8", "strict"); icalcomponent_free(comp); return ret; } else { diff --git a/src/libs/python/libbongo/libs.c b/src/libs/python/libbongo/libs.c index 1f3ad25..69c908b 100644 --- a/src/libs/python/libbongo/libs.c +++ b/src/libs/python/libbongo/libs.c @@ -25,7 +25,6 @@ #include "pybongo.h" #include #include -#include #include #include #include @@ -50,12 +49,11 @@ extern EnumItemDef MsgApiEnums[]; extern PyMethodDef StreamIOMethods[]; extern PyMethodDef BongoJsonMethods[]; extern PyMethodDef BongoUtilMethods[]; - +extern PyMethodDef TestMethods[]; PyMODINIT_FUNC initlibs() { - MDBHandle directoryHandle=NULL; char dbfdir[PATH_MAX]; /* Initialize the various bongo libraries */ @@ -71,22 +69,15 @@ initlibs() return; } - directoryHandle = MsgInit(); - if (!directoryHandle) { - PyErr_SetString(PyExc_ImportError, - "bongo.libs error: MsgInit() failed"); - return; - } + MsgInit(); - MsgGetDBFDir(dbfdir); - - if (!BongoCalInit(dbfdir)) { + if (!BongoCalInit(MsgGetDir(MSGAPI_DIR_DBF, NULL, 0))) { PyErr_SetString(PyExc_ImportError, "bongo.libs error: BongoCalInit() failed"); return; } - if (!NMAPInitialize(directoryHandle)) { + if (!NMAPInitialize()) { PyErr_SetString(PyExc_ImportError, "bongo.libs error: NMAPInitialize() failed"); return; @@ -110,11 +101,11 @@ initlibs() /* Add the Bongo libs */ AddLibrary(module, "cal", CalMethods, NULL); AddLibrary(module, "calcmd", CalCmdMethods, CalCmdEnums); - AddLibrary(module, "mdb", MdbMethods, MdbEnums); - AddLibrary(module, "msgapi", MsgApiMethods, MsgApiEnums); + AddLibrary(module, "msgapi", MsgApiMethods, NULL); AddLibrary(module, "streamio", StreamIOMethods, NULL); AddLibrary(module, "bongojson", BongoJsonMethods, NULL); AddLibrary(module, "bongoutil", BongoUtilMethods, NULL); + AddLibrary(module, "tests", TestMethods, NULL); BongoJsonPostInit(module); BongoCalPostInit(module); diff --git a/src/libs/python/libbongo/msgapi-defs.c b/src/libs/python/libbongo/msgapi-defs.c index a295828..f61e037 100644 --- a/src/libs/python/libbongo/msgapi-defs.c +++ b/src/libs/python/libbongo/msgapi-defs.c @@ -1,294 +1,8 @@ #include #include "msgapi-defs.h" -PyObject * -msgapi_GetConfigProperty(PyObject *self, PyObject *args) -{ - unsigned char *property; - unsigned char buf[256]; //MSGSRV_CONFIG_MAX_PROP_CHARS + 1 - - if (!PyArg_ParseTuple(args, "s", &property)) { - return NULL; - } - if(MsgGetConfigProperty(buf, property)) { - return Py_BuildValue("s", buf); - } - return NULL; -} - PyObject * msgapi_GetUnprivilegedUser(PyObject *self, PyObject *args) { return Py_BuildValue("z", MsgGetUnprivilegedUser()); } - -EnumItemDef MsgApiEnums[] = { - {"MAX_PROP_CHARS", MSGSRV_CONFIG_MAX_PROP_CHARS, NULL}, - {"MESSAGING_SERVER", 0, MSGSRV_CONFIG_PROP_MESSAGING_SERVER}, - {"WEB_ADMIN_SERVER", 0, MSGSRV_CONFIG_PROP_WEB_ADMIN_SERVER}, - {"DEFAULT_CONTEXT", 0, MSGSRV_CONFIG_PROP_DEFAULT_CONTEXT}, - {"BONGO_SERVICES", 0, MSGSRV_CONFIG_PROP_BONGO_SERVICES}, - {"CONFIG_FILENAME", 0, MSGSRV_CONFIG_FILENAME}, - {"ROOT", 0, MSGSRV_ROOT}, - {"USER_SETTINGS_ROOT", 0, MSGSRV_USER_SETTINGS_ROOT}, - {"C_ROOT", 0, MSGSRV_C_ROOT}, - {"C_SERVER", 0, MSGSRV_C_SERVER}, - {"C_WEBADMIN", 0, MSGSRV_C_WEBADMIN}, - {"C_ADDRESSBOOK", 0, MSGSRV_C_ADDRESSBOOK}, - {"C_AGENT", 0, MSGSRV_C_AGENT}, - {"C_ALIAS", 0, MSGSRV_C_ALIAS}, - {"C_ANTISPAM", 0, MSGSRV_C_ANTISPAM}, - {"C_FINGER", 0, MSGSRV_C_FINGER}, - {"C_GATEKEEPER", 0, MSGSRV_C_GATEKEEPER}, - {"C_CONNMGR", 0, MSGSRV_C_CONNMGR}, - {"C_IMAP", 0, MSGSRV_C_IMAP}, - {"C_LIST", 0, MSGSRV_C_LIST}, - {"C_NDSLIST", 0, MSGSRV_C_NDSLIST}, - {"C_LISTCONTAINER", 0, MSGSRV_C_LISTCONTAINER}, - {"C_LISTUSER", 0, MSGSRV_C_LISTUSER}, - {"C_LISTAGENT", 0, MSGSRV_C_LISTAGENT}, - {"C_STORE", 0, MSGSRV_C_STORE}, - {"C_QUEUE", 0, MSGSRV_C_QUEUE}, - {"C_POP", 0, MSGSRV_C_POP}, - {"C_PROXY", 0, MSGSRV_C_PROXY}, - {"C_RULESRV", 0, MSGSRV_C_RULESRV}, - {"C_SIGNUP", 0, MSGSRV_C_SIGNUP}, - {"C_SMTP", 0, MSGSRV_C_SMTP}, - {"C_PARENTCONTAINER", 0, MSGSRV_C_PARENTCONTAINER}, - {"C_PARENTOBJECT", 0, MSGSRV_C_PARENTOBJECT}, - {"C_TEMPLATECONTAINER", 0, MSGSRV_C_TEMPLATECONTAINER}, - {"C_ITIP", 0, MSGSRV_C_ITIP}, - {"C_ANTIVIRUS", 0, MSGSRV_C_ANTIVIRUS}, - {"C_RESOURCE", 0, MSGSRV_C_RESOURCE}, - {"C_CONNMGR_MODULE", 0, MSGSRV_C_CONNMGR_MODULE}, - {"C_CM_USER_MODULE", 0, MSGSRV_C_CM_USER_MODULE}, - {"C_CM_LISTS_MODULE", 0, MSGSRV_C_CM_LISTS_MODULE}, - {"C_CM_RBL_MODULE", 0, MSGSRV_C_CM_RBL_MODULE}, - {"C_CM_RDNS_MODULE", 0, MSGSRV_C_CM_RDNS_MODULE}, - {"C_CALCMD", 0, MSGSRV_C_CALCMD}, - {"C_COLLECTOR", 0, MSGSRV_C_COLLECTOR}, - {"C_USER", 0, MSGSRV_C_USER}, - {"C_ORGANIZATIONAL_ROLE", 0, MSGSRV_C_ORGANIZATIONAL_ROLE}, - {"C_ORGANIZATION", 0, MSGSRV_C_ORGANIZATION}, - {"C_ORGANIZATIONAL_UNIT", 0, MSGSRV_C_ORGANIZATIONAL_UNIT}, - {"C_GROUP", 0, MSGSRV_C_GROUP}, - {"C_USER_SETTINGS_CONTAINER", 0, MSGSRV_C_USER_SETTINGS_CONTAINER}, - {"C_USER_SETTINGS", 0, MSGSRV_C_USER_SETTINGS}, - {"AGENT_ADDRESSBOOK", 0, MSGSRV_AGENT_ADDRESSBOOK}, - {"AGENT_ALIAS", 0, MSGSRV_AGENT_ALIAS}, - {"AGENT_ANTISPAM", 0, MSGSRV_AGENT_ANTISPAM}, - {"AGENT_FINGER", 0, MSGSRV_AGENT_FINGER}, - {"AGENT_GATEKEEPER", 0, MSGSRV_AGENT_GATEKEEPER}, - {"AGENT_CALCMD", 0, MSGSRV_AGENT_CALCMD}, - {"AGENT_CONNMGR", 0, MSGSRV_AGENT_CONNMGR}, - {"AGENT_IMAP", 0, MSGSRV_AGENT_IMAP}, - {"AGENT_LIST", 0, MSGSRV_AGENT_LIST}, - {"AGENT_STORE", 0, MSGSRV_AGENT_STORE}, - {"AGENT_QUEUE", 0, MSGSRV_AGENT_QUEUE}, - {"AGENT_POP", 0, MSGSRV_AGENT_POP}, - {"AGENT_PROXY", 0, MSGSRV_AGENT_PROXY}, - {"AGENT_RULESRV", 0, MSGSRV_AGENT_RULESRV}, - {"AGENT_SIGNUP", 0, MSGSRV_AGENT_SIGNUP}, - {"AGENT_SMTP", 0, MSGSRV_AGENT_SMTP}, - {"AGENT_ITIP", 0, MSGSRV_AGENT_ITIP}, - {"AGENT_ANTIVIRUS", 0, MSGSRV_AGENT_ANTIVIRUS}, - {"AGENT_DMC", 0, MSGSRV_AGENT_DMC}, - {"AGENT_CMUSER", 0, MSGSRV_AGENT_CMUSER}, - {"AGENT_CMLISTS", 0, MSGSRV_AGENT_CMLISTS}, - {"AGENT_CMRBL", 0, MSGSRV_AGENT_CMRBL}, - {"AGENT_CMRDNS", 0, MSGSRV_AGENT_CMRDNS}, - {"AGENT_COLLECTOR", 0, MSGSRV_AGENT_COLLECTOR}, - {"A_AGENT_STATUS", 0, MSGSRV_A_AGENT_STATUS}, - {"A_ALIAS", 0, MSGSRV_A_ALIAS}, - {"A_AUTHENTICATION_REQUIRED", 0, MSGSRV_A_AUTHENTICATION_REQUIRED}, - {"A_CONFIGURATION", 0, MSGSRV_A_CONFIGURATION}, - {"A_CLIENT", 0, MSGSRV_A_CLIENT}, - {"A_CONTEXT", 0, MSGSRV_A_CONTEXT}, - {"A_DOMAIN", 0, MSGSRV_A_DOMAIN}, - {"A_EMAIL_ADDRESS", 0, MSGSRV_A_EMAIL_ADDRESS}, - {"A_DISABLED", 0, MSGSRV_A_DISABLED}, - {"A_FINGER_MESSAGE", 0, MSGSRV_A_FINGER_MESSAGE}, - {"A_HOST", 0, MSGSRV_A_HOST}, - {"A_IP_ADDRESS", 0, MSGSRV_A_IP_ADDRESS}, - {"A_LDAP_SERVER", 0, MSGSRV_A_LDAP_SERVER}, - {"A_LDAP_NMAP_SERVER", 0, MSGSRV_A_LDAP_NMAP_SERVER}, - {"A_LDAP_SEARCH_DN", 0, MSGSRV_A_LDAP_SEARCH_DN}, - {"A_MESSAGE_LIMIT", 0, MSGSRV_A_MESSAGE_LIMIT}, - {"A_MESSAGING_SERVER", 0, MSGSRV_A_MESSAGING_SERVER}, - {"A_MODULE_NAME", 0, MSGSRV_A_MODULE_NAME}, - {"A_MODULE_VERSION", 0, MSGSRV_A_MODULE_VERSION}, - {"A_MONITORED_QUEUE", 0, MSGSRV_A_MONITORED_QUEUE}, - {"A_QUEUE_SERVER", 0, MSGSRV_A_QUEUE_SERVER}, - {"A_STORE_SERVER", 0, MSGSRV_A_STORE_SERVER}, - {"A_OFFICIAL_NAME", 0, MSGSRV_A_OFFICIAL_NAME}, - {"A_QUOTA_MESSAGE", 0, MSGSRV_A_QUOTA_MESSAGE}, - {"A_POSTMASTER", 0, MSGSRV_A_POSTMASTER}, - {"A_REPLY_MESSAGE", 0, MSGSRV_A_REPLY_MESSAGE}, - {"A_URL", 0, MSGSRV_A_URL}, - {"A_RESOLVER", 0, MSGSRV_A_RESOLVER}, - {"A_ROUTING", 0, MSGSRV_A_ROUTING}, - {"A_SERVER_STATUS", 0, MSGSRV_A_SERVER_STATUS}, - {"A_QUEUE_INTERVAL", 0, MSGSRV_A_QUEUE_INTERVAL}, - {"A_QUEUE_TIMEOUT", 0, MSGSRV_A_QUEUE_TIMEOUT}, - {"A_UID", 0, MSGSRV_A_UID}, - {"A_VACATION_MESSAGE", 0, MSGSRV_A_VACATION_MESSAGE}, - {"A_WORD", 0, MSGSRV_A_WORD}, - {"A_MESSAGE_STORE", 0, MSGSRV_A_MESSAGE_STORE}, - {"A_FORWARDING_ADDRESS", 0, MSGSRV_A_FORWARDING_ADDRESS}, - {"A_FORWARDING_ENABLED", 0, MSGSRV_A_FORWARDING_ENABLED}, - {"A_AUTOREPLY_ENABLED", 0, MSGSRV_A_AUTOREPLY_ENABLED}, - {"A_AUTOREPLY_MESSAGE", 0, MSGSRV_A_AUTOREPLY_MESSAGE}, - {"A_PORT", 0, MSGSRV_A_PORT}, - {"A_SSL_PORT", 0, MSGSRV_A_SSL_PORT}, - {"A_SNMP_DESCRIPTION", 0, MSGSRV_A_SNMP_DESCRIPTION}, - {"A_SNMP_VERSION", 0, MSGSRV_A_SNMP_VERSION}, - {"A_SNMP_ORGANIZATION", 0, MSGSRV_A_SNMP_ORGANIZATION}, - {"A_SNMP_LOCATION", 0, MSGSRV_A_SNMP_LOCATION}, - {"A_SNMP_CONTACT", 0, MSGSRV_A_SNMP_CONTACT}, - {"A_SNMP_NAME", 0, MSGSRV_A_SNMP_NAME}, - {"A_MESSAGING_DISABLED", 0, MSGSRV_A_MESSAGING_DISABLED}, - {"A_STORE_TRUSTED_HOSTS", 0, MSGSRV_A_STORE_TRUSTED_HOSTS}, - {"A_QUOTA_VALUE", 0, MSGSRV_A_QUOTA_VALUE}, - {"A_SCMS_USER_THRESHOLD", 0, MSGSRV_A_SCMS_USER_THRESHOLD}, - {"A_SCMS_SIZE_THRESHOLD", 0, MSGSRV_A_SCMS_SIZE_THRESHOLD}, - {"A_SMTP_VERIFY_ADDRESS", 0, MSGSRV_A_SMTP_VERIFY_ADDRESS}, - {"A_SMTP_ALLOW_AUTH", 0, MSGSRV_A_SMTP_ALLOW_AUTH}, - {"A_SMTP_ALLOW_VRFY", 0, MSGSRV_A_SMTP_ALLOW_VRFY}, - {"A_SMTP_ALLOW_EXPN", 0, MSGSRV_A_SMTP_ALLOW_EXPN}, - {"A_WORK_DIRECTORY", 0, MSGSRV_A_WORK_DIRECTORY}, - {"A_LOGLEVEL", 0, MSGSRV_A_LOGLEVEL}, - {"A_MINIMUM_SPACE", 0, MSGSRV_A_MINIMUM_SPACE}, - {"A_SMTP_SEND_ETRN", 0, MSGSRV_A_SMTP_SEND_ETRN}, - {"A_SMTP_ACCEPT_ETRN", 0, MSGSRV_A_SMTP_ACCEPT_ETRN}, - {"A_LIMIT_REMOTE_PROCESSING", 0, MSGSRV_A_LIMIT_REMOTE_PROCESSING}, - {"A_LIMIT_REMOTE_START_WD", 0, MSGSRV_A_LIMIT_REMOTE_START_WD}, - {"A_LIMIT_REMOTE_END_WD", 0, MSGSRV_A_LIMIT_REMOTE_END_WD}, - {"A_LIMIT_REMOTE_START_WE", 0, MSGSRV_A_LIMIT_REMOTE_START_WE}, - {"A_LIMIT_REMOTE_END_WE", 0, MSGSRV_A_LIMIT_REMOTE_END_WE}, - {"A_PRODUCT_VERSION", 0, MSGSRV_A_PRODUCT_VERSION}, - {"A_PROXY_LIST", 0, MSGSRV_A_PROXY_LIST}, - {"A_MAXIMUM_ITEMS", 0, MSGSRV_A_MAXIMUM_ITEMS}, - {"A_TIME_INTERVAL", 0, MSGSRV_A_TIME_INTERVAL}, - {"A_RELAYHOST", 0, MSGSRV_A_RELAYHOST}, - {"A_ALIAS_OPTIONS", 0, MSGSRV_A_ALIAS_OPTIONS}, - {"A_LDAP_OPTIONS", 0, MSGSRV_A_LDAP_OPTIONS}, - {"A_CUSTOM_ALIAS", 0, MSGSRV_A_CUSTOM_ALIAS}, - {"A_ADVERTISING_CONFIG", 0, MSGSRV_A_ADVERTISING_CONFIG}, - {"A_LANGUAGE", 0, MSGSRV_A_LANGUAGE}, - {"A_PREFERENCES", 0, MSGSRV_A_PREFERENCES}, - {"A_QUOTA_WARNING", 0, MSGSRV_A_QUOTA_WARNING}, - {"A_QUEUE_TUNING", 0, MSGSRV_A_QUEUE_TUNING}, - {"A_TIMEOUT", 0, MSGSRV_A_TIMEOUT}, - {"A_PRIVACY", 0, MSGSRV_A_PRIVACY}, - {"A_THREAD_LIMIT", 0, MSGSRV_A_THREAD_LIMIT}, - {"A_DBF_PAGESIZE", 0, MSGSRV_A_DBF_PAGESIZE}, - {"A_DBF_KEYSIZE", 0, MSGSRV_A_DBF_KEYSIZE}, - {"A_ADDRESSBOOK_CONFIG", 0, MSGSRV_A_ADDRESSBOOK_CONFIG}, - {"A_ADDRESSBOOK_URL_SYSTEM", 0, MSGSRV_A_ADDRESSBOOK_URL_SYSTEM}, - {"A_ADDRESSBOOK_URL_PUBLIC", 0, MSGSRV_A_ADDRESSBOOK_URL_PUBLIC}, - {"A_ADDRESSBOOK", 0, MSGSRV_A_ADDRESSBOOK}, - {"A_SERVER_STANDALONE", 0, MSGSRV_A_SERVER_STANDALONE}, - {"A_FORWARD_UNDELIVERABLE", 0, MSGSRV_A_FORWARD_UNDELIVERABLE}, - {"A_PHRASE", 0, MSGSRV_A_PHRASE}, - {"A_ACCOUNTING_ENABLED", 0, MSGSRV_A_ACCOUNTING_ENABLED}, - {"A_ACCOUNTING_DATA", 0, MSGSRV_A_ACCOUNTING_DATA}, - {"A_BILLING_DATA", 0, MSGSRV_A_BILLING_DATA}, - {"A_BLOCKED_ADDRESS", 0, MSGSRV_A_BLOCKED_ADDRESS}, - {"A_ALLOWED_ADDRESS", 0, MSGSRV_A_ALLOWED_ADDRESS}, - {"A_RECIPIENT_LIMIT", 0, MSGSRV_A_RECIPIENT_LIMIT}, - {"A_RBL_HOST", 0, MSGSRV_A_RBL_HOST}, - {"A_SIGNATURE", 0, MSGSRV_A_SIGNATURE}, - {"A_CONNMGR", 0, MSGSRV_A_CONNMGR}, - {"A_CONNMGR_CONFIG", 0, MSGSRV_A_CONNMGR_CONFIG}, - {"A_USER_DOMAIN", 0, MSGSRV_A_USER_DOMAIN}, - {"A_RTS_ANTISPAM_CONFIG", 0, MSGSRV_A_RTS_ANTISPAM_CONFIG}, - {"A_SPOOL_DIRECTORY", 0, MSGSRV_A_SPOOL_DIRECTORY}, - {"A_SCMS_DIRECTORY", 0, MSGSRV_A_SCMS_DIRECTORY}, - {"A_DBF_DIRECTORY", 0, MSGSRV_A_DBF_DIRECTORY}, - {"A_NLS_DIRECTORY", 0, MSGSRV_A_NLS_DIRECTORY}, - {"A_BIN_DIRECTORY", 0, MSGSRV_A_BIN_DIRECTORY}, - {"A_LIB_DIRECTORY", 0, MSGSRV_A_LIB_DIRECTORY}, - {"A_DEFAULT_CHARSET", 0, MSGSRV_A_DEFAULT_CHARSET}, - {"A_RULE", 0, MSGSRV_A_RULE}, - {"A_RELAY_DOMAIN", 0, MSGSRV_A_RELAY_DOMAIN}, - {"A_LIST_DIGESTTIME", 0, MSGSRV_A_LIST_DIGESTTIME}, - {"A_LIST_ABSTRACT", 0, MSGSRV_A_LIST_ABSTRACT}, - {"A_LIST_DESCRIPTION", 0, MSGSRV_A_LIST_DESCRIPTION}, - {"A_LIST_CONFIGURATION", 0, MSGSRV_A_LIST_CONFIGURATION}, - {"A_LIST_STORE", 0, MSGSRV_A_LIST_STORE}, - {"A_LIST_NMAPSTORE", 0, MSGSRV_A_LIST_NMAPSTORE}, - {"A_LIST_MODERATOR", 0, MSGSRV_A_LIST_MODERATOR}, - {"A_LIST_OWNER", 0, MSGSRV_A_LIST_OWNER}, - {"A_LIST_SIGNATURE", 0, MSGSRV_A_LIST_SIGNATURE}, - {"A_LIST_SIGNATURE_HTML", 0, MSGSRV_A_LIST_SIGNATURE_HTML}, - {"A_LIST_DIGEST_VERSION", 0, MSGSRV_A_LIST_DIGEST_VERSION}, - {"A_LIST_MEMBERS", 0, MSGSRV_A_LIST_MEMBERS}, - {"A_LISTUSER_OPTIONS", 0, MSGSRV_A_LISTUSER_OPTIONS}, - {"A_LISTUSER_ADMINOPTIONS", 0, MSGSRV_A_LISTUSER_ADMINOPTIONS}, - {"A_LISTUSER_PASSWORD", 0, MSGSRV_A_LISTUSER_PASSWORD}, - {"A_FEATURE_SET", 0, MSGSRV_A_FEATURE_SET}, - {"A_PRIVATE_KEY_LOCATION", 0, MSGSRV_A_PRIVATE_KEY_LOCATION}, - {"A_CERTIFICATE_LOCATION", 0, MSGSRV_A_CERTIFICATE_LOCATION}, - {"A_CONFIG_CHANGED", 0, MSGSRV_A_CONFIG_CHANGED}, - {"A_LISTSERVER_NAME", 0, MSGSRV_A_LISTSERVER_NAME}, - {"A_LIST_WELCOME_MESSAGE", 0, MSGSRV_A_LIST_WELCOME_MESSAGE}, - {"A_PARENT_OBJECT", 0, MSGSRV_A_PARENT_OBJECT}, - {"A_FEATURE_INHERITANCE", 0, MSGSRV_A_FEATURE_INHERITANCE}, - {"A_TEMPLATE", 0, MSGSRV_A_TEMPLATE}, - {"A_TIMEZONE", 0, MSGSRV_A_TIMEZONE}, - {"A_LOCALE", 0, MSGSRV_A_LOCALE}, - {"A_PASSWORD_CONFIGURATION", 0, MSGSRV_A_PASSWORD_CONFIGURATION}, - {"A_TITLE", 0, MSGSRV_A_TITLE}, - {"A_DEFAULT_TEMPLATE", 0, MSGSRV_A_DEFAULT_TEMPLATE}, - {"A_TOM_MANAGER", 0, MSGSRV_A_TOM_MANAGER}, - {"A_TOM_CONTEXTS", 0, MSGSRV_A_TOM_CONTEXTS}, - {"A_TOM_DOMAINS", 0, MSGSRV_A_TOM_DOMAINS}, - {"A_TOM_OPTIONS", 0, MSGSRV_A_TOM_OPTIONS}, - {"A_DESCRIPTION", 0, MSGSRV_A_DESCRIPTION}, - {"A_STATSERVER_1", 0, MSGSRV_A_STATSERVER_1}, - {"A_STATSERVER_2", 0, MSGSRV_A_STATSERVER_2}, - {"A_STATSERVER_3", 0, MSGSRV_A_STATSERVER_3}, - {"A_STATSERVER_4", 0, MSGSRV_A_STATSERVER_4}, - {"A_STATSERVER_5", 0, MSGSRV_A_STATSERVER_5}, - {"A_STATSERVER_6", 0, MSGSRV_A_STATSERVER_6}, - {"A_NEWS", 0, MSGSRV_A_NEWS}, - {"A_MANAGER", 0, MSGSRV_A_MANAGER}, - {"A_AVAILABLE_SHARES", 0, MSGSRV_A_AVAILABLE_SHARES}, - {"A_OWNED_SHARES", 0, MSGSRV_A_OWNED_SHARES}, - {"A_NEW_SHARE_MESSAGE", 0, MSGSRV_A_NEW_SHARE_MESSAGE}, - {"A_AVAILABLE_PROXIES", 0, MSGSRV_A_AVAILABLE_PROXIES}, - {"A_OWNED_PROXIES", 0, MSGSRV_A_OWNED_PROXIES}, - {"A_RESOURCE_MANAGER", 0, MSGSRV_A_RESOURCE_MANAGER}, - {"A_BONGO_MESSAGING_SERVER", 0, MSGSRV_A_BONGO_MESSAGING_SERVER}, - {"A_ACL", 0, MSGSRV_A_ACL}, - {"A_WA_DEFAULT_TEMPLATE", 0, MSGSRV_A_WA_DEFAULT_TEMPLATE}, - {"A_WA_ALLOWED_TEMPLATES", 0, MSGSRV_A_WA_ALLOWED_TEMPLATES}, - {"A_WA_DISALLOWED_TEMPLATES", 0, MSGSRV_A_WA_DISALLOWED_TEMPLATES}, - {"A_SMS_AUTHORIZED_PHONES", 0, MSGSRV_A_SMS_AUTHORIZED_PHONES}, - {"A_CALCMD_ADDRESS_SUFFIX", 0, MSGSRV_A_CALCMD_ADDRESS_SUFFIX}, - {"A_MAX_LOAD", 0, MSGSRV_A_MAX_LOAD}, - {"A_ACL_ENABLED", 0, MSGSRV_A_ACL_ENABLED}, - {"A_UBE_SMTP_AFTER_POP", 0, MSGSRV_A_UBE_SMTP_AFTER_POP}, - {"A_UBE_REMOTE_AUTH_ONLY", 0, MSGSRV_A_UBE_REMOTE_AUTH_ONLY}, - {"A_MAX_FLOOD_COUNT", 0, MSGSRV_A_MAX_FLOOD_COUNT}, - {"A_MAX_NULL_SENDER_RECIPS", 0, MSGSRV_A_MAX_NULL_SENDER_RECIPS}, - {"A_MAX_MX_SERVERS", 0, MSGSRV_A_MAX_MX_SERVERS}, - {"A_RELAY_LOCAL_MAIL", 0, MSGSRV_A_RELAY_LOCAL_MAIL}, - {"A_CLUSTERED", 0, MSGSRV_A_CLUSTERED}, - {"A_FORCE_BIND", 0, MSGSRV_A_FORCE_BIND}, - {"A_SSL_TLS", 0, MSGSRV_A_SSL_TLS}, - {"A_SSL_ALLOW_CHAINED", 0, MSGSRV_A_SSL_ALLOW_CHAINED}, - {"A_BOUNCE_RETURN", 0, MSGSRV_A_BOUNCE_RETURN}, - {"A_BOUNCE_CC_POSTMASTER", 0, MSGSRV_A_BOUNCE_CC_POSTMASTER}, - {"A_QUOTA_USER", 0, MSGSRV_A_QUOTA_USER}, - {"A_QUOTA_SYSTEM", 0, MSGSRV_A_QUOTA_SYSTEM}, - {"A_REGISTER_QUEUE", 0, MSGSRV_A_REGISTER_QUEUE}, - {"A_QUEUE_LIMIT_BOUNCES", 0, MSGSRV_A_QUEUE_LIMIT_BOUNCES}, - {"A_LIMIT_BOUNCE_ENTRIES", 0, MSGSRV_A_LIMIT_BOUNCE_ENTRIES}, - {"A_LIMIT_BOUNCE_INTERVAL", 0, MSGSRV_A_LIMIT_BOUNCE_INTERVAL}, - {"A_DOMAIN_ROUTING", 0, MSGSRV_A_DOMAIN_ROUTING}, - {"A_MONITOR_INTERVAL", 0, MSGSRV_A_MONITOR_INTERVAL}, - {"A_MANAGER_PORT", 0, MSGSRV_A_MANAGER_PORT}, - {"A_MANAGER_SSL_PORT", 0, MSGSRV_A_MANAGER_SSL_PORT}, - {NULL, 0, NULL} -}; diff --git a/src/libs/python/libbongo/msgapi.c b/src/libs/python/libbongo/msgapi.c index b2d053a..e81813c 100644 --- a/src/libs/python/libbongo/msgapi.c +++ b/src/libs/python/libbongo/msgapi.c @@ -72,79 +72,6 @@ msgapi_CollectUser(PyObject *self, PyObject *args) return Py_None; } -PyDoc_STRVAR(DirectoryHandle_doc, -"DirectoryHandle() -> handle\n\ -\n\ -Return the directory handle used by libmsgapi."); - -static PyObject * -msgapi_DirectoryHandle(PyObject *self, PyObject *args) -{ - MDBHandle handle; - - if (!PyArg_ParseTuple(args, "")) { - return NULL; - } - - handle = (MDBHandle)MsgDirectoryHandle(); - - if (handle == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - - return PyCObject_FromVoidPtr(handle, NULL); -} - -PyDoc_STRVAR(FindObject_doc, -"FindObject(u) -> string dn\n\ -\n\ -Return a string containing the dn of user u."); - -static PyObject * -msgapi_FindObject(PyObject *self, PyObject *args) -{ - unsigned char *user; - unsigned int len=MDB_MAX_OBJECT_CHARS+1; - unsigned char buf[len]; - - if (!PyArg_ParseTuple(args, "s", &user)) { - return NULL; - } - - if (!MsgFindObject(user, buf, NULL, NULL, NULL)) { - Py_INCREF(Py_None); - return Py_None; - } - - return Py_BuildValue("s", buf); -} - -PyDoc_STRVAR(FindUserNmap_doc, -"FindUserNmap(u) -> (string host, int port) tuple\n\ -\n\ -Return the ip address and port of user u's document store."); - -static PyObject * -msgapi_FindUserNmap(PyObject *self, PyObject *args) -{ - unsigned char *user; - unsigned int len=33; - unsigned char buf[len]; - unsigned short port; - - if (!PyArg_ParseTuple(args, "s", &user)) { - return NULL; - } - - if (!MsgFindUserNmap(user, buf, len, &port)) { - Py_INCREF(Py_None); - return Py_None; - } - - return Py_BuildValue("si", buf, port); -} - PyDoc_STRVAR(GetUserFeature_doc, "GetUserFeature(dn, featurename, ) -> array of strings\n\ \n\ @@ -177,227 +104,6 @@ static const char *features[] = { NULL }; -PyDoc_STRVAR(GetUserSetting_doc, "GetUserSetting(user, attribute)\n"); - -static PyObject * -msgapi_GetUserSetting(PyObject *self, PyObject *args) -{ - unsigned char *user; - char *attribute; - MDBValueStruct *v; - PyObject *ret = Py_None; - int i; - - if (!PyArg_ParseTuple(args, "ss", &user, &attribute)) { - return NULL; - } - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (v) { - if (MsgGetUserSetting(user, attribute, v)) { - ret = PyList_New(v->Used); - - for (i = 0; i < v->Used; i++) { - PyList_SetItem(ret, i, PyString_FromString(v->Value[i])); - } - } else { - ret = PyList_New(0); - } - - MDBDestroyValueStruct(v); - } else { - Py_INCREF(Py_None); - } - - return ret; -} - -PyDoc_STRVAR(SetUserSetting_doc, "SetUserSetting(user, attribute, values)\n"); - -static PyObject * -msgapi_SetUserSetting(PyObject *self, PyObject *args) -{ - unsigned char *user; - char *attribute; - char *val; - void *vals; - MDBValueStruct *v; - PyObject *item; - PyObject *ret = Py_False; - int i, size; - - if (!PyArg_ParseTuple(args, "ssO", &user, &attribute, &vals)) { - return NULL; - } - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (v) { - size = PyList_Size(vals); - - for (i = 0; i < size; i++) { - item = PyList_GetItem(vals, i); - PyArg_Parse(item, "s", &val); - if (!MDBAddValue(val, v)) { - break; - } - } - - if (i == size && MsgSetUserSetting(user, attribute, v)) { - ret = Py_True; - } - - MDBDestroyValueStruct(v); - } - - Py_INCREF(ret); - return ret; -} - -PyDoc_STRVAR(AddUserSetting_doc, "AddUserSetting(user, attribute, value)\n"); - -static PyObject * -msgapi_AddUserSetting(PyObject *self, PyObject *args) -{ - unsigned char *user; - char *attribute; - char *value; - MDBValueStruct *v; - PyObject *ret = Py_False; - - if (!PyArg_ParseTuple(args, "sss", &user, &attribute, &value)) { - return NULL; - } - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (v) { - if (MsgAddUserSetting(user, attribute, value, v)) { - ret = Py_True; - } - - MDBDestroyValueStruct(v); - } - - Py_INCREF(ret); - return ret; -} - -PyDoc_STRVAR(GetUserDisplayName_doc, -"GetUserDisplayName(user) -> string\n\ -\n\ -Return a string containing the display name of the user."); - -static PyObject * -msgapi_GetUserDisplayName(PyObject *self, PyObject *args) -{ - unsigned char *userDN; - unsigned char *name; - MDBValueStruct *v; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s", &userDN)) { - return NULL; - } - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (v) { - name = MsgGetUserDisplayName(userDN, v); - MDBDestroyValueStruct(v); - - ret = Py_BuildValue("s", name); - MemFree(name); - } else { - Py_INCREF(Py_None); - ret = Py_None; - } - - return ret; -} - -PyDoc_STRVAR(GetUserEmailAddress_doc, -"GetUserEmailAddress(user) -> string\n\ -\n\ -Return a string containing the email address of the user."); - -static PyObject * -msgapi_GetUserEmailAddress(PyObject *self, PyObject *args) -{ - unsigned char *userDN; - unsigned char email[400]; /* according to RFC2821, the maximum length of a - user name is 64 chars. A domain name can be - 255. */ - MDBValueStruct *v; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s", &userDN)) { - return NULL; - } - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (v) { - MsgGetUserEmailAddress(userDN, v, email, sizeof(email)-1); - MDBDestroyValueStruct(v); - - ret = Py_BuildValue("s", email); - } else { - Py_INCREF(Py_None); - ret = Py_None; - } - - return ret; -} - -static PyObject * -msgapi_GetUserFeature(PyObject *self, PyObject *args) -{ - unsigned char *user; - char *feature; - char *attribute; - unsigned int len=33; - unsigned char buf[len]; - char row; - int col; - - if (!PyArg_ParseTuple(args, "sss", &user, &feature, &attribute)) { - return NULL; - } - - row = 'A'; - for (col = 0; features[col] != NULL; col++) { - if (!strcmp(features[col], feature)) { - break; - } - } - - if (features[col]) { - MDBValueStruct *v; - PyObject *ret; - - v = MDBCreateValueStruct(MsgDirectoryHandle(), NULL); - - if (MsgGetUserFeature(user, row, col, attribute, v)) { - int i; - ret = PyList_New(v->Used); - for (i = 0; i < v->Used; i++) { - PyList_SetItem(ret, i, PyString_FromString(v->Value[i])); - } - } else { - Py_INCREF(Py_None); - ret = Py_None; - } - - MDBDestroyValueStruct(v); - return ret; - } else { - Py_INCREF(Py_None); - return Py_None; - } -} - static void ThrowImportException(int code) { @@ -613,20 +319,11 @@ extern PyObject *msgapi_GetConfigProperty(PyObject *, PyObject *); PyMethodDef MsgApiMethods[] = { {"CollectAllUsers", msgapi_CollectAllUsers, METH_VARARGS | METH_STATIC, CollectAllUsers_doc}, {"CollectUser", msgapi_CollectUser, METH_VARARGS | METH_STATIC, CollectUser_doc}, - {"DirectoryHandle", msgapi_DirectoryHandle, METH_VARARGS | METH_STATIC, DirectoryHandle_doc}, - {"FindObject", msgapi_FindObject, METH_VARARGS | METH_STATIC, FindObject_doc}, - {"FindUserNmap", msgapi_FindUserNmap, METH_VARARGS | METH_STATIC, FindUserNmap_doc}, - {"GetUserSetting", msgapi_GetUserSetting, METH_VARARGS | METH_STATIC, GetUserSetting_doc}, - {"SetUserSetting", msgapi_SetUserSetting, METH_VARARGS | METH_STATIC, SetUserSetting_doc}, - {"GetUserDisplayName", msgapi_GetUserDisplayName, METH_VARARGS | METH_STATIC, GetUserDisplayName_doc}, - {"GetUserEmailAddress", msgapi_GetUserEmailAddress, METH_VARARGS | METH_STATIC, GetUserEmailAddress_doc}, - {"GetUserFeature", msgapi_GetUserFeature, METH_VARARGS | METH_STATIC, GetUserFeature_doc}, {"ImportIcsUrl", msgapi_ImportIcsUrl, METH_VARARGS | METH_STATIC, ImportIcsUrl_doc}, {"ImportIcs", msgapi_ImportIcs, METH_VARARGS | METH_STATIC, ImportIcs_doc}, {"IcsSubscribe", msgapi_IcsSubscribe, METH_VARARGS | METH_STATIC, IcsSubscribe_doc}, {"IcsImport", msgapi_IcsImport, METH_VARARGS | METH_STATIC, IcsImport_doc}, {"NmapChallenge", msgapi_NmapChallenge, METH_VARARGS | METH_STATIC, NmapChallenge_doc}, - {"GetConfigProperty", msgapi_GetConfigProperty, METH_VARARGS | METH_STATIC, GetConfigProperty_doc}, {"GetUnprivilegedUser", msgapi_GetUnprivilegedUser, METH_VARARGS | METH_STATIC, GetUnprivilegedUser_doc}, {"GetBuildVersion", msgapi_GetBuildVersion, METH_VARARGS | METH_STATIC, GetBuildVersion_doc}, {"GetAvailableVersion", msgapi_GetAvailableVersion, METH_VARARGS | METH_STATIC, GetAvailableVersion_doc}, diff --git a/src/libs/python/libbongo/tests.c b/src/libs/python/libbongo/tests.c new file mode 100644 index 0000000..fb0fa54 --- /dev/null +++ b/src/libs/python/libbongo/tests.c @@ -0,0 +1,47 @@ +#include + +#include + +#include "libs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// to test this: +// from libbongo.libs import tests +// print tests.GetAsciiString() +// print tests.GetUnicodeString() + +static PyObject * +test_GetAsciiString(void) +{ + char *hello_english = "Hello"; + PyObject *ret; + + ret = Py_BuildValue("s", hello_english); + + return ret; +} + +static PyObject * +test_GetUnicodeString(void) +{ + char *hello_finnish = "hyvää päivää"; + PyObject *ret; + + ret = PyUnicode_Decode(hello_finnish, strlen(hello_finnish), + "utf-8", "strict"); + + return ret; +} + +PyMethodDef TestMethods[] = { + {"GetAsciiString", test_GetAsciiString, METH_VARARGS | METH_STATIC}, + {"GetUnicodeString", test_GetUnicodeString, METH_VARARGS | METH_STATIC}, + {NULL, NULL, 0, NULL} +}; + +#ifdef __cplusplus +} +#endif diff --git a/src/libs/streamio/Bongo.rules b/src/libs/streamio/Bongo.rules index e95a18c..a162b42 100644 --- a/src/libs/streamio/Bongo.rules +++ b/src/libs/streamio/Bongo.rules @@ -3,16 +3,16 @@ lib_LTLIBRARIES += libbongostreamio.la #libbongostreamio_la_LDFLAGS = -static -libbongostreamio_la_CPPFLAGS := $(AM_CPPFLAGS) \ +libbongostreamio_la_CPPFLAGS = $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/libs/streamio/codec -libbongostreamio_la_SOURCES := \ +libbongostreamio_la_SOURCES = \ src/libs/streamio/streamio.c \ src/libs/streamio/streamiop.h \ src/libs/streamio/search.c \ src/libs/streamio/bongostream.c -libbongostreamio_la_LIBADD := libbongoutil.la +libbongostreamio_la_LIBADD = libbongoutil.la src/libs/streamio/all: libbongostreamio.la src/libs/streamio/clean: clean diff --git a/src/libs/xpl/Bongo.rules b/src/libs/xpl/Bongo.rules index defeaab..f503067 100644 --- a/src/libs/xpl/Bongo.rules +++ b/src/libs/xpl/Bongo.rules @@ -1,7 +1,7 @@ # -*- Makefile -*- lib_LTLIBRARIES += libbongoxpl.la -libbongoxpl_la_SOURCES := \ +libbongoxpl_la_SOURCES = \ src/libs/xpl/dir.c \ src/libs/xpl/dns.c \ src/libs/xpl/dns.h \ @@ -14,8 +14,8 @@ libbongoxpl_la_SOURCES := \ src/libs/xpl/util.c \ src/libs/xpl/cryptolock.c -libbongoxpl_la_LIBADD := $(RESOLV_LIBS) -libbongoxpl_la_LDFLAGS := $(PTHREAD_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS) $(KSTAT_LIBS) +libbongoxpl_la_LIBADD = $(RESOLV_LIBS) +libbongoxpl_la_LDFLAGS = $(PTHREAD_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS) $(KSTAT_LIBS) src/libs/xpl/all: libbongoxpl.la src/libs/xpl/clean: clean diff --git a/src/libs/xpl/cryptolock.c b/src/libs/xpl/cryptolock.c index 865b72a..ddc4f2b 100644 --- a/src/libs/xpl/cryptolock.c +++ b/src/libs/xpl/cryptolock.c @@ -32,7 +32,6 @@ void XPLCryptoLockInit(void); void XPLCryptoLockDestroy(void); -static void CryptoLockCallback(int mode,int type,char *file,int line); #ifdef SOLARIS static unsigned long solaris_thread_id(void ); #endif @@ -232,13 +231,14 @@ solaris_thread_id(void) /* Linux and a few others */ #if defined(LINUX) || defined(S390RH) +#if 0 +// FIXME: This looks like a lock needed for OpenSSL - deprecated? static pthread_mutex_t *CryptoLocks = NULL; static long *CryptoLockCount = NULL; void XPLCryptoLockInit(void) { -/* int i; if (!CryptoLocks && !CryptoLockCount) { @@ -266,14 +266,13 @@ XPLCryptoLockInit(void) free(CryptoLockCount); CryptoLockCount = NULL; } - } */ + } return; } void XPLCryptoLockDestroy(void) { -/* int i; if (CryptoLocks) { @@ -290,30 +289,24 @@ void XPLCryptoLockDestroy(void) free(CryptoLockCount); CryptoLockCount = NULL; } -*/ return; } void CryptoLockCallback(int mode, int type, char *file, int line) { -/* -#if 0 fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",CRYPTO_thread_id(), (mode&CRYPTO_LOCK)?"l":"u", (type&CRYPTO_READ)?"r":"w",file,line); -#endif -#if 0 if (CRYPTO_LOCK_SSL_CERT == type) { fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n", CRYPTO_thread_id(), mode,file,line); } -#endif if (mode & CRYPTO_LOCK) { pthread_mutex_lock(&(CryptoLocks[type])); CryptoLockCount[type]++; } else { pthread_mutex_unlock(&(CryptoLocks[type])); } - */ } +#endif unsigned long pthreads_thread_id(void) diff --git a/src/libs/xpl/dns.c b/src/libs/xpl/dns.c index d8a50c6..2c2db3b 100644 --- a/src/libs/xpl/dns.c +++ b/src/libs/xpl/dns.c @@ -366,7 +366,6 @@ _XplDns_ParseQuery(const char *answer_buffer, int answer_len, XplDns_Result *res const char *response, *response_end; int x; int res; - int answers; // try to parse the answer header = (XplDnsResponseHeader *)answer_buffer; diff --git a/src/libs/xpl/hash.c b/src/libs/xpl/hash.c index f0ce70a..be33aa9 100644 --- a/src/libs/xpl/hash.c +++ b/src/libs/xpl/hash.c @@ -10,6 +10,7 @@ #include #include #include +#include #include GCRY_THREAD_OPTION_PTHREAD_IMPL; diff --git a/src/libs/xpl/mem.c b/src/libs/xpl/mem.c index a137ab4..4aa34ea 100644 --- a/src/libs/xpl/mem.c +++ b/src/libs/xpl/mem.c @@ -92,11 +92,12 @@ void XplSignalBlock(void) void XplSignalCatcher(XplShutdownFunc XplShutdownFunction) { sigset_t signalSet; - struct sigaction act = {0}; + struct sigaction act; int i; XplSignalBlock(); + memset (&act, 0, sizeof(struct sigaction)); ApplicationXplShutdownFunction = XplShutdownFunction; sigemptyset(&act.sa_mask); diff --git a/src/libs/xpl/tests/Bongo.rules b/src/libs/xpl/tests/Bongo.rules index ce368b1..57d2ca5 100644 --- a/src/libs/xpl/tests/Bongo.rules +++ b/src/libs/xpl/tests/Bongo.rules @@ -8,7 +8,7 @@ dist_noinst_DATA += \ CLEANFILES += \ src/libs/xpl/tests/checklog.xml -checktest_bongoxpl_dns_SOURCES := \ +checktest_bongoxpl_dns_SOURCES = \ src/libs/xpl/tests/dns-test.c checktest_bongoxpl_dns_LDADD = $(CHECK_LIBS) \ diff --git a/src/www/Bongo.rules b/src/www/Bongo.rules index 1d36b73..d02e939 100644 --- a/src/www/Bongo.rules +++ b/src/www/Bongo.rules @@ -1,18 +1,17 @@ # -*- Makefile -*- htdocsdir = $(pkgdatadir)/htdocs -dist_htdocs_DATA := \ +dist_htdocs_DATA = \ src/www/dragonfly.html \ src/www/dragonfly-debug.html \ src/www/favicon.ico htl10ndir = $(htdocsdir)/l10n -htl10n_DATA := $(htl10n_jsfiles) +htl10n_DATA = $(htl10n_jsfiles) cssdir = $(htdocsdir)/css -dist_css_DATA := \ - src/www/css/interpreter.css \ +dist_css_DATA = \ src/www/css/layout.css \ src/www/css/widgets.css \ src/www/css/login.css \ @@ -22,11 +21,12 @@ dist_css_DATA := \ src/www/css/calendar.css \ src/www/css/summary.css \ src/www/css/print.css \ - src/www/css/admin.css + src/www/css/admin.css \ + src/www/css/log.css screencssdir = $(cssdir) -compress_script := $(top_srcdir)/src/www/compress.py +compress_script = $(top_srcdir)/src/www/compress.py dist_screencss_DATA = \ src/www/css/screen.css @@ -36,7 +36,7 @@ src/www/css/screen.css: $(dist_css_DATA) imgdir = $(htdocsdir)/img -dist_img_DATA := \ +dist_img_DATA = \ src/www/img/accessories-text-editor.gif \ src/www/img/accessories-text-editor.png \ src/www/img/addressbook-16.png \ @@ -189,13 +189,29 @@ dist_img_DATA := \ src/www/img/system-installer.png \ src/www/img/system-users.png \ src/www/img/user.png \ - src/www/img/user-desktop.png - - + src/www/img/user-desktop.png \ + src/www/img/agent-control.png \ + src/www/img/agent-bongoimap.png \ + src/www/img/agent-bongomailprox.png \ + src/www/img/agent-bongopluspack.png \ + src/www/img/agent-bongopop3.png \ + src/www/img/agent-bongosmtp.png \ + src/www/img/agent-bongoantispam.png \ + src/www/img/agent-bongoavirus.png \ + src/www/img/agent-bongocalcmd.png \ + src/www/img/agent-bongocollector.png \ + src/www/img/agent-bongoqueue.png \ + src/www/img/agent-global.png \ + src/www/img/agent-unknown.png \ + src/www/img/list-add.png \ + src/www/img/list-remove.png \ + src/www/img/document-properties.png \ + src/www/img/document-delete.png + jsdir = $(htdocsdir)/js # These *must* be in the order in which they get loaded in the browser -dist_js_DATA := \ +dist_js_DATA = \ src/www/js/Dragonfly.js \ src/www/js/Format.js \ src/www/js/Gettext.js \ @@ -224,17 +240,19 @@ dist_js_DATA := \ src/www/js/MailConversationView.js \ src/www/js/MailListView.js \ src/www/js/Browser.js \ - src/www/js/BrowserCheck.js + src/www/js/BrowserCheck.js \ + src/www/js/Admin.js \ + src/www/js/Log.js eAreadir = $(htdocsdir)/js/eArea -dist_eArea_DATA := \ +dist_eArea_DATA = \ src/www/js/eArea/editableArea.js \ src/www/js/eArea/blank.html eAreaimagedir = $(htdocsdir)/js/eArea/icons -dist_eAreaimage_DATA := \ +dist_eAreaimage_DATA = \ src/www/js/eArea/icons/edit-select-all.png \ src/www/js/eArea/icons/edit-undo.png \ src/www/js/eArea/icons/edit-redo.png \ @@ -244,6 +262,7 @@ dist_eAreaimage_DATA := \ src/www/js/eArea/icons/format-justify-fill.png \ src/www/js/eArea/icons/format-text-bold.png \ src/www/js/eArea/icons/format-text-italic.png \ + src/www/js/eArea/icons/format-text-underline.png \ src/www/js/eArea/icons/format-indent-more.png \ src/www/js/eArea/icons/format-indent-less.png \ src/www/js/eArea/icons/insert-image.png \ @@ -252,36 +271,33 @@ dist_eAreaimage_DATA := \ plugindir = $(htdocsdir)/plugins -dist_plugin_DATA := \ +dist_plugin_DATA = \ src/www/plugins/example.js prototypedir = $(jsdir)/lib/prototype -dist_prototype_DATA := \ +dist_prototype_DATA = \ src/www/js/lib/prototype/prototype.js mochidir = $(jsdir)/lib/MochiKit # These *must* be in the order in which they get loaded in the browser/MochiKit -dist_mochi_DATA := \ +dist_mochi_DATA = \ src/www/js/lib/MochiKit/Base.js \ src/www/js/lib/MochiKit/Iter.js \ - src/www/js/lib/MochiKit/Logging.js \ src/www/js/lib/MochiKit/DateTime.js \ src/www/js/lib/MochiKit/Format.js \ src/www/js/lib/MochiKit/Async.js \ src/www/js/lib/MochiKit/DOM.js \ - src/www/js/lib/MochiKit/LoggingPane.js \ src/www/js/lib/MochiKit/Color.js \ src/www/js/lib/MochiKit/Signal.js \ src/www/js/lib/MochiKit/Visual.js \ - src/www/js/lib/MochiKit/MochiKit.js \ - src/www/js/lib/MochiKit/interpreter.js + src/www/js/lib/MochiKit/MochiKit.js scriptaculousdir = $(jsdir)/lib/script.aculo.us # Same as with above JS. -dist_scriptaculous_DATA := \ +dist_scriptaculous_DATA = \ src/www/js/lib/script.aculo.us/effects.js \ src/www/js/lib/script.aculo.us/controls.js @@ -291,14 +307,14 @@ dist_finaljs_DATA = \ src/www/js/final.js src/www/js/final.js: $(dist_js_DATA) $(dist_prototype_DATA) $(dist_scriptaculous_DATA) $(dist_mochi_DATA) - $(compress_script) $(dist_prototype_DATA) $(dist_scriptaculous_DATA) $(dist_mochi_DATA) $(dist_js_DATA) src/www/js/eArea/editableArea.js -o src/www/js/final.js --measure --type js + $(compress_script) $(dist_prototype_DATA) $(dist_scriptaculous_DATA) $(dist_mochi_DATA) $(dist_js_DATA) src/www/js/eArea/editableArea.js -o src/www/js/final.js --measure --type js -i src/www/js/Admin.js -i src/www/js/Browser.js -i src/www/js/BrowserCheck.js install-data-local:: install-dist_htdocsDATA ln -sf dragonfly.html "$(DESTDIR)$(htdocsdir)/index.html" pkgpythondragonflydir = $(pkgpythondir)/dragonfly -pkgpythondragonfly_PYTHON := \ +pkgpythondragonfly_PYTHON = \ src/www/bongo/dragonfly/__init__.py \ src/www/bongo/dragonfly/AddressbookView.py \ src/www/bongo/dragonfly/Auth.py \ @@ -314,10 +330,10 @@ pkgpythondragonfly_PYTHON := \ pkgpythonhawkeyedir = $(pkgpythondir)/hawkeye -pkgpythonhawkeye_PYTHON := \ +pkgpythonhawkeye_PYTHON = \ src/www/bongo/hawkeye/__init__.py \ - src/www/bongo/hawkeye/AntispamView.py \ src/www/bongo/hawkeye/AgentView.py \ + src/www/bongo/hawkeye/AliasView.py \ src/www/bongo/hawkeye/Auth.py \ src/www/bongo/hawkeye/BackupView.py \ src/www/bongo/hawkeye/HawkeyeHandler.py \ @@ -328,9 +344,24 @@ pkgpythonhawkeye_PYTHON := \ src/www/bongo/hawkeye/ServerView.py \ src/www/bongo/hawkeye/UsersView.py +pkgpythonsundialdir = $(pkgpythondir)/sundial + +pkgpythonsundial_PYTHON := \ + src/www/bongo/sundial/__init__.py \ + src/www/bongo/sundial/SundialHandler.py \ + src/www/bongo/sundial/SundialPath.py \ + src/www/bongo/sundial/Auth.py \ + src/www/bongo/sundial/GetView.py \ + src/www/bongo/sundial/PropfindView.py \ + src/www/bongo/sundial/OptionsView.py \ + src/www/bongo/sundial/ReportView.py \ + src/www/bongo/sundial/DeleteView.py \ + src/www/bongo/sundial/PutView.py \ + src/www/bongo/sundial/Server.py + pkgpythoncommonwebdir = $(pkgpythondir)/commonweb -pkgpythoncommonweb_PYTHON := \ +pkgpythoncommonweb_PYTHON = \ src/www/bongo/commonweb/__init__.py \ src/www/bongo/commonweb/HttpError.py \ src/www/bongo/commonweb/ApacheLogHandler.py \ @@ -338,37 +369,41 @@ pkgpythoncommonweb_PYTHON := \ src/www/bongo/commonweb/BongoFieldStorage.py \ src/www/bongo/commonweb/BongoUtil.py \ src/www/bongo/commonweb/Standalone.py \ - src/www/bongo/commonweb/BongoSession.py + src/www/bongo/commonweb/BongoSession.py \ + src/www/bongo/commonweb/ElementTree.py hawkeyetplrootdir = $(htdocsdir)/hawkeye/root -dist_hawkeyetplroot_DATA := \ +dist_hawkeyetplroot_DATA = \ src/www/hawkeye/root/login.tpl \ src/www/hawkeye/root/test.tpl \ src/www/hawkeye/root/test-hello.tpl \ src/www/hawkeye/root/index.tpl hawkeyetplbackupdir = $(htdocsdir)/hawkeye/backup -dist_hawkeyetplbackup_DATA := \ +dist_hawkeyetplbackup_DATA = \ src/www/hawkeye/backup/index.tpl hawkeyetplserverdir = $(htdocsdir)/hawkeye/server -dist_hawkeyetplserver_DATA := \ +dist_hawkeyetplserver_DATA = \ src/www/hawkeye/server/index.tpl hawkeyetplsystemdir = $(htdocsdir)/hawkeye/system -dist_hawkeyetplsystem_DATA := \ +dist_hawkeyetplsystem_DATA = \ src/www/hawkeye/system/index.tpl hawkeyetplagentsdir = $(htdocsdir)/hawkeye/agents -dist_hawkeyetplagents_DATA := \ - src/www/hawkeye/agents/index.tpl - -hawkeyetplantispamdir = $(htdocsdir)/hawkeye/antispam -dist_hawkeyetplantispam_DATA := \ - src/www/hawkeye/antispam/index.tpl +dist_hawkeyetplagents_DATA = \ + src/www/hawkeye/agents/index.tpl \ + src/www/hawkeye/agents/agentview.tpl + +hawkeyetplaliasesdir = $(htdocsdir)/hawkeye/aliases +dist_hawkeyetplaliases_DATA = \ + src/www/hawkeye/aliases/index.tpl \ + src/www/hawkeye/aliases/edit.tpl \ + src/www/hawkeye/aliases/confirmdelete.tpl hawkeyetpldir = $(htdocsdir)/hawkeye -dist_hawkeyetpl_DATA := \ +dist_hawkeyetpl_DATA = \ src/www/hawkeye/footer.tpl \ src/www/hawkeye/header.tpl @@ -386,13 +421,13 @@ dist_noinst_SCRIPTS += \ templatesdir = $(pkgdatadir)/templates -dist_templates_DATA := \ +dist_templates_DATA = \ src/www/templates/month-view.html \ src/www/templates/event.html exampledir = $(pkgdatadir)/examples -example_DATA := \ +example_DATA = \ src/www/bongo.conf dist_noinst_DATA += \ @@ -418,7 +453,7 @@ src/www/bongo-devel.conf: src/www/bongo.conf.in Makefile -e "s%\@DATADIR\@/\@PACKAGE\@/hawkeye%${top_srcdir}/src/www/hawkeye%" \ $< > $@ -po2json := $(top_srcdir)/src/www/l10n/po2json +po2json = $(top_srcdir)/src/www/l10n/po2json src/www/l10n/%.js: po/bongo-web/%.mo config.status $(po2json) -p po/bongo-web/$*.po -o $@ diff --git a/src/www/bongo-standalone.py b/src/www/bongo-standalone.py index d47877d..1deaef8 100755 --- a/src/www/bongo-standalone.py +++ b/src/www/bongo-standalone.py @@ -26,7 +26,9 @@ import bongo.dragonfly.Auth import bongo.commonweb.BongoUtil import bongo.commonweb.BongoSession as BongoSession import bongo.hawkeye.Auth +import bongo.sundial.Auth from bongo.hawkeye.HawkeyePath import HawkeyePath +from bongo.sundial.SundialPath import SundialPath from bongo.external.simplejson import loads, dumps import Cookie @@ -179,28 +181,63 @@ class DragonflyHandler(SimpleHTTPRequestHandler): rp = HawkeyePath(req) handler = rp.GetHandler() + req.log.debug("Got handler and stuff. Getting session...") + req.session = BongoSession.Session(req) req.session.load() + req.log.debug("Checking we need auth:") + if handler.NeedsAuth(rp): + req.log.debug("Yup!") auth = bongo.hawkeye.Auth.authenhandler(req) if auth != bongo.commonweb.HTTP_OK: - target = "/admin/login?%s" % req.uri - self.send_response( - bongo.commonweb.BongoUtil.redirect(req, target)) + target = "/admin/login" + self.send_response(bongo.commonweb.BongoUtil.redirect(req, target)) return + else: + req.log.debug("Nope.") - req.log.debug("request for %s (handled by %s)", req.uri, handler) + req.log.debug("request for %s (handled by %s)" % (req.uri, handler)) mname = rp.action + "_" + req.method + hackymethod = False + + req.log.debug("Doing attr check on %s (%s)" % (handler, mname)) + req.log.debug("Action was: %s" % rp.action) + req.log.debug("View was: %s" % rp.view) if not hasattr(handler, mname): - req.log.debug("%s has no %s", handler, mname) - self.send_response(bongo.commonweb.HTTP_NOT_FOUND) - return + req.log.debug("Handler: %s", handler) + req.log.debug("RP: %s", rp) + if rp.view == "agents": + # Special case for agents view + hackymethod = True + if req.method == "POST": + mname = "saveConfig" + else: + mname = "showConfig" + elif rp.view == "aliases": + # Special case for domains + hackymethod = True + else: + req.log.debug("%s has no %s" % (handler, mname)) + self.send_response(bongo.commonweb.HTTP_NOT_FOUND) + return + + req.log.debug("Getting attributes...") method = getattr(handler, mname) - ret = method(req, rp) + if hackymethod: + req.log.debug("Running new way.") + ret = method(rp.action, req, rp) + else: + req.log.debug("Running normal way.") + ret = method(req, rp) + + if ret is None: + req.log.debug("Handler %s returned invalid value: None" % handler) + return bongo.commonweb.OK if ret is None: self.send_response(bongo.commonweb.HTTP_OK) @@ -208,33 +245,36 @@ class DragonflyHandler(SimpleHTTPRequestHandler): self.send_response(ret) return - if self.path.startswith("/dav"): - handler = DavHandler() - print "running %s" % (self.command) - mname = "do_" + self.command - if not hasattr(handler, mname): - self.send_error(501, "Unsupported method (%r)" % self.command) - return - method = getattr(handler, mname) + if self.path.startswith("/calendars"): self.dragonfly_req = True - req = HttpRequest(self, "/dav", self.server) + req = HttpRequest(self, "/calendars", self.server) self.req = req - auth = bongo.dragonfly.Auth.authenhandler(self.req) - if auth != bongo.commonweb.HTTP_OK: - print "no auth" - self.send_error(auth) - return auth - if req.user == None : - req.headers_out["WWW-Authenticate"] = "Basic realm=\"Bongo\"" - self.send_error(bongo.commonweb.HTTP_UNAUTHORIZED) - return bongo.commonweb.HTTP_UNAUTHORIZED - - print "user: %s" % (req.user) + rp = SundialPath(req) + handler = rp.GetHandler(req, rp) + + if handler.NeedsAuth(rp): + if req.user is None: + self.req.headers_out["WWW-Authenticate"] = "Basic realm=\"Bongo\"" + self.send_error(bongo.commonweb.HTTP_UNAUTHORIZED) + return bongo.commonweb.HTTP_UNAUTHORIZED + else: + auth = bongo.sundial.Auth.authenhandler(req) + + req.log.debug("request for %s (handled by %s)", req.uri, handler) + + mname = "do_" + req.method + + if not hasattr(handler, mname): + req.log.debug("%s has no %s", handler, mname) + self.send_response(bongo.commonweb.HTTP_NOT_FOUND) + return + + method = getattr(handler, mname) try: - print "running method" - ret = method(self.req) + print "running" + ret = method(req, rp) except HttpError, e: print "http error" self.send_error(e.code) @@ -244,11 +284,12 @@ class DragonflyHandler(SimpleHTTPRequestHandler): print "error" self.send_error(bongo.commonweb.HTTP_INTERNAL_SERVER_ERROR) return - - if ret is None: - print "valid response!" - self.send_response(bongo.commonweb.HTTP_OK) + + if str(ret).startswith('20'): + print "Valid response!" + self.send_response(ret) else: + print "Uh oh. Bad response:" self.send_response(ret) return diff --git a/src/www/bongo/commonweb/ElementTree.py b/src/www/bongo/commonweb/ElementTree.py new file mode 100644 index 0000000..e478872 --- /dev/null +++ b/src/www/bongo/commonweb/ElementTree.py @@ -0,0 +1,17 @@ +## Helper functions for use with etree. + +import lxml.etree as ET + +## Returns a normalized version of the tag name. +# @param name Tag name. +# +# This does two things: remove the way ElementTree handles XML +# namespaces, and put the text into lowercase. +def normalize(name): + if name[0] == "{": + uri, tag = name[1:].split("}") + output = uri + ":" + tag + else: + output = name + + return output.lower() diff --git a/src/www/bongo/commonweb/Standalone.py b/src/www/bongo/commonweb/Standalone.py index 8afd96d..84a46e7 100644 --- a/src/www/bongo/commonweb/Standalone.py +++ b/src/www/bongo/commonweb/Standalone.py @@ -1,6 +1,8 @@ import os import sys +import base64 + import Cookie import StringIO import logging @@ -23,7 +25,8 @@ class HttpRequest: log = logging.getLogger("Dragonfly") options = { "DragonflyUriRoot" : "/user", "HawkeyeTmplRoot" : None, # determine this later - "HawkeyeUriRoot" : "/admin"} + "HawkeyeUriRoot" : "/admin", + "SundialUriRoot" : "/calendars"} def __init__(self, req, path, server=HttpServer()): self.oldreq = req @@ -38,7 +41,15 @@ class HttpRequest: else: self.uri, self.args = req.path.split("?", 1) - self.user = None + # TODO Review this. This needs updating, but it "works for now". + auth_header = self.headers_in.get("Authorization", None) + if auth_header and auth_header[:5] == "Basic": + userpassencoded = auth_header[6:] + userpass = base64.b64decode(userpassencoded) + self.user = userpass[:userpass.find(":")] + self._password = userpass[(userpass.find(":")+1):] + else: + self.user = None self.sent_bodyct = 0 self.wbuf = StringIO.StringIO() @@ -85,3 +96,6 @@ class HttpRequest: def write(self, str, *args, **kwargs): self.sent_bodyct += len(str) return self.wbuf.write(str) + + def get_basic_auth_pw(self): + return self._password diff --git a/src/www/bongo/dragonfly/Auth.py b/src/www/bongo/dragonfly/Auth.py index c8d78b3..4bd5b79 100644 --- a/src/www/bongo/dragonfly/Auth.py +++ b/src/www/bongo/dragonfly/Auth.py @@ -5,8 +5,6 @@ import logging import pprint import time -from libbongo.libs import mdb -from libbongo.libs import msgapi from bongo.store.StoreClient import StoreClient from bongo.store.StoreConnection import StoreConnection import bongo @@ -37,12 +35,9 @@ def GetCredentials(req): return autz[len(basic)+1:] def CheckAuthCookie(username, cookie): - addr = msgapi.FindUserNmap(username) - if addr is None: - # this is likely because the user does not exist - return False; - host, port = addr - + host = "localhost" + port = 689 + ret = False conn = None @@ -59,9 +54,19 @@ def CheckUserPass(username, password): # shortcut some failure cases, so we don't have to hit MDB if username is None or password is None: return False - dn = msgapi.FindObject(username) - handle = msgapi.DirectoryHandle() - return mdb.mdb_VerifyPassword(handle, dn, password) + #dn = msgapi.FindObject(username) + #handle = msgapi.DirectoryHandle() + #return mdb.mdb_VerifyPassword(handle, dn, password) + + store = None + try: + store = StoreClient(username, username, authPassword=password) + store.Quit() + return True + except: + if store is not None: + store.Quit() + return False def GetUserPass(creds): return base64.decodestring(creds).split(":") @@ -128,9 +133,9 @@ def AcceptCredentials(req): # different cookie libs give us different results?! if authCookieName: - authCookie = reqCookies.get(authCookieName, None) + authCookie = reqCookies.get(authCookieName.replace("@", "%40"), None) if not authCookie: - authCookie = reqCookies.get(authCookieName.lower(), None) + authCookie = reqCookies.get(authCookieName.lower().replace("@", "%40"), None) if not authCookie: req.log.debug("Unable to get cookie %s for %s", authCookieName, currentUser) @@ -153,6 +158,8 @@ def AcceptCredentials(req): return False authCookieName = GetAuthCookieName(credUser) + # Escape the cookie name (incase the user's name has funny chars) + authCookieName = authCookieName.replace("@", "%40") req.log.debug("adding auth cookie: %s", authCookieName) Cookie.add_cookie(req, authCookieName, newCookie, path="/") @@ -178,7 +185,7 @@ def AcceptCredentials(req): if ver is None: req.log.debug("adding currentUser cookie") # expire in one hour - Cookie.add_cookie(req, "currentUser", currentUser, + Cookie.add_cookie(req, "currentUser", currentUser.replace("@", "%40"), path=req.uri, expires=time.time()+3600) req.user = currentUser diff --git a/src/www/bongo/dragonfly/MailView.py b/src/www/bongo/dragonfly/MailView.py index ad2ad8c..306f10f 100644 --- a/src/www/bongo/dragonfly/MailView.py +++ b/src/www/bongo/dragonfly/MailView.py @@ -267,7 +267,7 @@ class ConversationsHandler(ResourceHandler): def _PropsToJson(self, props): jsob = {} - jsob["date"] = props["nmap.conversation.date"]; + jsob["date"] = props.get("nmap.conversation.date") mfrom = props.get("bongo.from") @@ -281,7 +281,7 @@ class ConversationsHandler(ResourceHandler): jsob["subject"] = props.get("bongo.conversation.subject", props.get("nmap.conversation.subject", "")) jsob["unread"] = int(props.get("nmap.conversation.unread", 1)) jsob["count"] = int(props.get("nmap.conversation.count", 1)) - jsob["snippet"] = "there is no snippet."; + jsob["snippet"] = "there is no snippet." return jsob def _MsgToJson(self, store, msg, props): @@ -1027,23 +1027,8 @@ class ContactsHandler(ConversationsHandler): class ToMeHandler(ConversationsHandler): def _GetMyContact(self, store): - email = msgapi.GetUserEmailAddress(store.owner) - try: - prefs = self._JsonToObj(store.Read("/preferences/dragonfly")) - if not prefs.has_key("addressbook") \ - or not prefs["addressbook"].has_key("me"): - return [ email ] - - jsob = self._JsonToObj(store.Read(prefs["addressbook"]["me"])) - except: - return [ email ] - - emails = AddressbookContactsHandler.GetContactAddresses(jsob) - for address in emails: - if address == email: - return emails - emails.append(email) - return emails + # FIXME: Deprecated + return None def GetToMeQuery (self, store) : a = self._GetMyContact(store) diff --git a/src/www/bongo/dragonfly/PreferencesView.py b/src/www/bongo/dragonfly/PreferencesView.py index 8288ebe..eab372c 100644 --- a/src/www/bongo/dragonfly/PreferencesView.py +++ b/src/www/bongo/dragonfly/PreferencesView.py @@ -33,14 +33,6 @@ class DragonflyHandler(ResourceHandler): else: raise - email = msgapi.GetUserEmailAddress(req.user) - if email: - name = msgapi.GetUserDisplayName(req.user) - if name: - email = '%s <%s>' % (name, email) - - req.headers_out["X-Bongo-Address"] = email - if rp.extension == "json": return self._SendJsonText(req, stream) @@ -161,8 +153,9 @@ class RulesHandler(ResourceHandler): } def do_GET(self, req, rp): - dn = msgapi.FindObject(req.user) - mdbrules = msgapi.GetUserFeature(dn, "rules", "BongoRule") + # FIXME: FindObject is deprecated + # dn = msgapi.FindObject(req.user) + # mdbrules = msgapi.GetUserFeature(dn, "rules", "BongoRule") if not mdbrules : mdbrules = [] diff --git a/src/www/bongo/dragonfly/ResourcePath.py b/src/www/bongo/dragonfly/ResourcePath.py index 41e54e4..0f83af4 100644 --- a/src/www/bongo/dragonfly/ResourcePath.py +++ b/src/www/bongo/dragonfly/ResourcePath.py @@ -14,7 +14,8 @@ class ResourcePath: "mail" : 1, "preferences" : 1, "search" : 1, - "summary" : 1} + "summary" : 1, + "sendlog" : 0} def __init__(self, req): self.req = req @@ -117,6 +118,9 @@ class ResourcePath: def GetHandler(self): handler = None + + print "View is " + self.view + if self.view == "addressbook" and self.handler == "contacts": handler = AddressbookView.ContactsHandler() elif self.view == "calendar" and self.handler == "events": @@ -137,6 +141,8 @@ class ResourcePath: handler = PreferencesView.RulesHandler() elif self.view == "summary" and self.handler == "summary": handler = SummaryView.SummaryHandler() + elif self.view == "sendlog": + handler = SummaryView.LogHandler() if handler is None: raise HttpError(bongo.commonweb.HTTP_NOT_FOUND) diff --git a/src/www/bongo/dragonfly/SummaryView.py b/src/www/bongo/dragonfly/SummaryView.py index 96766ee..0fe7110 100644 --- a/src/www/bongo/dragonfly/SummaryView.py +++ b/src/www/bongo/dragonfly/SummaryView.py @@ -284,3 +284,35 @@ class SummaryHandler(ResourceHandler): except: store.Quit() raise + +#TODO: Put this in a seperate file. +class LogHandler(ResourceHandler): + def get_slexy_dest(self, data): + rawloc = data.find("/raw/") + if rawloc == -1: + return "BAD-RESP" + else: + rawloc += 5 + return data[rawloc:rawloc + 10] + + def do_POST(self, req, rp): + #rp.handlerData = { "contents" : "just a test.", + # "desc": "testing stuff" } + + print rp.handlerData + + # FIXME: This is buggered atm since rp.handlerData always returns { } + # for some retarded reason. Look into this. + if rp.handlerData.has_key("contents") and rp.handlerData.has_key("desc"): + try: + import urllib + params = urllib.urlencode({"raw_paste" : rp.handlerData["contents"], "language" : "text", "submit" : "Submit Paste", "desc" : rp.handlerData["desc"]}) + f = urllib.urlopen("http://slexy.org/index.php/submit", params) + req.write(self.get_slexy_dest(f.read())) + except ImportError, e: + # Tell client about missing dep and why we failed + req.write("URLLIB") + else: + req.write("FAIL") + + return bongo.commonweb.OK diff --git a/src/www/bongo/hawkeye/AgentView.py b/src/www/bongo/hawkeye/AgentView.py index 6c38ca2..13d9b57 100644 --- a/src/www/bongo/hawkeye/AgentView.py +++ b/src/www/bongo/hawkeye/AgentView.py @@ -1,63 +1,257 @@ import bongo.commonweb import bongo.commonweb.BongoUtil -from bongo.store.StoreClient import StoreClient, DocTypes -import bongo.external.simplejson as simplejson from HawkeyeHandler import HawkeyeHandler +# Status of operation output (if any). doneop = 0 -class AgentHandler(HawkeyeHandler): +# Agent definitions +agentdefs = { + 'global' : { + 'label' : 'Global', + 'description' : 'This page describes the global configuration options available in your Bongo installation.\nOptions here will be used in most agents where required.', + 'filename' : '/config/global', + 'data' : { + 'hostname' : { 'label' : 'Hostname', 'type' : 'string' }, + 'hostaddr' : { 'label' : 'Host address', 'type' : 'string' }, + 'postmaster' : { 'label' : 'Postmaster', 'type' : 'string' } + } + }, + 'bongoantispam' : { + 'label' : 'Antispam', + 'filename' : '/config/antispam', + 'data' : { + 'timeout' : { 'label' : 'Timeout', 'type' : 'int', 'suffix' : 'milliseconds' }, + 'hosts' : { 'label' : 'Hosts', 'type' : 'hostlist,783' } + } + }, + 'bongoqueue' : { + 'label' : 'Queue', + 'filename' : '/config/queue', + 'data' : { + 'forwardundeliverable_enabled' : { 'label' : 'Forward undeliverable mail', 'type' : 'bool' }, + 'forwardundeliverable_to' : { 'label' : 'Forward undeliverable mail to', 'type' : 'string' }, + 'bouncereturn' : { 'label' : 'Return mail on bounce', 'type' : 'bool' }, + 'bounceccpostmaster' : { 'label' : 'CC postmaster on bounce', 'type' : 'bool' }, + 'queuetimeout' : { 'label' : 'Queue timeout', 'type' : 'int', 'suffix' : 'seconds' }, + 'quotamessage' : { 'label' : 'Quota message', 'type' : 'string' } + } + }, + 'bongoavirus' : { + 'label' : 'Antivirus', + 'filename' : '/config/antivirus', + 'data' : { + 'timeout' : { 'label' : 'Timeout', 'type' : 'int', 'suffix' : 'milliseconds' }, + 'hosts' : { 'label' : 'Hosts', 'type' : 'hostlist,783' } + } + }, + 'bongosmtp' : { + 'label' : 'SMTP', + 'filename' : '/config/smtp', + 'data' : { + 'port' : { 'label' : 'Port', 'type' : 'int' }, + 'port_ssl' : { 'label' : 'SSL Port', 'type' : 'int' }, + 'max_mx_servers' : { 'label' : 'Maximum MX servers', 'type' : 'int' }, + 'socket_timeout' : { 'label' : 'Socket timeout', 'type' : 'int' }, + 'maximum_recipients' : { 'label' : 'Maximum recipients', 'type' : 'int' }, + 'message_size_limit' : { 'label' : 'Message size limit', 'type' : 'int', 'suffix' : 'bytes (0 for no limit)' }, + 'allow_client_ssl' : { 'label' : 'Allow client SSL', 'type' : 'bool' }, + 'max_thread_load' : { 'label' : 'Maximum threads', 'type' : 'int' } + } + }, + 'bongopop3' : { + 'label' : 'POP3', + 'filename' : '/config/pop3', + 'data' : { + 'port' : { 'label' : 'Port', 'type' : 'int' }, + 'port_ssl' : { 'label' : 'SSL Port', 'type' : 'int' } + } + }, + 'bongoimap' : { + 'label' : 'IMAP', + 'filename' : '/config/imap', + 'data' : { + 'port' : { 'label' : 'Port', 'type' : 'int' }, + 'port_ssl' : { 'label' : 'SSL Port', 'type' : 'int' }, + 'threads_max' : { 'label' : 'Maximum threads', 'type' : 'int' } + } + }, + 'bongomailprox' : { + 'label' : 'Mail proxy', + 'filename' : '/config/mailproxy', + 'data' : { + 'max_threads' : { 'label' : 'Maximum threads', 'type' : 'int' }, + 'interval' : { 'label' : 'Fetch interval', 'type' : 'int', 'suffix' : 'minutes' }, + 'max_accounts' : { 'label' : 'Maximum accounts', 'type' : 'int' } + } + } +} + +class AgentHandler(HawkeyeHandler): + def index_GET(self, req, rp): - global doneop - + ''' + Handler for main agent list view. + ''' + global doneop, agentdefs + + # Loop through agent defs and make a list to display + agentlist = [ ] + for agent in agentdefs: + pa = { } + pa["url"] = "agents/" + agent + pa["rname"] = agentdefs[agent]["label"] + pa["img"] = "../img/agent-" + agent + ".png" + agentlist.append(pa) + self.SetVariable("agentlist", agentlist) + self.SetVariable("success", 1) + self.SetVariable("error", None) + self.SetVariable("dremove", None) + + # Setup the all clear if we saved some stuff. if doneop: self.SetVariable("opsuccess", 1) doneop = 0 else: self.SetVariable("opsuccess", 0) + # Usual template cruft - setup tab and spit the page out. self.SetVariable("agntab", "selecteditem") - return self.SendTemplate(req, rp, "index.tpl") + return self.SendTemplate(req, rp, "index.tpl", title="Agents") + + ############### CONFIGURATION HELPERS ################ + + def saveConfig(self, agentname, req, rp): + global doneop, agentdefs - def index_POST(self, req, rp): - global doneop + self.SetStoreData(req, agentdefs[agentname]['filename'], self.setAgent(self.GetStoreData(req, agentdefs[agentname]['filename']), req.form, agentdefs[agentname]['data'])) - if not req.form: - return bongo.commonweb.HTTP_UNAUTHORIZED - - if not req.form.has_key("command"): - return bongo.commonweb.HTTP_UNAUTHORIZED - - # Operation completed OK. doneop = 1 - return self.index_GET(req, rp) + return self.showConfig(agentname, req, rp) - def _getAntispam(self, req): - config = {} - store = None - decoder = simplejson.JSONDecoder() - try: - store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) - store.Store("_system") - configfile = store.Read("/config/antispam") - config = decoder.decode(configfile) - store.Quit() - except: - if store: - store.Quit() - return None - + def setAgent(self, config, rf, agent): + for key in rf: + value = rf[key].value + print "Has key: %s (value: %s)" % (key, value) + + # Mm, value-type formatting. + # Note: keys with type 'string' remain unchanged. + if agent[key]['type'] == 'int': + value = int(value) + elif agent[key]['type'] == 'bool': + value = bool(value) + elif agent[key]['type'].startswith('array,') or agent[key]['type'].startswith('hostlist,'): + # Split value type and determine what kind of array/default port + arraytype = agent[key]['type'].split(',')[1] + + # Now, split input data into an array, and change valuetypes as required. + # Input data for this key should be a comma-seperated string of values. + arraydata = value.split(",") + for dobj in arraydata: + if arraytype == "int": + dobj = int(dobj) + elif arraytype == "bool": + dobj = bool(dobj) + elif agent[key]['type'].startswith('hostlist,'): + # It's a hostlist, and arraytype is the default port + # Check if value has port and/or weighting + defaultweight = 1 + defultport = arraytype + + if dobj.count(':') == 1: + # Port and hostname + dobj = dobj + ":" + defaultweight + elif dobj.count(':') == 0: + # Only hostname + dobj = dobj + ":" + defaultport + ":" + defaultweight + + # Otherwise, type was string (default). + + # Set the data back. + value = arraydata + + # Set new value. + config[key] = value + return config + + def showConfig(self, agentname, req, rp): + global agentdefs + return self.doAgent(agentname, self.GetStoreData(req, agentdefs[agentname]['filename']), agentdefs[agentname]['data'], req, rp) - def _setAntispam(self, req, obj): - encoder = simplejson.JSONEncoder() - store = None - try: - store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) - store.Store("_system") - configfile = encoder.encode(obj) - store.Replace("/config/antispam", configfile) - finally: - if store: - store.Quit() + def doAgent(self, agentname, config, d, req, rp): + ''' + Displays an agent configuration page, using information + provided via method arguments. + ''' + global doneop, agentdefs + rkeys = [] + + if config != None: + for key in config: + # Disallow other keys that weren't passed along (eg version, etc) + if d.has_key(key): + nkey = {} + nkey["id"] = key + nkey["value"] = config[key] + nkey["name"] = d[key]['label'] + ":" + if d[key].has_key('suffix'): + nkey["suffix"] = d[key]['suffix'] + + if d[key]['type'] == "int": + nkey["numericentry"] = True + elif d[key]['type'] == "bool": + nkey["boolentry"] = True + elif d[key]['type'] == "string": + nkey["textentry"] = True + elif d[key]['type'].startswith('array,') or d[key]['type'].startswith('hostlist,'): + nkey["selectentry"] = True + # TODO: Fix this so we can have plain lists, instead of arrays + nkey["jsadd"] = "javascript:addToList('" + key + "');" + nkey["jsrm"] = "javascript:removeFromList('" + key + "');" + nkey["jsid"] = key + "-removebtn" + nkey["selectorid"] = key + "-box" + nkey["revertbox"] = key + "-normal" + nkey["revertjs"] = "$('" + nkey["revertbox"] + "').hide(); $('" + nkey["selectorid"] + "').show();" + + strthingy = "" + for value in config[key]: + strthingy += value + "," + + nkey["strvalue"] = strthingy + + rkeys.append(nkey) + + self.SetVariable("settinglist", rkeys) + + # Setup desc if agent def has one + if agentdefs[agentname].has_key('description'): + self.SetVariable("description", agentdefs[agentname]["description"]) + else: + # Set as empty (may have been set from previous agent) + self.SetVariable("description", None) + + # Reset variable that may have been incorrectly set earlier + self.SetVariable("success", 1) + self.SetVariable("error", None) + else: + self.SetVariable("success", 0) + self.SetVariable("settinglist", None) + + # Check if we've done stuff (ie saving config) + if doneop: + self.SetVariable("opsuccess", 1) + doneop = 0 + + # Setup action history + store = self.EventHistory(req, "Modified agent " + agentdefs[agentname]["label"], "agents/" + agentname) + + else: + self.SetVariable("opsuccess", 0) + + self.SetVariable("agntab", "selecteditem") + self.SetVariable("name", agentname) + self.SetVariable("hname", agentdefs[agentname]["label"]) + self.SetVariable("dremove", None) + return self.SendTemplate(req, rp, "agentview.tpl", title=agentdefs[agentname]["label"]) diff --git a/src/www/bongo/hawkeye/AliasView.py b/src/www/bongo/hawkeye/AliasView.py new file mode 100644 index 0000000..c7ec0f3 --- /dev/null +++ b/src/www/bongo/hawkeye/AliasView.py @@ -0,0 +1,179 @@ +import bongo.commonweb +import bongo.commonweb.BongoUtil +from bongo.store.StoreClient import StoreClient, DocTypes +import bongo.external.simplejson as simplejson +from HawkeyeHandler import HawkeyeHandler + +storePath = "/config/aliases" + +class AliasHandler(HawkeyeHandler): + def index_GET(self, req, rp): + global storePath + # Fetch list of current domains setup + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store("_system") + domains = store.List(storePath, ["nmap.document"]) + + # Make listy + ret = [] + for domain in domains: + # Ignore magic .svn file for devel installs (workaround bug in bongo-config) + if domain.filename.endswith("/.svn") != True: + obj = { } + obj["name"] = domain.filename.replace(storePath + "/", "") + print "Domain was: %s" % domain.filename + #print "Dir of domain: %s" % dir(domain) + obj["deletelink"] = "delete/" + domain.uid + obj["editlink"] = "edit/" + domain.uid + ret.append(obj) + + # Send template foo. + #self.SetVariable("error", None) + self.SetVariable("info", None) + self.SetVariable("domainlist", ret) + self.SetVariable("systab", "selecteditem") + store.Quit() + return self.SendTemplate(req, rp, "index.tpl", title="Domains") + + def index_POST(self, req, rp): + return bongo.commonweb.HTTP_UNAUTHORIZED + + def add_GET(self, req, rp): + self.SetVariable("newmode", True) + return self.SendTemplate(req, rp, "edit.tpl", title="Adding new domain") + + def add_POST(self, req, rp): + return self.edit_POST(req, rp, addMode=True) + + def edit_GET(self, req, rp): + global storePath + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store("_system") + info = store.Info(rp.path) + print "Doc info: %s" % info + #print "Actions on doc info: %s" % dir(info) + + print "Doc filename: %s" % info.filename + + self.SetVariable("error", None) + self.SetVariable("dremove", None) + + # Template stuff + #domainName = info.filename.replace(storePath + "/", "") + domainName = info.filename + + # Fetch data and set template variables + dataobj = store.Read(storePath + "/" + info.filename) + decoder = simplejson.JSONDecoder() + data = { } + try: + data = decoder.decode(dataobj) + except ValueError: + print "Oh darn, JSON parsing failed. Either crap JSON was in the file, or there's nothing to begin with." + + if data.has_key("domainalias"): + domainalias = data["domainalias"] + else: + domainalias = None + + if data.has_key("aliases"): + aliases = data["aliases"] + else: + aliases = { } + tpl_aliases = [ ] + aliases_txt = "" + + # Convert aliases to = list + for alias in aliases: + magicstr = "%s=%s" % (alias, aliases[alias]) + tpl_aliases.append(magicstr) + aliases_txt += (magicstr + ",") + + # Mmm, templates + if domainalias != None and domainalias != "": + self.SetVariable("domainwide", "checked") + else: + self.SetVariable("domainwide", None) + + self.SetVariable("useraliasestxt", aliases_txt) + self.SetVariable("useraliases", tpl_aliases) + self.SetVariable("domainalias", domainalias) + self.SetVariable("name", domainName) + self.SetVariable("newmode", False) + store.Quit() + return self.SendTemplate(req, rp, "edit.tpl", title="Editing " + domainName) + + def edit_POST(self, req, rp, addMode=False): + global storePath + + # Get stuff from request URI. + if addMode: + # Set later in form loop + domainGuid = "" + else: + domainGuid = rp.path + + self.SetVariable("error", None) + self.SetVariable("info", None) + self.SetVariable("dremove", None) + + config = { } + + # Put together some sort of config wha-hoozle to fo-shizzle later. + form = req.form + for key in form: + value = form[key].value + if key == "name" and addMode: + print "Name was %s" % value + domainGuid = value + rp.path = storePath + "/" + value + print "new path: %s" % rp.path + if key == "domainwide": + # This is the checkbox thingy + print "Checkbox value returned was: " + value + elif key == "domainalias": + # Actual domain alias val + config["domainalias"] = value + elif key == "useralias": + # User aliases + # Split this, and set array as value. + # eg we get input of "user=domain,user1=domain2" + commasplit = value.split(",") + userlist = { } + for entry in commasplit: + tempy = entry.split("=") + if len(tempy) == 2: + userlist[tempy[0]] = tempy[1] + + print "userlist: %s" % userlist + config["aliases"] = userlist + + # Write the fo-shizzle. + rp.path = self.SetStoreData(req, domainGuid, config, create=addMode, newcollection=storePath) + + # Stop using made up words and sent stuff back to the user to look at. + if addMode: + return bongo.commonweb.BongoUtil.redirect(req, "edit/" + rp.path) + else: + self.SetVariable("info", "Updated domain successfully.") + return self.edit_GET(req, rp) + + def delete_GET(self, req, rp): + self.SetVariable("error", None) + self.SetVariable("info", None) + self.SetVariable("dremove", None) + return self.SendTemplate(req, rp, "confirmdelete.tpl", title="Deleting domain") + + def delete_POST(self, req, rp): + # Assume on post that we accept your battle challenge! + + try: + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store("_system") + store.Delete(rp.path) + store.Quit() + self.SetVariable("dremove", "Domain removed successfully.") + except Exception, e: + self.SetVariable("error", "Failed to delete domain %s." % rp.path) + + return bongo.commonweb.BongoUtil.redirect(req, "../../") diff --git a/src/www/bongo/hawkeye/AntispamView.py b/src/www/bongo/hawkeye/AntispamView.py deleted file mode 100644 index 69c0273..0000000 --- a/src/www/bongo/hawkeye/AntispamView.py +++ /dev/null @@ -1,113 +0,0 @@ -import bongo.commonweb -import bongo.commonweb.BongoUtil -from bongo.store.StoreClient import StoreClient, DocTypes -import bongo.external.simplejson as simplejson -from HawkeyeHandler import HawkeyeHandler - -doneop = 0 - -class AntispamHandler(HawkeyeHandler): - def NeedsAuth(self, rp): - return True - - def index_GET(self, req, rp): - global doneop - config = self._getAntispam(req) - - if doneop: - self.SetVariable("opsuccess", 1) - doneop = 0 - else: - self.SetVariable("opsuccess", 0) - - nosetcheck = 0 - - # Set values to display back - if config != None and config.has_key("enabled"): - self.SetVariable("success", 1) - if len(config) < 3: - nosetcheck = 1 - else: - nosetcheck = 0 - - for key in config: - if key == "timeout": - if int(config[key]) > 1: - self.SetVariable("timeout", config[key]) - elif key == "host": - hval = config[key].split(':', 3) - if len(hval) > 1: - self.SetVariable("host", hval[0]) - self.SetVariable("port", hval[1]) - - if nosetcheck == 1: - self.SetVariable("error", "Antispam is not currently set up. Please enter the correct values below or accept the defaults, and click 'Save'.") - - # Defaults (TODO: move back into store) - self.SetVariable("timeout", 20) - self.SetVariable("host", "127.0.0.1") - self.SetVariable("port", 783) - else: - self.SetVariable("error", 0) - self.SetVariable("success", 1) - else: - self.SetVariable("success", 0) - self.SetVariable("error", "Unable to read configuration information from the Bongo store. Are you logged in as a user with administrative permissions?") - - self.SetVariable("agntab", "selecteditem") - - return self.SendTemplate(req, rp, "index.tpl") - - def index_POST(self, req, rp): - global doneop - - config = self._getAntispam(req) - if config != None: - for key in req.form: - if key == "timeout": - config["timeout"] = int(req.form[key].value); - elif key == "host": - config["host"] = req.form[key].value; - elif key == "port": - config["host"] += ":" + req.form[key].value; - - # Set weight (always 1 since we can only handle 1 host) - config["host"] += ":1" - else: - config = "{ version: 1, enabled: 1, timeout: 20, host: \"127.0.0.1:783:1\" }" - - self._setAntispam(req, config) - # Operation completed OK. - doneop = 1 - - return self.index_GET(req, rp) - - def _getAntispam(self, req): - config = {} - store = None - decoder = simplejson.JSONDecoder() - try: - store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) - store.Store("_system") - configfile = store.Read("/config/antispam") - config = decoder.decode(configfile) - store.Quit() - except: - if store: - store.Quit() - return None - - return config - - def _setAntispam(self, req, obj): - encoder = simplejson.JSONEncoder() - store = None - try: - store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) - store.Store("_system") - configfile = encoder.encode(obj) - store.Replace("/config/antispam", configfile) - finally: - if store: - store.Quit() - diff --git a/src/www/bongo/hawkeye/BackupView.py b/src/www/bongo/hawkeye/BackupView.py index 73a1385..59452f1 100644 --- a/src/www/bongo/hawkeye/BackupView.py +++ b/src/www/bongo/hawkeye/BackupView.py @@ -14,7 +14,7 @@ class BackupHandler(HawkeyeHandler): today = datetime.date.today() self.SetVariable("set", today.strftime("%y%m%d")) self.SetVariable("systab", "selecteditem") - return self.SendTemplate(req, rp, "index.tpl") + return self.SendTemplate(req, rp, "index.tpl", title="Backup & Restore") def download_GET(self, req, rp): backup = "" diff --git a/src/www/bongo/hawkeye/HawkeyeHandler.py b/src/www/bongo/hawkeye/HawkeyeHandler.py index 5845fa4..3a83abe 100644 --- a/src/www/bongo/hawkeye/HawkeyeHandler.py +++ b/src/www/bongo/hawkeye/HawkeyeHandler.py @@ -1,11 +1,102 @@ import os from bongo.Template import Template +import bongo.external.simplejson as simplejson +from bongo.store.StoreClient import StoreClient, DocTypes import bongo.commonweb class HawkeyeHandler: def __init__(self): self._template = Template() - + + def GetStoreData(self, req, filename, storeName="_system"): + config = {} + store = None + decoder = simplejson.JSONDecoder() + try: + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store(storeName) + configfile = store.Read(filename) + config = decoder.decode(configfile) + store.Quit() + except ValueError, e: + self.SetVariable("error", "Failed to parse JSON.") + print "Failed to parse JSON: %s" % e + if store: + store.Quit() + return None + except Exception, e: + self.SetVariable("error", "Unable to read data from store: %s" % str(e)) + if store: + store.Quit() + return None + + return config + + def SetStoreData(self, req, filename, data, storeName="_system", create=False, newcollection=None): + encoder = simplejson.JSONEncoder() + store = None + try: + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store(storeName) + configfile = encoder.encode(data) + guid = 0 + if not create: + guid = store.Replace(filename, configfile) + else: + # Create document + print "Writing (not replacing) to %s..." % (newcollection + "/" + filename) + guid = store.Write(newcollection, 7, configfile, filename=filename) + + if store: + store.Quit() + return guid + except ValueError: + self.SetVariable("error", "Failed to parse JSON.") + if store: + store.Quit() + return False + except Exception, e: + self.SetVariable("error", "Unable to save data to store: %s" % str(e)) + if store: + store.Quit() + return False + + def EventHistory(self, req, desc, path): + config = {} + store = None + encoder = simplejson.JSONEncoder() + decoder = simplejson.JSONDecoder() + try: + store = StoreClient(req.session["credUser"], req.session["credUser"], authPassword=req.session["credPass"]) + store.Store("_system") + + # Fetch old data (if any) + datafile = store.Read("/hawkeye/history") + data = decoder.decode(datafile) + + # Now, move everything down one. + data["4"] = data["3"] + data["3"] = data["2"] + data["2"] = data["1"] + data["1"] = data["0"] + + # Put in new data in first slot + data["0"] = { 'desc' : desc, 'url' : path } + + # Save new data + datafile = encoder.encode(data) + store.Replace("/hawkeye/history", datafile) + + # Finish up + if store: + store.Quit() + return True + except Exception, e: + self.SetVariable("error", "Unable to set history: %s" % str(e)) + if store: + store.Quit() + return False + def NeedsAuth(self, rp): return True @@ -18,7 +109,13 @@ class HawkeyeHandler: def index(self, req, rp): return bongo.commonweb.OK - def SendTemplate(self, req, rp, file): + def SendTemplate(self, req, rp, file, title=None): + if title != None: + self.SetVariable("doctitle", "%s - Bongo Web Administration" % title) + else: + self.SetVariable("doctitle", "Bongo Web Administration") + + self.SetVariable("release", "M3") # TODO: Set this from Makefile. path = os.path.join(rp.tmplPath, file) req.content_type = "text/html" diff --git a/src/www/bongo/hawkeye/HawkeyePath.py b/src/www/bongo/hawkeye/HawkeyePath.py index 497bc84..682a0ac 100644 --- a/src/www/bongo/hawkeye/HawkeyePath.py +++ b/src/www/bongo/hawkeye/HawkeyePath.py @@ -7,10 +7,10 @@ from bongo.commonweb.HttpError import HttpError import RootView import AgentView -import AntispamView import BackupView import ServerView import SystemView +import AliasView views = { "root" : RootView.RootHandler(), @@ -18,11 +18,12 @@ views = { "backup" : BackupView.BackupHandler(), "system" : SystemView.SystemHandler(), "server" : ServerView.ServerHandler(), - "antispam" : AntispamView.AntispamHandler() + "aliases" : AliasView.AliasHandler() } class HawkeyePath: def __init__(self, req): + print "Creating new HawkeyePath from: %s" % req self.req = req self.view = self.action = self.path = None @@ -75,9 +76,15 @@ class HawkeyePath: global views if views.has_key(self.view): + print "Found handler %s, using." % self.view handler = views[self.view] else: - raise HttpError(bongo.commonweb.HTTP_NOT_FOUND) + if self.view == "agents": + print "Using default crap handler" + handler = views["agents"] + else: + print "Yay, we 404ed while getting the handler" + raise HttpError(bongo.commonweb.HTTP_NOT_FOUND) handler.ParsePath(self) diff --git a/src/www/bongo/hawkeye/RootView.py b/src/www/bongo/hawkeye/RootView.py index 76cf96e..df7cd4c 100644 --- a/src/www/bongo/hawkeye/RootView.py +++ b/src/www/bongo/hawkeye/RootView.py @@ -59,15 +59,39 @@ class RootHandler(HawkeyeHandler): sw_current = "%d" % build_ver if build_custom: sw_current += " (custom build)" - sw_available = msgapi.GetAvailableVersion() self.SetVariable("sw_current", sw_current) - if (sw_available - build_ver) > 9: - self.SetVariable("sw_upgrade", 1) - if sw_available == 0: - sw_available = "Unknown (no network, or DNS failure)" + + #sw_available = msgapi.GetAvailableVersion() + #if (sw_available - build_ver) > 9: + #self.SetVariable("sw_upgrade", 1) + #if sw_available == 0: + #sw_available = "Unknown (no network, or DNS failure)" + + sw_available = "Disabled" self.SetVariable("sw_available", sw_available) + + # Get last few actions + actions = self.GetStoreData(req, "/hawkeye/history") + sortedacts = sorted(actions) + + print "actions: %s" % actions + + act = [] + for actid in sortedacts: + obj = { } + action = actions[actid] + if action["desc"] != "" and action["desc"] != None: + obj["href"] = "/admin/" + action["url"] + obj["title"] = action["desc"] + obj["img"] = None + act.append(obj) + + #print "Act: %s" % act + # send the template - return self.SendTemplate(req, rp, "index.tpl") + self.SetVariable("actionlist", act) + self.SetVariable("dremove", None) + return self.SendTemplate(req, rp, "index.tpl", title="Desktop") def login_GET(self, req, rp): global AuthMode @@ -84,6 +108,7 @@ class RootHandler(HawkeyeHandler): self.SetVariable("badauth", 0) self.SetVariable("loggedout", 0) + self.SetVariable("dremove", None) return self.SendTemplate(req, rp, "login.tpl") def login_POST(self, req, rp): diff --git a/src/www/bongo/hawkeye/Server.py b/src/www/bongo/hawkeye/Server.py index 574174f..cb11cd3 100644 --- a/src/www/bongo/hawkeye/Server.py +++ b/src/www/bongo/hawkeye/Server.py @@ -32,32 +32,60 @@ def handler(req): rp = HawkeyePath(req) handler = rp.GetHandler() + req.log.debug("Got handler and stuff. Getting session...") + req.session = BongoSession.Session(req) req.session.load() + req.log.debug("Checking we need auth:") + if handler.NeedsAuth(rp): + req.log.debug("Yup!") auth = bongo.hawkeye.Auth.authenhandler(req) if auth != bongo.commonweb.HTTP_OK: target = "/admin/login" BongoUtil.redirect(req, target) return bongo.commonweb.OK + else: + req.log.debug("Nope.") - req.log.debug("request for %s (handled by %s)", req.path_info, handler) + req.log.debug("request for %s (handled by %s)" % (req.path_info, handler)) mname = rp.action + "_" + req.method + hackymethod = False + req.log.debug("Doing attr check on %s (%s)" % (handler, mname)) + if not hasattr(handler, mname): - req.log.debug("%s has no %s", handler, mname) - return bongo.commonweb.HTTP_NOT_FOUND + req.log.debug("Handler: %s", handler) + req.log.debug("RP: %s", rp) + if rp.view == "agents": + # Special case for agents view + hackymethod = True + if req.method == "POST": + mname = "saveConfig" + else: + mname = "showConfig" + else: + req.log.debug("%s has no %s" % (handler, mname)) + return bongo.commonweb.HTTP_NOT_FOUND + req.log.debug("Getting attributes...") + method = getattr(handler, mname) - ret = method(req, rp) + if hackymethod: + req.log.debug("Running new way.") + ret = method(rp.action, req, rp) + else: + req.log.debug("Running normal way.") + ret = method(req, rp) if ret is None: - req.log.error("Handler %s returned invalid value: None" % handler) + req.log.debug("Handler %s returned invalid value: None" % handler) return bongo.commonweb.OK return ret except HttpError, e: + req.log.debug("Error, yay!") req.log.debug(str(e), exc_info=1) return e.code diff --git a/src/www/bongo/hawkeye/ServerView.py b/src/www/bongo/hawkeye/ServerView.py index bc5a0f0..e321083 100644 --- a/src/www/bongo/hawkeye/ServerView.py +++ b/src/www/bongo/hawkeye/ServerView.py @@ -35,8 +35,9 @@ class ServerHandler(HawkeyeHandler): self.SetVariable("breadcrumb", "Agents » Enable/Disable Agents") self.SetVariable("title", "Enable/Disable Agents") self.SetVariable("agntab", "selecteditem") + self.SetVariable("dremove", None) - return self.SendTemplate(req, rp, "index.tpl") + return self.SendTemplate(req, rp, "index.tpl", title="Enable/Disable Agents") def index_POST(self, req, rp): global doneop diff --git a/src/www/bongo/hawkeye/SystemView.py b/src/www/bongo/hawkeye/SystemView.py index ec11ece..71c9d22 100644 --- a/src/www/bongo/hawkeye/SystemView.py +++ b/src/www/bongo/hawkeye/SystemView.py @@ -6,4 +6,4 @@ class SystemHandler(HawkeyeHandler): def index_GET(self, req, rp): self.SetVariable("systab", "selecteditem") - return self.SendTemplate(req, rp, "index.tpl") + return self.SendTemplate(req, rp, "index.tpl", title="System") diff --git a/src/www/bongo/sundial/Auth.py b/src/www/bongo/sundial/Auth.py new file mode 100644 index 0000000..10241d1 --- /dev/null +++ b/src/www/bongo/sundial/Auth.py @@ -0,0 +1,41 @@ +## Sundial authentication functions. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +from bongo.store.StoreClient import StoreClient +import bongo.commonweb + +## Function to actually test the credentials provided by a user. +# @param req The HttpRequest instance for the current request. +def AcceptCredentials(req): + credUser = req.user + credPass = req.get_basic_auth_pw() + + if credUser is None and credPass is None: + # no session + return False + + # Try and authenticate by connecting to the store. + client = None + try: + client = StoreClient(credUser, credUser, authPassword=credPass) + finally: + if client: + client.Quit() + return True + + return False + +## Authentication handler for Sundial. +# @param req The HttpRequest instance for the current request +# +# Tests the credentials the user provided by calling AcceptCredentials. +# Upon a success or failure, return the appropriate HTTP error code. +def authenhandler(req): + if AcceptCredentials(req): +# req.log.debug("successful auth") + return bongo.commonweb.HTTP_OK + + return bongo.commonweb.HTTP_UNAUTHORIZED diff --git a/src/www/bongo/sundial/DeleteView.py b/src/www/bongo/sundial/DeleteView.py new file mode 100644 index 0000000..6d01a89 --- /dev/null +++ b/src/www/bongo/sundial/DeleteView.py @@ -0,0 +1,38 @@ +## Sundial DELETE request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from SundialHandler import SundialHandler +from bongo.store.StoreClient import StoreClient + +## Class to handle the DELETE request method. +class DeleteHandler(SundialHandler): + ## The contructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for this handler. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## The default entry point. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_DELETE(self, req, rp): + store = StoreClient(req.user, rp.user, authPassword=req.get_basic_auth_pw()) + + try: + store.Delete('/events/%s' % rp.filename) + except: + return bongo.commonweb.HTTP_NOT_FOUND + + return bongo.commonweb.HTTP_NO_CONTENT diff --git a/src/www/bongo/sundial/GetView.py b/src/www/bongo/sundial/GetView.py new file mode 100644 index 0000000..14b60a0 --- /dev/null +++ b/src/www/bongo/sundial/GetView.py @@ -0,0 +1,55 @@ +## Sundial GET request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from SundialHandler import SundialHandler +from bongo.store.StoreClient import StoreClient +from libbongo.libs import bongojson, cal + + +## Class to handle the GET request method. +class GetHandler(SundialHandler): + ## The contructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for this handler. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## The default entry point. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_GET(self, req, rp): + store = StoreClient(req.user, rp.user, authPassword=req.get_basic_auth_pw()) + + # Get the nmap document from the store. + try: + doc = store.Read('/events/%s' % rp.filename) + except: + return bongo.commonweb.HTTP_NOT_FOUND + + jsob = bongojson.ParseString(doc.strip()) + + if jsob: + # TODO TODO TODO This should not be encoded into ASCII at all. + # At the moment, this doesn't work without though. + data = cal.JsonToIcal(jsob).encode('ascii', 'replace') + else: + data = "" + + # Get rid of the boring headers, and data. + req.headers_out["Content-Length"] = str(len(data)) + req.content_type = 'text/calendar' + + req.write(data) + return bongo.commonweb.HTTP_OK diff --git a/src/www/bongo/sundial/OptionsView.py b/src/www/bongo/sundial/OptionsView.py new file mode 100644 index 0000000..825705f --- /dev/null +++ b/src/www/bongo/sundial/OptionsView.py @@ -0,0 +1,35 @@ +## Sundial OPTIONS request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from SundialHandler import SundialHandler + +## Class to handle the OPTIONS request method. +class OptionsHandler(SundialHandler): + ## The constructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for the method. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## The default entry point for the handler. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_OPTIONS(self, req, rp): + # Total lies. At the time of writing, Allow should be more like "OPTIONS, GET, PUT, PROPFIND, REPORT". + # It's getting there though! + req.headers_out['Allow'] = "OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE, PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL" + req.headers_out['DAV'] = "1, 2, access-control, calendar-access" + req.headers_out['Content-Length'] = "0" + return bongo.commonweb.HTTP_OK diff --git a/src/www/bongo/sundial/PropfindView.py b/src/www/bongo/sundial/PropfindView.py new file mode 100644 index 0000000..8dcd324 --- /dev/null +++ b/src/www/bongo/sundial/PropfindView.py @@ -0,0 +1,112 @@ +## Sundial PROPFIND request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +import bongo.commonweb.ElementTree +from bongo.commonweb.HttpError import HttpError +from SundialHandler import SundialHandler +from bongo.store.StoreClient import StoreClient +from bongo.store.StoreClient import DocTypes +from libbongo.libs import cal, bongojson +import lxml.etree as et +import md5 + +## Class to handle PROPFIND request methods. +class PropfindHandler(SundialHandler): + ## The constructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for the method. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## Get some information about the requested resource, be that a calendar, or event. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + # @param store StoreClient instance. + def _handle_resource(self, req, rp, store): + is_calendar = False + icsdata = '' + + if rp.filename is not None: + # Talking about an individual event, not a calendar. + try: + doc = store.Read('/events/%s' % rp.filename) + jsob = bongojson.ParseString(doc.strip()) + + # Get the iCal data as that's what Sundial's etags are made from. + icsdata = cal.JsonToIcal(jsob) + except: + raise HttpError(404) + + else: + # Talking about a calendar, not a revolution. + try: + info = store.Info("/calendars/" + rp.calendar) + if info.type == DocTypes.Calendar: + is_calendar = True + except: + raise HttpError(404) + + # is_calendar is a boolean, whether the request is for a calendar. + # icsdata is a string. It contains the event data in iCal format. + return [is_calendar, icsdata] + + ## The entry point for the handler. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_PROPFIND(self, req, rp): + store = StoreClient(req.user, rp.user, authPassword=req.get_basic_auth_pw()) + + # Get some information about what's being asked for. + is_calendar, icsdata = self._handle_resource(req, rp, store) + + multistatus_tag = et.Element('multistatus', nsmap={None:'DAV:'}) # + + response_tag = et.SubElement(multistatus_tag, 'response') # + + href_tag = et.SubElement(response_tag, 'href') + + # The reason this looks a little funny is because SundialUriRoot will + # look like "/calendars" -- note the slash at the beginning. However, + # rp.get_hostname() returns a path with slash at the end, so the [:-1] + # is simply removing the slash. + href_tag.text = "%s%s/%s/%s/" % (rp.get_hostname()[:-1], req.get_options()['SundialUriRoot'], rp.user, rp.calendar) + if not is_calendar: + href_tag.text += "%s.ics" % rp.filename + + propstat_tag = et.SubElement(response_tag, 'propstat') # + prop_tag = et.SubElement(propstat_tag, 'prop') # + + for t in rp.xml_input.getchildren()[0].getchildren(): + if bongo.commonweb.ElementTree.normalize(t.tag) == 'dav::resourcetype': + resourcetype_tag = et.SubElement(prop_tag, 'resourcetype') # + # Check to make sure it is actually a calendar we're dealing with. + # RFC2518 section 13.9 states the default type of D:resourcetype is empty, so only + # return something if it is indeed a calendar. + if is_calendar: + et.SubElement(resourcetype_tag, 'calendar', nsmap={None: 'urn:ietf:params:xml:ns:caldav'}) # + + elif bongo.commonweb.ElementTree.normalize(t.tag) == 'dav::getetag' and not is_calendar: + et.SubElement(prop_tag, 'getetag').text = '"%s"' % md5.new(icsdata.encode('ascii', 'replace')).hexdigest() + + et.SubElement(propstat_tag, 'status').text = "HTTP/1.1 200 OK" + + req.headers_out['Content-Type'] = 'text/xml; charset="utf-8"' + + req.write("""""") + req.write(et.tostring(multistatus_tag)) + + return bongo.commonweb.HTTP_MULTI_STATUS + diff --git a/src/www/bongo/sundial/PutView.py b/src/www/bongo/sundial/PutView.py new file mode 100644 index 0000000..e61803b --- /dev/null +++ b/src/www/bongo/sundial/PutView.py @@ -0,0 +1,56 @@ +## Sundial PUT request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from SundialHandler import SundialHandler +from bongo.store.StoreClient import StoreClient, DocTypes +from libbongo.libs import cal +from bongo.store.CommandStream import CommandError +from bongo.external import vobject + +## Class to handle the PUT request method. +class PutHandler(SundialHandler): + ## The contructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for this handler. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## The default entry point. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_PUT(self, req, rp): + store = StoreClient(req.user, rp.user, authPassword=req.get_basic_auth_pw()) + json = str(cal.IcalToJson(rp.raw_input)) + filename = "/events/" + rp.filename + + parsed_ical = vobject.readOne(rp.raw_input) + if 'vevent' in parsed_ical.sortChildKeys(): + try: + store.Info(filename) + # File exists, so overwrite it. + store.Replace(filename, json) + except CommandError: + # File probably doesn't exist. + try: + store.Write("/events", DocTypes.Event, json, filename=rp.filename, link="/calendars/" + rp.calendar) + except CommandError: + return bongo.commonweb.HTTP_INTERNAL_SERVER_ERROR + + return bongo.commonweb.HTTP_CREATED + + elif 'vtodo' in parsed_ical.sortChildKeys(): + # Do nothing. Todo lists are not implemented. + # Perhaps a 404 isn't the best thing to return in this case. + return bongo.commonweb.HTTP_NOT_FOUND diff --git a/src/www/bongo/sundial/ReportView.py b/src/www/bongo/sundial/ReportView.py new file mode 100644 index 0000000..7e07e3a --- /dev/null +++ b/src/www/bongo/sundial/ReportView.py @@ -0,0 +1,159 @@ +## Sundial REPORT request method handler. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from bongo.commonweb.ElementTree import normalize +from SundialHandler import SundialHandler +from bongo.store.StoreClient import StoreClient +import lxml.etree as et +import md5 +from bongo.external.dateutil.parser import parse +from libbongo.libs import cal, bongojson + +## Class to handle the PROPFIND request method. +class ReportHandler(SundialHandler): + ## The constructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def __init__(self, req, rp): + pass + + ## Returns whether authentication is required for the method. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## Creates appropriate XML tags for requested VEVENTS. + # @param self The object pointer. + # @param output Dictionary of some information needed for the request. + # + # First, events are pulled from the store based on the collection/calendar and also + # the filters used. Then, tags are created, satisfying all the + # requests, one-by-one. + def _vevent_filter(self, output, prop_tags): + try: + start = output['start'] + end = output['end'] + except KeyError: + start = None + end = None + + # Get calender GUID from name. + try: + info = self.store.Info("/calendars/" + self.rp.calendar) + caluid = info.uid + except: + return bongo.commonweb.HTTP_NOT_FOUND + + # Grab 'dem events from the store. + events = list(self.store.Events(caluid, ["nmap.document", "nmap.event.calendars"], start=start, end=end)) + + # Loop through each VEVENT that was returned. + for response in events: + response_tag = et.SubElement(self.multistatus_tag, 'response') # + + # The reason this looks a little funny is because SundialUriRoot will + # look like "/calendars" -- note the slash at the beginning. However, + # rp.get_hostname() returns a path with slash at the end, so the [:-1] + # is simply removing the slash. + et.SubElement(response_tag, 'href').text = "%s%s/%s/%s/%s.ics" % (self.rp.get_hostname()[:-1], self.req.get_options()['SundialUriRoot'], self.rp.user, self.rp.calendar, response.filename) # url + + propstat_tag = et.SubElement(response_tag, 'propstat') # + prop_tag = et.SubElement(propstat_tag, 'prop') # + + # For each VEVENT, loop through each prop. + for prop in prop_tags: + # Get NMAP document for current VEVENT. + doc = response.props['nmap.document'].strip() + + # Parse the document into JSON. + jsob = bongojson.ParseString(doc) + + # Convert JSON to iCalendar format. + calendardata = cal.JsonToIcal(jsob) + + # Deal with each tag. + if prop == 'dav::getetag': + et.SubElement(prop_tag, 'getetag').text = '"%s"' % md5.new(calendardata.encode('ascii', 'replace')).hexdigest() # etag + elif prop == 'urn:ietf:params:xml:ns:caldav:calendar-data': + et.SubElement(prop_tag, 'calendar-data', nsmap={None: 'urn:ietf:params:xml:ns:caldav'}).text = calendardata # BEGIN:VCALENDAR... + # TODO Implement more of these. + + et.SubElement(propstat_tag, 'status').text = "HTTP/1.1 200 OK" + + return bongo.commonweb.HTTP_OK + + ## Handles the D:calendar-query request. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def calendar_query(self, req, rp): + self.rp = rp + self.req = req + output = {} + + # Loop each child tag of D:calendar-query. + for t in rp.xml_input.getchildren(): + if normalize(t.tag) == 'dav::prop': + # List of /normalize/d props, required. + prop_tags = [normalize(prop.tag) for prop in t.getchildren()] + + elif normalize(t.tag) == 'urn:ietf:params:xml:ns:caldav:filter': + # There is only one C:comp-filter element under C:filter. + vcalendar = t.getchildren()[0] + # It should have name="VCALENDAR". + if vcalendar.get('name') != 'VCALENDAR': + continue + + # There can also be only one C:comp-filter element under the previous. + # It's going to have name="%s", where %s = VEVENT, or VTODO.. + # TODO Perhaps more here.. + filter = vcalendar.getchildren()[0] + + if filter.get('name') == 'VEVENT': + output['type'] = 'VEVENT' + elif filter.get('name') == 'VTODO': + output['type'] = 'VTODO' + # Nothing to implement for the moment. Bongo doesn't support tasks. + pass + + + # Loop through different ranges and whatnot. + for f in filter.getchildren(): + if normalize(f.tag) == 'urn:ietf:params:xml:ns:caldav:time-range': + # C:time-range -- only events between two times. + output['start'] = parse(f.get('start')) + output['end'] = parse(f.get('end')) + + elif normalize(f.tag) == 'urn:ietf:params:xml:ns:caldav:is-defined': + # This means nothing in Bongo as all events in the store are "defined". + pass + + # Generate + self.multistatus_tag = et.Element('multistatus', nsmap={None: 'DAV:'}) + + if output['type'] == 'VEVENT': + ret = self._vevent_filter(output, prop_tags) + if ret != bongo.commonweb.HTTP_OK: + return ret + + # Throw out the output. + req.content_type = 'text/xml; charset="utf-8"' + req.write("""""") + req.write(et.tostring(self.multistatus_tag)) + return bongo.commonweb.HTTP_MULTI_STATUS + + ## The default entry point for the handler. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def do_REPORT(self, req, rp): + self.store = StoreClient(req.user, rp.user, authPassword=req.get_basic_auth_pw()) + return { + 'urn:ietf:params:xml:ns:caldav:calendar-query' : self.calendar_query + }[normalize(rp.xml_input.tag)](req, rp) diff --git a/src/www/bongo/sundial/Server.py b/src/www/bongo/sundial/Server.py new file mode 100644 index 0000000..304132d --- /dev/null +++ b/src/www/bongo/sundial/Server.py @@ -0,0 +1,52 @@ +from bongo.commonweb.ApacheLogHandler import ApacheLogHandler, RequestLogProxy +from SundialPath import SundialPath +from bongo.commonweb.HttpError import HttpError + +import Auth +import bongo.commonweb + +# Add a handler so messages from python's logging module go to apache. +# We don't use that module in the Bongo server proper, because we need +# to log to apache requests directly +import logging +logging.getLogger('').addHandler(ApacheLogHandler()) +logging.root.setLevel(logging.DEBUG) + +def handler(req): + req.log = RequestLogProxy(req) + + req.log.debug("Request: %s", req) + + try: + rp = SundialPath(req) + handler = rp.GetHandler(req, rp) + + +# if handler.NeedsAuth(rp): +# if req.user is None: +# self.req.headers_out["WWW-Authenticate"] = 'Basic realm="Bongo"' +# self.send_error(bongo.commonweb.HTTP_UNAUTHORIZED) +# return bongo.commonweb.HTTP_UNAUTHORIZED +# else: +# auth = bongo.sundial.Auth.authenhandler(req) + + req.log.debug("request for %s (handled by %s)", req.path_info, handler) + + mname = "do_" + req.method + + if not hasattr(handler, mname): + req.log.debug("%s has no %s", handler, mname) + return bongo.commonweb.HTTP_NOT_FOUND + + method = getattr(handler, mname) + + ret = method(req, rp) + + if ret is None: + req.log.error("Handler %s returned invalid value: None" % handler) + return bongo.commonweb.OK + + return ret + except HttpError, e: + req.log.debug(str(e), exc_info=1) + return e.code diff --git a/src/www/bongo/sundial/SundialHandler.py b/src/www/bongo/sundial/SundialHandler.py new file mode 100644 index 0000000..6204e83 --- /dev/null +++ b/src/www/bongo/sundial/SundialHandler.py @@ -0,0 +1,28 @@ +## Sundial mod_python handler class. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb + +## Default SundialHandler class. +class SundialHandler(object): + ## Returns whether the handler requires authentication. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def NeedsAuth(self, rp): + return True + + ## Looks at the path of the request. By default, does nothing. + # @param self The object pointer. + # @param rp The SundialPath instance for the current request. + def ParsePath(self, rp): + pass + + ## Entry point for the handler. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def index(self, req, rp): + return bongo.commonweb.OK diff --git a/src/www/bongo/sundial/SundialPath.py b/src/www/bongo/sundial/SundialPath.py new file mode 100644 index 0000000..00edb5d --- /dev/null +++ b/src/www/bongo/sundial/SundialPath.py @@ -0,0 +1,125 @@ +## Sundial resource path class. +# +# @author Jonny Lamb +# @copyright 2007 Jonny Lamb +# @license GNU GPL v2 + +import bongo.commonweb +from bongo.commonweb.HttpError import HttpError +import re +import lxml.etree as et +import urllib + +import GetView +import PropfindView +import OptionsView +import ReportView +import DeleteView +import PutView + +## Dictionary of views available depending on type of request method. +views = { + 'GET' : GetView.GetHandler, + 'PROPFIND' : PropfindView.PropfindHandler, + 'OPTIONS' : OptionsView.OptionsHandler, + 'REPORT' : ReportView.ReportHandler, + 'DELETE' : DeleteView.DeleteHandler, + 'PUT' : PutView.PutHandler +} + +## Resource path class for Sundial. +class SundialPath(object): + + ## Takes the request URI and parses it into its separate parts. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + def _handle_path(self, req): + # There's no law to say that the "calendars/" directory is at /calendars/. + # So, let's create the right path *not including* the actual + # calendars directory. E.g. if the request was for /something/calendars/blah, + # the sundialpath will be "/something". + splituri = req.uri.split('/') + pathparts = [] + path = splituri[:] + for i in path: + splituri.__delitem__(0) + # SundialUriRoot comes in as "/calendars" but i + # will not have the following slash, so the [1:] + # is just to remove that. + if i == req.get_options()['SundialUriRoot'][1:]: + break + pathparts.append(i) + + self.sundialpath = '/'.join(pathparts) + + if len(splituri) != 3: + raise HttpError(404) + + # The user the calendar belongs to. + self.user = splituri[0] + + # The calendar name. + self.calendar = urllib.unquote(splituri[1]) + + # The file name. + self.filename = splituri[2] + + if self.filename != '': + # This shop only serves up iCalendar. + if self.filename[-4:] != '.ics': + raise HttpError(404) + + self.filename = self.filename[:-4] + else: + self.filename = None + + ## The constructor. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + def __init__(self, req): + self.req = req + + self.view = self.action = self.sundialpath = self.user = self.calender = self.filename = None + + req.log.debug(str(self)) + + # The path should be something like one of the following: + # {/otherpath}/calendars/user/calendar/ + # {/calendars}/user/calendar/filename.ics + self._handle_path(req) + + if req.headers_in.get('Content-Length', None): + self.raw_input = str(req.read(int(req.headers_in.get('Content-Length', None)))) + + # Look for XML content, and if it exists, parse it. + # RFC2518 says that both text/xml and application/xml are valid. + p = re.compile("(application|text)/xml") + if p.match(str(req.headers_in.get('Content-Type', None))): + self.xml_input = et.XML(self.raw_input) + + # For debugging, print out headers_in, and the content. + #print req.headers_in + #try: + # print self.raw_input + #except: + # pass + + ## Returns the handler for the request method. + # @param self The object pointer. + # @param req The HttpRequest instance for the current request. + # @param rp The SundialPath instance for the current request. + def GetHandler(self, req, rp): + return views[req.method](req, rp) + + ## Returns hostname based on HTTP_HOST. + # @param self The object pointer. + # + # Evolution does not support relative URLs in dav::href, therefore + def get_hostname(self): + user_agent = self.req.headers_in.get('User-Agent') + + if user_agent is not None and user_agent.startswith('Evolution'): + # TODO This doesn't support https. + return 'http://' + self.req.headers_in.get('Host') + self.sundialpath + + return self.sundialpath diff --git a/src/www/bongo/sundial/__init__.py b/src/www/bongo/sundial/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/www/css/admin.css b/src/www/css/admin.css index 65970fc..c9ef0aa 100644 --- a/src/www/css/admin.css +++ b/src/www/css/admin.css @@ -1,7 +1,7 @@ /* Bongo web administration interface (aka Hawkeye) stylesheet (c) 2007 Alexander Hixon - see COPYING for details - Last modified: Sunday May 20, 2007 + Last modified: Monday Sep 3, 2007 =======[ Global Styles ]======= */ @@ -66,9 +66,9 @@ body { } input, select { - color: #555753; - background-color: #eeeeec; - border: 1px solid #2e3436; + color: #2e3436; + background-color: #fff; + border: 1px solid #888a85; } .lang { @@ -108,14 +108,23 @@ p { color: #2e3436; /* Tango DARK-GREY */ } +a { + text-decoration:none; + color: #2e3436; +} + #page { background: url('/img/cbg.png'); background-repeat: repeat-x; background-color: #eeeeec; /* Tango GREY */ - margin-left: 155px; /* Push across width of sidebar, minus 10px, for bg behind round corner */ - padding-left: 20px; /* Prints BG for 10px, now flush with sidebar */ + /*margin-left: 155px; /* Push across width of sidebar, minus 10px, for bg behind round corner */ + /*padding-left: 20px; /* Prints BG for 10px, now flush with sidebar */ + margin: 0px; + padding: 0px; + margin-left: 175px; + /*float: right;*/ padding-top: 6px; - min-height: 500px; + min-height: 390px; -moz-border-radius-bottomright: 20px; -khtml-border-radius-bottomright: 20px; @@ -138,31 +147,81 @@ p { display: block; } -/* - =======[ Sidebar Styles ]======= -*/ - -#sidebar { - color: #eeeeec; /* Tango WHITE */ - background: url('/img/sbg.png'); - background-repeat: no-repeat; - background-color: #2e3436; /* Tango DARK-GREY */ - float: left; - min-height: 500px; - width: 175px; - - text-align: right; - margin-right: 0px; - padding-right: 0px; - padding-bottom: 6px; - - -moz-border-radius-bottomleft: 20px; +#wrap { + background: url('/img/cbg.png'); + background-repeat: repeat-x; + background-color: #eeeeec; /* Tango GREY */ + /*margin-left: 155px; /* Push across width of sidebar, minus 10px, for bg behind round corner */ + /*padding-left: 20px; /* Prints BG for 10px, now flush with sidebar */ + margin: 0px; + padding: 0px; + /*padding-left: 175px;*/ + /*padding-top: 6px;*/ + + -moz-border-radius-bottomleft: 20px; -khtml-border-radius-bottomleft: 20px; border-radius-bottomleft: 20px; -moz-border-radius-bottomright: 20px; -khtml-border-radius-bottomright: 20px; border-radius-bottomright: 20px; + + padding-bottom: 6px; + margin-bottom: 1em; +} + +#footer { + margin-bottom: 1em; + text-align: right; + padding-right: 2em; + font-size: 85%; + display: block; +} + +/* + =======[ Sidebar Styles ]======= +*/ + +#sidebar-wrap { + float: left; + width: 175px; + + /*height: 500px;*/ + + margin: 0px; + padding: 0px; + + background: url('/img/sbg.png'); + background-repeat: no-repeat; + + color: #eeeeec; /* Tango WHITE */ + + text-align:center; +} + +nlink a, a.nlink { + color: #eeeeec; + border-bottom: 0px none; +} + +#sidebartoggle { + display: inline; + position:relative; + top: -50px; +} + +#sidebar { + height: 400px; + /*height: 100%; /* Always make sidebar as big as content. */ + + /*background-color: #2e3436; /* Tango DARK-GREY */ + + text-align: right; + margin: 0px; + padding: 0px; + /*margin-right: 0px; + padding-right: 0px; + padding-bottom: 6px;*/ } .helpitem { @@ -285,6 +344,58 @@ ul.nav{ border: 3px solid #204a85; } +/* + ========[ Icon View ]======= +*/ + +#iconview { + text-align:center; + vertical-align:middle; +} + +#iconview div.icon { + margin:3px; +} + +#iconview div.icon a { + border:1px solid #d3d7cf; + display:block; + float:left; + height:97px !important; + padding:2px 5px 1px; + text-decoration:none; + vertical-align:middle; + width:108px !important; +} + +#iconview div.icon a:link { + color:#888a85; +} + +#iconview div.icon a:hover { + background-color:#d3d7cf; + border:1px solid #2e3436; + color:#2e3436; + padding:3px 4px 0px 6px; +} + +#iconview div.icon a:active { + color:#888a85; +} + +#iconview div.icon a:visited { + color:#888a85; +} + +#iconview div.icon img { + margin-top:13px; +} + +#iconview div.icon span { + display:block; + padding-top:3px; +} + /* =======[ Button Styles ]======= http://www.hedgerwow.com/360/dhtml/css-round-button/ diff --git a/src/www/css/interpreter.css b/src/www/css/interpreter.css deleted file mode 100644 index 580dde6..0000000 --- a/src/www/css/interpreter.css +++ /dev/null @@ -1,54 +0,0 @@ -h1 { - font-size: 2em; - color: #4B4545; - text-align: center; -} - -textarea.textbox { - font-family: Monaco, "lucida console", Courier; - border: 1px solid #CCCCCC; - font-size: .60em; - padding: 2px 4px; - margin-top: .3em; -} - -input.textbox { - font-family: Monaco, "lucida console", Courier; - border: 1px solid #CCCCCC; - font-size: .60em; - padding: 2px 4px; - margin-top: .3em; -} - -#interpreter_area { - display: block; - border: 1px solid #CCCCCC; - padding: 2px 4px; - margin-top: .3em; - width: 600px; - height: 100px; - overflow: auto; -} - -#interpreter_output { - display: inline; - font-family: Monaco, "lucida console", Courier; - font-size: .60em; -} - -#interpreter_output span { - white-space: -moz-pre-wrap; /* Mozilla */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS 2.1 */ - white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ - word-wrap: break-word; /* IE */ - wrap-option: emergency; /* CSS 3 */ -} - -input.textbox:focus { background-color: #FFFEE3; } - -.code { color: blue; } -.data { color: black; } -.error { color: red; } -.banner { color: green; } -.invisible { display: none; } diff --git a/src/www/css/log.css b/src/www/css/log.css new file mode 100644 index 0000000..5f39c30 --- /dev/null +++ b/src/www/css/log.css @@ -0,0 +1,106 @@ +/* + * log.css + * Visual themeing for browser-based logging provided by Log.js + * + * (c) 2008 Alexander Hixon + * + * 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, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#logbox { + display: block; + z-index: 1000; + left: 0px; + bottom: 0px; + position: fixed; + width: 100%; +} + +#log { + font-family: Inconsolata, Dejavu Sans Mono, monospace; + background-color: #2e3436; + color: #eeeeec; + padding: 2px; + height: 100px; + overflow: auto; +} + +#jsprompt { + font-family: Inconsolata, Dejavu Sans Mono, monospace; + background-color: #555753; + color: #eeeeec; + + border: 0px none; + width: 100%; +} + +#log div.error { + color: #ef2929; +} + +#log div.debug { + color: #73d216; +} + +#log div.warn { + color: #f57900; +} + +#log .group div.error { + color: #a40000; +} + +#log a, #log a:active { + text-decoration: none; + border-bottom: 1px dotted #babdb6; + color: #eeeeec; +} + +#log .groupbox a, #log .groupbox a:active { + color: #2e3436; +} + +#log div.a { + color: #eeeeec; +} + +#log a:hover { + border-bottom: 0px none; +} + +#log .titlespan { + background-color: #888a85; + width: 100%; +} + +.group { + padding: 2px; + background-color: #555753; +} + +.groupbox { + margin-top: 0.5em; + margin-bottom: 0.5em; + margin-left: 1em; + border: 1px solid #babdb6; +} + +#log .floatright { + float: right; + color: #eeeeec; + /*padding: 2px; + display: inline;*/ +} diff --git a/src/www/dragonfly-debug.html b/src/www/dragonfly-debug.html index 5daa575..3a9e733 100644 --- a/src/www/dragonfly-debug.html +++ b/src/www/dragonfly-debug.html @@ -6,7 +6,7 @@ Bongo