From 87f97b23f6e38efa43f87b1d06a0ae62b022864c Mon Sep 17 00:00:00 2001 From: alexhudson Date: Thu, 10 May 2007 23:13:00 +0000 Subject: [PATCH] * Add support for resolving TXT DNS RRs * Add ability to check online for updates --- Makefile.am | 1 + autogen.sh | 13 ++++ include/msgapi.h | 5 ++ include/xplresolve.h | 8 ++- src/apps/config/config.c | 45 +++++++++----- src/apps/config/config.h | 19 ++++++ src/libs/msgapi/Bongo.rules | 2 +- src/libs/msgapi/msgapi.c | 105 +++++++++++++++++++++++++++++++++ src/libs/python/bongo/msgapi.c | 23 ++++++++ src/libs/xpl/resolve.c | 8 +++ 10 files changed, 211 insertions(+), 18 deletions(-) diff --git a/Makefile.am b/Makefile.am index 54a9251..03207e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ EXTRA_DIST := \ config.rpath \ bongo.pc.in \ HACKING \ + include/bongo-buildinfo.h \ init/bongo.init.fc4.in \ init/bongo.init.sles9.in \ init/bongo.init.suse10.in \ diff --git a/autogen.sh b/autogen.sh index 9a82f82..ff2037e 100755 --- a/autogen.sh +++ b/autogen.sh @@ -436,6 +436,19 @@ for configure_ac in $configure_files; do fi done +SVNREV=$(svnversion .) +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 +else + echo SVN Rev at $SVNREV + echo \#define BONGO_BUILD_BRANCH \"trunk\" > ./include/bongo-buildinfo.h + echo \#define BONGO_BUILD_VSTR \"r\" >> ./include/bongo-buildinfo.h + echo \#define BONGO_BUILD_VER \"$SVNREV\" >> ./include/bongo-buildinfo.h +fi + conf_flags="--enable-maintainer-mode" if test x$NOCONFIGURE = x; then diff --git a/include/msgapi.h b/include/msgapi.h index 85c575f..f81ce12 100644 --- a/include/msgapi.h +++ b/include/msgapi.h @@ -496,6 +496,11 @@ EXPORT BOOL MsgResolveStop(); EXPORT void MsgGetUid(char *buffer, int buflen); +EXPORT BOOL MsgGetAvailableVersion(int *version); +EXPORT BOOL MsgGetBuildVersion(int *version, BOOL *custom); + +EXPORT void MsgNmapChallenge(const unsigned char *response, unsigned char *reply, size_t length); + /* from msgcollector.c */ enum { diff --git a/include/xplresolve.h b/include/xplresolve.h index b00186c..8f14983 100644 --- a/include/xplresolve.h +++ b/include/xplresolve.h @@ -58,13 +58,17 @@ typedef struct _XplSoaRecord { unsigned long expire; /* max Time to keep data (sec) */ unsigned long minimum; /* TTL for zone (sec) */ } Xpl8BitPackedStructure XplSoaRecord; - + +typedef struct _XplTxtRecord { + char txt[MAXEMAILNAMESIZE + 1]; /* the text record */ +} Xpl8BitPackedStructure XplTxtRecord; typedef union _XplDnsRecord { XplARecord A; XplMxRecord MX; XplPtrRecord PTR; XplSoaRecord SOA; + XplTxtRecord TXT; } Xpl8BitPackedStructure XplDnsRecord; #if defined(WIN32) || defined(NETWARE) || defined(LIBC) @@ -77,7 +81,7 @@ typedef union _XplDnsRecord { #define XPL_RR_SOA 0x0006 /* Start of Zone Authority */ #define XPL_RR_PTR 0x000C /* Domain Name Pointer */ #define XPL_RR_MX 0x000F /* Mail exchanger */ -#define XPL_RR_MX 0x000F /* Mail exchanger */ +#define XPL_RR_TXT 0x0010 /* Text record */ /* Return codes for MX */ #define XPL_DNS_SUCCESS 0 diff --git a/src/apps/config/config.c b/src/apps/config/config.c index bf9b4e8..cd7aeb9 100644 --- a/src/apps/config/config.c +++ b/src/apps/config/config.c @@ -3,28 +3,15 @@ * Copyright (c) 2007 Alex Hudson */ -#include "config.h" #include #include +#include #include #include #include #include #include - -/* cli opts */ -struct { - int verbose; - -} BongoConfig; - -typedef struct { - Connection *conn; - char buffer[CONN_BUFSIZE + 1]; -} StoreClient; - -#define malloc(bytes) MemMalloc(bytes) -#define free(ptr) MemFree(ptr) +#include "config.h" void usage() { @@ -36,6 +23,7 @@ usage() { "Commands:\n" " install do the initial Bongo install\n" " crypto generate data needed for encryption\n" + " checkversion see if a newer Bongo is available\n" ""; XplConsolePrintf("%s", usage); @@ -259,6 +247,28 @@ GenerateCryptoData() { return TRUE; } +void +CheckVersion() { + int current_version, available_version; + BOOL custom_version; + + + if (!MsgGetBuildVersion(¤t_version, &custom_version)) { + printf("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); + if (custom_version) + printf("This is modified software.\n"); + } + printf("Version currently available: "); + if (!MsgGetAvailableVersion(&available_version)) { + printf("unable to request online information.\n"); + } else { + printf("%s%d\n", BONGO_BUILD_VSTR, available_version); + } +} + int main(int argc, char *argv[]) { int next_arg = 0; @@ -289,6 +299,8 @@ main(int argc, char *argv[]) { command = 1; } else if (!strcmp(argv[next_arg], "crypto")) { command = 2; + } else if (!strcmp(argv[next_arg], "checkversion")) { + command = 3; } else { printf("Unrecognized command: %s\n", argv[next_arg]); } @@ -312,6 +324,9 @@ main(int argc, char *argv[]) { case 2: GenerateCryptoData(); break; + case 3: + CheckVersion(); + break; default: break; } diff --git a/src/apps/config/config.h b/src/apps/config/config.h index 1e741d0..7750ee6 100644 --- a/src/apps/config/config.h +++ b/src/apps/config/config.h @@ -6,8 +6,27 @@ #ifndef BONGOCONFIG_H #define BONGOCONFIG_H +/* cli opts */ +struct { + int verbose; + +} BongoConfig; + +typedef struct { + Connection *conn; + char buffer[CONN_BUFSIZE + 1]; +} StoreClient; + +#define malloc(bytes) MemMalloc(bytes) +#define free(ptr) MemFree(ptr) + void usage(); +BOOL NMAPSimpleCommand(StoreClient *client, char *command); +BOOL SetAdminRights(StoreClient *client, char *document); +BOOL PutOrReplaceConfig(StoreClient *client, char *collection, char *filename, char *content); void InitialStoreConfiguration(); +BOOL GenerateCryptoData(); +void CheckVersion(); /* 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) diff --git a/src/libs/msgapi/Bongo.rules b/src/libs/msgapi/Bongo.rules index 72bc4f5..f43bb17 100644 --- a/src/libs/msgapi/Bongo.rules +++ b/src/libs/msgapi/Bongo.rules @@ -26,7 +26,7 @@ libbongomsgapi_la_LIBADD := \ $(top_builddir)/import/libical/src/libical/libical-bongo.la \ $(DL_LIBS) -src/libs/msgapi/all: libbongomsgapi.la +src/libs/msgapi/all: libbongomsgapi.la 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/msgapi.c b/src/libs/msgapi/msgapi.c index 24df7fe..a933ee0 100644 --- a/src/libs/msgapi/msgapi.c +++ b/src/libs/msgapi/msgapi.c @@ -39,6 +39,7 @@ #include #include "msgapip.h" +#include #include #include #include @@ -166,6 +167,51 @@ typedef struct _ConnectionManagerCommand { unsigned char name[1]; } ConnectionManagerCommand; +/* I tried to remove this, but it's still needed :( + * Python server for Dragonfly needs a way to authenticate itself + * to the queue... + */ +void +MsgNmapChallenge(const unsigned char *response, unsigned char *reply, size_t length) +{ + unsigned char *ptr; + unsigned char *salt; + static unsigned char access[NMAP_HASH_SIZE] = { '\0' }; + MDBValueStruct *v; + 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); + } + } + } + + if (access[0] && reply && (length > 32) && ((ptr = strchr(response, '<')) != NULL)) { + salt = ++ptr; + + if ((ptr = strchr(ptr, '>')) != NULL) { + *ptr = '\0'; + } + + XplHashNew(&ctx, XPLHASH_MD5); + XplHashWrite(&ctx, salt, strlen(salt)); + XplHashWrite(&ctx, access, NMAP_HASH_SIZE); + XplHashFinal(&ctx, XPLHASH_LOWERCASE, reply, XPLHASH_MD5_LENGTH); + } else if (reply) { + *reply = '\0'; + } + + return; +} + EXPORT const unsigned char * MsgGetServerDN(unsigned char *buffer) { @@ -1909,6 +1955,65 @@ MsgGetSystemDirectoryHandle(void) return(systemHandle); } +BOOL +MsgGetBuildVersion(int *version, BOOL *custom) +{ + /* Get the version of this build of bongo. + * version - what SVN rev or branch minor this is + * custom - whether or not this is a custom build + */ + int len = 0; + char *ptr = BONGO_BUILD_VER; + + *version = strtol(ptr, NULL, 10); + len = strlen(ptr); + + if (ptr[len] == 'M') *custom = TRUE; + return TRUE; +} + +BOOL +MsgGetAvailableVersion(int *version) +{ + /* Get the information about latest version of bongo available + * version - what SVN rev or branch minor is available + */ + char record[500]; + char *ptr; + int v; + + if (!MsgGetUpdateStatus(record, 499)) + return FALSE; + + ptr = strchr(record, '|'); + if (ptr == NULL) return FALSE; + + *version = strtol(record, &ptr, 10); + return TRUE; +} + +BOOL +MsgGetUpdateStatus(char *record, int record_length) +{ + char *branch = BONGO_BUILD_BRANCH; + char *zone = "revisions.bongo-project.com"; + char hostname[256]; + XplDnsRecord *result = NULL; + int status; + + snprintf(hostname, 255, "%s.%s", branch, zone); + + status = XplDnsResolve(hostname, &result, XPL_RR_TXT); + switch(status) { + case XPL_DNS_SUCCESS: + snprintf(record, record_length, "%s", result[0].TXT.txt); + MemFree(result); + return TRUE; + break; + default: + return FALSE; + } +} static BOOL MsgReadConfiguration(void) diff --git a/src/libs/python/bongo/msgapi.c b/src/libs/python/bongo/msgapi.c index 5af87c6..9f36b0b 100644 --- a/src/libs/python/bongo/msgapi.c +++ b/src/libs/python/bongo/msgapi.c @@ -551,6 +551,28 @@ msgapi_IcsSubscribe(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(guid); } +PyDoc_STRVAR(NmapChallenge_doc, +"NmapChallenge(s) -> string response\n\ +\n\ +Return the response string for an NMAP challenge string s.\n\ +s is of the format \"NMAP <40c0cbb0hostname441444a4>\"."); + +static PyObject * +msgapi_NmapChallenge(PyObject *self, PyObject *args) +{ + unsigned char *salt; + unsigned int len=33; + unsigned char buf[len]; + + if (!PyArg_ParseTuple(args, "s", &salt)) { + return NULL; + } + + MsgNmapChallenge(salt, buf, len); + + return Py_BuildValue("s", buf); +} + extern PyObject *msgapi_GetConfigProperty(PyObject *, PyObject *); PyMethodDef MsgApiMethods[] = { @@ -568,6 +590,7 @@ PyMethodDef MsgApiMethods[] = { {"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}, {NULL, NULL, 0, NULL} diff --git a/src/libs/xpl/resolve.c b/src/libs/xpl/resolve.c index e109578..e1c10ec 100644 --- a/src/libs/xpl/resolve.c +++ b/src/libs/xpl/resolve.c @@ -218,6 +218,7 @@ XplDnsResolve(char *host, XplDnsRecord **list, int type) /* We loop here in case we get a CNAME in response to the query. We'll stop looping when * we get an MX or A record, which is what we're looking for */ do { + int len = 0; d("Starting query loop\n"); cnameLooping = FALSE; /* Will be set to TRUE if we get a CNAME response */ @@ -308,6 +309,13 @@ XplDnsResolve(char *host, XplDnsRecord **list, int type) ++cnameLoops; break; + case XPL_RR_TXT: + len = (int) answer[answerOff]; + strncpy(answers[i].TXT.txt, answer + answerOff + 1, len); + d("TXT Record\n"); + d("Answer : %s\n", answers[i].TXT.txt); + break; + case XPL_RR_PTR: { ptrData = (struct PTRData*)(answer + answerOff); answerOff += DecodeName(answer, answerOff, answers[i].PTR.name);