1699 lines
49 KiB
C
1699 lines
49 KiB
C
/****************************************************************************
|
|
* <Novell-copyright>
|
|
* 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.
|
|
* </Novell-copyright>
|
|
****************************************************************************/
|
|
// Parts Copyright (C) 2007 Alex Hudson. See COPYING for details.
|
|
|
|
/** \file nmap.c
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <xpl.h>
|
|
#include <bongoutil.h>
|
|
|
|
#include <memmgr.h>
|
|
|
|
#include <nmlib.h>
|
|
#include <msgapi.h>
|
|
#include <nmap.h>
|
|
#include <bongostore.h>
|
|
|
|
struct {
|
|
RegistrationStates state;
|
|
|
|
unsigned char access[NMAP_HASH_SIZE];
|
|
|
|
bongo_ssl_context *context;
|
|
|
|
BOOL debug;
|
|
} NMAPLibrary = {
|
|
REGISTRATION_LOADING,
|
|
{ '\0' },
|
|
NULL,
|
|
NULL,
|
|
|
|
FALSE
|
|
};
|
|
|
|
int
|
|
NMAPSendCommand(Connection *conn, const unsigned char *command, size_t length)
|
|
{
|
|
int written;
|
|
|
|
written = ConnWrite(conn, command, length);
|
|
if (written < 0 || (size_t)written != length) {
|
|
return -1;
|
|
}
|
|
|
|
if (ConnFlush(conn) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
NMAPSendCommandF(Connection *conn, const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
int written;
|
|
|
|
va_start(ap, format);
|
|
written = ConnWriteVF(conn, format, ap);
|
|
va_end(ap);
|
|
|
|
if (written < 0) {
|
|
return written;
|
|
}
|
|
|
|
if (ConnFlush(conn) < 0) {
|
|
return -1;
|
|
} else {
|
|
return written;
|
|
}
|
|
}
|
|
|
|
__inline static unsigned char *
|
|
FindNewLineChar(unsigned char *Buffer, unsigned char *EndPtr) {
|
|
register unsigned char *ptr = Buffer;
|
|
register unsigned char *endPtr = EndPtr;
|
|
|
|
do {
|
|
if (ptr < endPtr) {
|
|
if (*ptr != '\n') {
|
|
ptr++;
|
|
continue;
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
break;
|
|
} while(TRUE);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
__inline static unsigned char *
|
|
FindEndOfLine(Connection *conn)
|
|
{
|
|
int count;
|
|
char *newLine;
|
|
|
|
Connection *c = conn;
|
|
|
|
do {
|
|
if ((newLine = FindNewLineChar(c->receive.read, c->receive.write)) != NULL) {
|
|
return(newLine);
|
|
}
|
|
|
|
count = c->receive.write - c->receive.read;
|
|
|
|
if (count < CONN_TCP_MTU) {
|
|
if (count == 0) {
|
|
CONN_TCP_RECEIVE(c, c->receive.buffer, CONN_TCP_MTU, count);
|
|
if (count > 0) {
|
|
c->receive.read = c->receive.buffer;
|
|
c->receive.write = c->receive.buffer + count;
|
|
c->receive.remaining = CONN_TCP_MTU - count;
|
|
c->receive.write[0] = '\0';
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* preserve unread data in the buffer */
|
|
memcpy(c->receive.buffer, c->receive.read, count);
|
|
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);
|
|
if (count > 0) {
|
|
c->receive.write += count;
|
|
c->receive.remaining -= count;
|
|
c->receive.write[0] = '\0';
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* This line is longer than MTU size, NMAP is not supposed to do that on a response line */
|
|
return(c->receive.write - 1);
|
|
} while (TRUE);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
__inline static int
|
|
NMAPReadDataAfterResponseCode(Connection *conn, unsigned char *response, size_t length, BOOL RemoveCRLF)
|
|
{
|
|
int ccode;
|
|
int count;
|
|
char *newLine;
|
|
|
|
do {
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if (*newLine == '\n') {
|
|
newLine++;
|
|
ccode = atol(conn->receive.read);
|
|
if (ccode != 6000) {
|
|
if ((ccode > 999) && (ccode < 10000) && ((conn->receive.read[4] == ' ') || (conn->receive.read[4] == '-'))) {
|
|
if (RemoveCRLF) {
|
|
if (newLine[-2] == '\r') {
|
|
count = newLine - conn->receive.read - 7;
|
|
} else {
|
|
count = newLine - conn->receive.read - 6;
|
|
}
|
|
} else {
|
|
count = newLine - conn->receive.read - 5;
|
|
}
|
|
|
|
if ((unsigned long)count < length) {
|
|
memcpy(response, conn->receive.read + 5, count);
|
|
response[count] = '\0';
|
|
conn->receive.read = newLine;
|
|
return(ccode);
|
|
}
|
|
|
|
return(NMAP_ERROR_BUFFER_TOO_SHORT);
|
|
}
|
|
|
|
return(NMAP_ERROR_INVALID_RESPONSE_CODE);
|
|
}
|
|
|
|
if (conn->client.cb) {
|
|
if (((NMAPOutOfBoundsCallback)conn->client.cb)(conn->client.data, conn->receive.read + 5, newLine)) {
|
|
conn->receive.read = newLine;
|
|
continue;
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_FAILED);
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_NOT_DEFINED);
|
|
}
|
|
|
|
return(NMAP_ERROR_LINE_TOO_LONG);
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
__inline static int
|
|
NMAPReadFullLine(Connection *conn, unsigned char *response, size_t length, BOOL RemoveCRLF)
|
|
{
|
|
int ccode;
|
|
int count;
|
|
char *newLine;
|
|
|
|
do {
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if (*newLine == '\n') {
|
|
newLine++;
|
|
ccode = atol(conn->receive.read);
|
|
if (ccode > -1) {
|
|
if (ccode != 6000) {
|
|
if (RemoveCRLF) {
|
|
if (newLine[-2] == '\r') {
|
|
count = newLine - conn->receive.read - 2;
|
|
} else {
|
|
count = newLine - conn->receive.read - 1;
|
|
}
|
|
} else {
|
|
count = newLine - conn->receive.read;
|
|
}
|
|
|
|
if ((unsigned long)count < length) {
|
|
memcpy(response, conn->receive.read, count);
|
|
response[count] = '\0';
|
|
conn->receive.read = newLine;
|
|
return(ccode);
|
|
}
|
|
|
|
return(NMAP_ERROR_BUFFER_TOO_SHORT);
|
|
}
|
|
|
|
if (conn->client.cb) {
|
|
if (((NMAPOutOfBoundsCallback)conn->client.cb)(conn->client.data, conn->receive.read + 5, newLine)) {
|
|
conn->receive.read = newLine;
|
|
continue;
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_FAILED);
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_NOT_DEFINED);
|
|
}
|
|
|
|
return(NMAP_ERROR_INVALID_RESPONSE_CODE);
|
|
}
|
|
|
|
return(NMAP_ERROR_LINE_TOO_LONG);
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
|
|
__inline static int
|
|
NMAPReadJustResponseCode(Connection *conn)
|
|
{
|
|
int ccode;
|
|
char *newLine;
|
|
|
|
do {
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if (*newLine == '\n') {
|
|
newLine++;
|
|
ccode = atol(conn->receive.read);
|
|
if (ccode != 6000) {
|
|
if ((ccode > 999) && (ccode < 10000) && ((conn->receive.read[4] == ' ') || (conn->receive.read[4] == '-'))) {
|
|
conn->receive.read = newLine;
|
|
return(ccode);
|
|
}
|
|
|
|
return(NMAP_ERROR_INVALID_RESPONSE_CODE);
|
|
}
|
|
|
|
if (conn->client.cb) {
|
|
if (((NMAPOutOfBoundsCallback)conn->client.cb)(conn->client.data, conn->receive.read + 5, newLine)) {
|
|
conn->receive.read = newLine;
|
|
continue;
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_FAILED);
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_NOT_DEFINED);
|
|
}
|
|
|
|
return(NMAP_ERROR_LINE_TOO_LONG);
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
/** Used to read response lines from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- positive numeric equivalent of the first characters on the line on success
|
|
- negative number on failure
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param response is either a pointer to a buffer or NULL.
|
|
- \<destination buffer\>
|
|
- the response code will be returned
|
|
- the line will be copied to the destination buffer
|
|
- NULL
|
|
- the response code will be returned
|
|
|
|
@param length the length of the destination buffer
|
|
|
|
@param check is a boolean value with the following effects:
|
|
- TRUE
|
|
- the NMAP response code will be validated
|
|
- only the data after the response code will be copied to the destination buffer
|
|
- FALSE
|
|
- will not require the first characters read to be an NMAP response code
|
|
- the entire line will be copied to the destination buffer
|
|
|
|
*/
|
|
int
|
|
NMAPReadResponse(Connection *conn, unsigned char *response, size_t length, BOOL check)
|
|
{
|
|
if (response) {
|
|
if (check) {
|
|
return(NMAPReadDataAfterResponseCode(conn, response, length, TRUE));
|
|
} else {
|
|
return(NMAPReadFullLine(conn, response, length, TRUE));
|
|
}
|
|
} else {
|
|
return(NMAPReadJustResponseCode(conn));
|
|
}
|
|
}
|
|
|
|
|
|
/* NMAPReadResponseLine
|
|
|
|
Same as NMAPReadResponse except that it does not strip the \r\n
|
|
|
|
*/
|
|
int
|
|
NMAPReadResponseLine(Connection *conn, unsigned char *response, size_t length, BOOL check)
|
|
{
|
|
if (response) {
|
|
if (check) {
|
|
return(NMAPReadDataAfterResponseCode(conn, response, length, FALSE));
|
|
} else {
|
|
return(NMAPReadFullLine(conn, response, length, FALSE));
|
|
}
|
|
} else {
|
|
return(NMAPReadJustResponseCode(conn));
|
|
}
|
|
}
|
|
|
|
/* NMAPReadResponseAndCount
|
|
|
|
Remarks
|
|
This function is designed for reading NMAP responses that take the form:
|
|
|
|
<response code><' ' | '-'><count>
|
|
|
|
2021 374 (for example)
|
|
|
|
This function:
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- evaluates the first non 6000 line
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
Return Value
|
|
- the NMAP response code on success
|
|
- negative number on failure
|
|
|
|
Parameters
|
|
conn - the network connection to read the line from
|
|
|
|
count - this variable will be assigned the numberic equivalent of
|
|
the string following the NMAP response code.
|
|
*/
|
|
int
|
|
NMAPReadResponseAndCount(Connection *conn, unsigned long *count)
|
|
{
|
|
int ccode;
|
|
char *newLine;
|
|
|
|
do {
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if (*newLine == '\n') {
|
|
newLine++;
|
|
ccode = atol(conn->receive.read);
|
|
if (ccode != 6000) {
|
|
if ((ccode > 999) && (ccode < 10000) && ((conn->receive.read[4] == ' ') || (conn->receive.read[4] == '-'))) {
|
|
*count = atol(conn->receive.read + 5);
|
|
conn->receive.read = newLine;
|
|
return(ccode);
|
|
}
|
|
|
|
return(NMAP_ERROR_INVALID_RESPONSE_CODE);
|
|
}
|
|
|
|
if (conn->client.cb) {
|
|
if (((NMAPOutOfBoundsCallback)conn->client.cb)(conn->client.data, conn->receive.read + 5, newLine)) {
|
|
conn->receive.read = newLine;
|
|
continue;
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_FAILED);
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_NOT_DEFINED);
|
|
}
|
|
|
|
return(NMAP_ERROR_LINE_TOO_LONG);
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
__inline static int
|
|
ReadPropertyValueLen(Connection *conn, const char *propertyName, unsigned long *len)
|
|
{
|
|
int ccode;
|
|
long count;
|
|
char *newLine;
|
|
|
|
do {
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if (*newLine == '\n') {
|
|
newLine++;
|
|
ccode = atol(conn->receive.read);
|
|
if (ccode != 6000) {
|
|
if ((ccode > 999) && (ccode < 10000) && ((conn->receive.read[4] == ' ') || (conn->receive.read[4] == '-'))) {
|
|
if (ccode == 2001) {
|
|
char *ptr = conn->receive.read + 5;
|
|
size_t propertyNameLen = strlen(propertyName);
|
|
|
|
if (XplStrNCaseCmp(ptr, propertyName, propertyNameLen) == 0) {
|
|
ptr += propertyNameLen;
|
|
if (*ptr == ' ') {
|
|
ptr++;
|
|
count = atol(ptr);
|
|
if (count > -1) {
|
|
conn->receive.read = newLine;
|
|
*len = (unsigned long)count;
|
|
return(2001);
|
|
}
|
|
}
|
|
}
|
|
return(NMAP_ERROR_BAD_PROPERTY);
|
|
}
|
|
|
|
conn->receive.read = newLine;
|
|
return(ccode);
|
|
}
|
|
return(NMAP_ERROR_INVALID_RESPONSE_CODE);
|
|
}
|
|
|
|
if (conn->client.cb) {
|
|
if (((NMAPOutOfBoundsCallback)conn->client.cb)(conn->client.data, conn->receive.read + 5, newLine)) {
|
|
conn->receive.read = newLine;
|
|
continue;
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_FAILED);
|
|
}
|
|
|
|
return(NMAP_ERROR_CALLBACK_FUNCTION_NOT_DEFINED);
|
|
}
|
|
|
|
return(NMAP_ERROR_LINE_TOO_LONG);
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
__inline static int
|
|
ReadCrLf(Connection *conn)
|
|
{
|
|
char *newLine;
|
|
|
|
if (conn->receive.write > (conn->receive.read + 1)) {
|
|
if ((conn->receive.read[0] == '\r') && (conn->receive.read[1] == '\n')) {
|
|
conn->receive.read += 2;
|
|
return(2);
|
|
}
|
|
return(NMAP_ERROR_PROTOCOL);
|
|
}
|
|
|
|
/* go to the wire */
|
|
newLine = FindEndOfLine(conn);
|
|
if (newLine) {
|
|
if ((newLine == (conn->receive.read + 1)) && (conn->receive.read[0] == '\r')) {
|
|
newLine++;
|
|
conn->receive.read = newLine;
|
|
return(2);
|
|
}
|
|
return(NMAP_ERROR_PROTOCOL);
|
|
}
|
|
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
|
|
__inline static int
|
|
ReadPropertyValue(Connection *conn, char *property, long propertyLen)
|
|
{
|
|
long ccode;
|
|
|
|
property[propertyLen] = '\0';
|
|
if (propertyLen > 0) {
|
|
|
|
if (NMAPReadCount(conn, property, propertyLen) == propertyLen) {
|
|
;
|
|
} else {
|
|
return(NMAP_ERROR_COMM);
|
|
}
|
|
}
|
|
|
|
/* eat the extra CR LF */
|
|
if ((ccode = ReadCrLf(conn)) == 2) {
|
|
return(propertyLen);
|
|
}
|
|
|
|
return(ccode);
|
|
}
|
|
|
|
__inline static int
|
|
ReadProperty(Connection *conn, const char *propertyName, char *propertyBuffer, size_t propertyBufferLen)
|
|
{
|
|
int ccode;
|
|
unsigned long len;
|
|
|
|
if ((ccode = ReadPropertyValueLen(conn, propertyName, &len)) == 2001) {
|
|
if (len < propertyBufferLen) {
|
|
if (((ccode = ReadPropertyValue(conn, propertyBuffer, len)) > -1) && ((unsigned long)ccode == len)) {
|
|
return(2001);
|
|
}
|
|
return(ccode);
|
|
}
|
|
return(NMAP_ERROR_BUFFER_TOO_SHORT);
|
|
}
|
|
|
|
return(ccode);
|
|
}
|
|
|
|
/* Used to read and toss CRLFs that are part of the protocol
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- positive numeric is the length of the text written to the response buffer.
|
|
- negative number on failure
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
*/
|
|
|
|
int
|
|
NMAPReadCrLf(Connection *conn)
|
|
{
|
|
return(ReadCrLf(conn));
|
|
}
|
|
|
|
|
|
/** Used to read the initial response from the GETPROP and READ commands
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- positive numeric is the length of the text written to the response buffer.
|
|
- negative number on failure
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyValueLen the length of the value to be read
|
|
|
|
*/
|
|
|
|
int
|
|
NMAPReadPropertyValueLength(Connection *conn, const char *propertyName, size_t *propertyValueLen)
|
|
{
|
|
return(ReadPropertyValueLen(conn, propertyName, (unsigned long *)propertyValueLen));
|
|
}
|
|
|
|
/** Used to read text properties responses from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- positive numeric is the length of the text written to the response buffer.
|
|
- negative number on failure
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyBuffer is a pointer to a buffer where the property value will be copied
|
|
|
|
@param propertyBufferLen the length of the property buffer
|
|
|
|
|
|
*/
|
|
int
|
|
NMAPReadTextPropertyResponse(Connection *conn, const char *propertyName, char *propertyBuffer, size_t propertyBufferLen)
|
|
{
|
|
return(ReadProperty(conn, propertyName, propertyBuffer, propertyBufferLen));
|
|
}
|
|
|
|
/** Used to read text properties responses from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- positive numeric is the length of the text written to the response buffer.
|
|
- negative number on failure
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be read
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyBuffer is a pointer to a buffer where the property value will be copied
|
|
|
|
@param propertyBufferLen the length of the property buffer
|
|
|
|
|
|
*/
|
|
int
|
|
NMAPGetTextProperty(Connection *conn, uint64_t guid, const char *propertyName, char *propertyBuffer, size_t propertyBufferLen)
|
|
{
|
|
if (NMAPSendCommandF(conn, "PROPGET %llx %s\r\n", guid, propertyName) != -1) {
|
|
return(ReadProperty(conn, propertyName, propertyBuffer, propertyBufferLen));
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/** Used to write text properties to NMAP.
|
|
|
|
Remarks
|
|
- Sends the PROPSET command to NMAP and processes the response
|
|
- processes 6000 response lines encountered
|
|
|
|
@return
|
|
- 1000 on success
|
|
- other values between 1001 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be applied
|
|
|
|
@param propertyName is the property name to be set
|
|
|
|
@param propertyValue is the property value to be set
|
|
|
|
@param propertyValueLen is the length of the property value to be set
|
|
|
|
*/
|
|
int
|
|
NMAPSetTextProperty(Connection *conn, uint64_t guid, const char *propertyName, const char *propertyValue, unsigned long propertyValueLen)
|
|
{
|
|
long ccode;
|
|
|
|
if (NMAPSendCommandF(conn, "PROPSET %llx %s %lu\r\n", guid, propertyName, propertyValueLen) != -1) {
|
|
ccode = NMAPReadResponse(conn, NULL, 0, 0);
|
|
if (ccode == 2002) {
|
|
ConnWrite(conn, propertyValue, propertyValueLen);
|
|
if (ConnFlush(conn) != -1) {
|
|
return(NMAPReadResponse(conn, NULL, 0, 0));
|
|
}
|
|
return(-1);
|
|
}
|
|
return(ccode);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int
|
|
NMAPSetTextPropertyFilename(Connection *conn, const char *filename, const char *propertyName, const char *propertyValue, unsigned long propertyValueLen)
|
|
{
|
|
long ccode;
|
|
|
|
if (NMAPSendCommandF(conn, "PROPSET \"%s\" %s %lu\r\n", filename, propertyName, propertyValueLen) != -1) {
|
|
ccode = NMAPReadResponse(conn, NULL, 0, 0);
|
|
if (ccode == 2002) {
|
|
ConnWrite(conn, propertyValue, propertyValueLen);
|
|
if (ConnFlush(conn) != -1) {
|
|
return(NMAPReadResponse(conn, NULL, 0, 0));
|
|
}
|
|
return(-1);
|
|
}
|
|
return(ccode);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
#define MAX_DIGITS 25
|
|
|
|
/** Used to read decimal property responses from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- 2001 on success
|
|
- other values between 1000 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyValue is a pointer where the property value will be set
|
|
|
|
*/
|
|
int
|
|
NMAPReadDecimalPropertyResponse(Connection *conn, const char *propertyName, long *propertyValue)
|
|
{
|
|
long ccode;
|
|
char propertyBuffer[MAX_DIGITS];
|
|
|
|
ccode = ReadProperty(conn, propertyName, propertyBuffer, sizeof(propertyBuffer));
|
|
if (ccode == 2001) {
|
|
*propertyValue = atol(propertyBuffer);
|
|
return(2001);
|
|
}
|
|
return(ccode);
|
|
}
|
|
|
|
|
|
/** Used to read decimal properties from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- 2001 on success
|
|
- other values between 1000 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be read
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyValue is a pointer where the property value will be set
|
|
|
|
*/
|
|
int
|
|
NMAPGetDecimalProperty(Connection *conn, uint64_t guid, const char *propertyName, long *propertyValue)
|
|
{
|
|
if (NMAPSendCommandF(conn, "PROPGET %llx %s\r\n", guid, propertyName) != -1) {
|
|
return(NMAPReadDecimalPropertyResponse(conn, propertyName, propertyValue));
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/** Used to read hex properties response from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- 2001 on success
|
|
- other values between 1000 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be read
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyValue is a pointer where the property value will be set
|
|
|
|
*/
|
|
int
|
|
NMAPReadHexadecimalPropertyResponse(Connection *conn, const char *propertyName, unsigned long *propertyValue)
|
|
{
|
|
long ccode;
|
|
char propertyBuffer[MAX_DIGITS];
|
|
|
|
ccode = ReadProperty(conn, propertyName, propertyBuffer, sizeof(propertyBuffer));
|
|
if (ccode == 2001) {
|
|
*propertyValue = (unsigned long)HexToUInt64(propertyBuffer, NULL);
|
|
return(2001);
|
|
}
|
|
return(ccode);
|
|
}
|
|
|
|
|
|
/** Used to read hex properties from NMAP.
|
|
|
|
Remarks
|
|
- will block until a line can be read from the network
|
|
- for every 6000 line encountered the callback function is called and the next line is found
|
|
- copies the first non 6000 line excluding the \\r\\n into the response buffer
|
|
- advances read pointer to the beginning of the next line on success
|
|
|
|
@return
|
|
- 2001 on success
|
|
- other values between 1000 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be read
|
|
|
|
@param propertyName is the property name expected
|
|
|
|
@param propertyValue is a pointer where the property value will be set
|
|
|
|
*/
|
|
int
|
|
NMAPGetHexadecimalProperty(Connection *conn, uint64_t guid, const char *propertyName, unsigned long *propertyValue)
|
|
{
|
|
if (NMAPSendCommandF(conn, "PROPGET %llx %s\r\n", guid, propertyName) != -1) {
|
|
return(NMAPReadHexadecimalPropertyResponse(conn, propertyName, propertyValue));
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/** Used to write decimal properties to NMAP.
|
|
|
|
Remarks
|
|
- Sends the PROPSET command to NMAP and processes the response
|
|
- processes 6000 response lines encountered
|
|
|
|
@return
|
|
- 1000 on success
|
|
- other values between 1001 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be applied
|
|
|
|
@param propertyName is the property name to be set
|
|
|
|
@param propertyValue is the property value to be set
|
|
|
|
*/
|
|
int
|
|
NMAPSetDecimalProperty(Connection *conn, uint64_t guid, const char *propertyName, long propertyValue)
|
|
{
|
|
long ccode;
|
|
char propertyBuffer[MAX_DIGITS];
|
|
unsigned long len;
|
|
|
|
len = snprintf(propertyBuffer, sizeof(propertyBuffer), "%d", (int)propertyValue);
|
|
|
|
if (NMAPSendCommandF(conn, "PROPSET %llx %s %lu\r\n", guid, propertyName, len) != -1) {
|
|
ccode = NMAPReadResponse(conn, NULL, 0, 0);
|
|
if (ccode == 2002) {
|
|
ConnWrite(conn, propertyBuffer, len);
|
|
if (ConnFlush(conn) != -1) {
|
|
return(NMAPReadResponse(conn, NULL, 0, 0));
|
|
}
|
|
return(-1);
|
|
}
|
|
return(ccode);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/** Used to write hexadecimal properties to NMAP.
|
|
|
|
Remarks
|
|
- Sends the PROPSET command to NMAP and processes the response
|
|
- processes 6000 response lines encountered
|
|
|
|
@return
|
|
- 1000 on success
|
|
- other values between 1001 and 9999 indicate protocol error
|
|
- negative value indicates a network error
|
|
|
|
@param conn the network connection to read the line from
|
|
|
|
@param guid the object where the property will be applied
|
|
|
|
@param propertyName is the property name to be set
|
|
|
|
@param propertyValue is the property value to be set
|
|
|
|
*/
|
|
int
|
|
NMAPSetHexadecimalProperty(Connection *conn, uint64_t guid, const char *propertyName, unsigned long propertyValue)
|
|
{
|
|
long ccode;
|
|
char propertyBuffer[MAX_DIGITS];
|
|
unsigned long len;
|
|
|
|
len = snprintf(propertyBuffer, sizeof(propertyBuffer), "%x", (unsigned int)propertyValue);
|
|
|
|
if (NMAPSendCommandF(conn, "PROPSET %llx %s %lu\r\n", guid, propertyName, len) != -1) {
|
|
ccode = NMAPReadResponse(conn, NULL, 0, 0);
|
|
if (ccode == 2002) {
|
|
ConnWrite(conn, propertyBuffer, len);
|
|
if (ConnFlush(conn) != -1) {
|
|
return(NMAPReadResponse(conn, NULL, 0, 0));
|
|
}
|
|
return(-1);
|
|
}
|
|
return(ccode);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
BongoCalObject *
|
|
NMAPGetEvents(Connection *conn, const char *calendar, BongoCalTime start, BongoCalTime end)
|
|
{
|
|
int ccode;
|
|
char *split[2];
|
|
int n;
|
|
int num;
|
|
char *data;
|
|
char starts[BONGO_CAL_TIME_BUFSIZE];
|
|
char ends[BONGO_CAL_TIME_BUFSIZE];
|
|
char buffer[CONN_BUFSIZE];
|
|
BongoJsonNode *node;
|
|
BongoJsonObject *calJson;
|
|
BOOL done;
|
|
|
|
printf("Before, hour is %d, tzid is %s\n", start.hour, BongoCalTimezoneGetTzid(start.tz));
|
|
|
|
start = BongoCalTimezoneConvertTime(start, BongoCalTimezoneGetUtc());
|
|
BongoCalTimeToIcal(start, starts, BONGO_CAL_TIME_BUFSIZE);
|
|
|
|
printf("after, hour is %d\n", start.hour);
|
|
|
|
|
|
end = BongoCalTimezoneConvertTime(end, BongoCalTimezoneGetUtc());
|
|
BongoCalTimeToIcal(end, ends, BONGO_CAL_TIME_BUFSIZE);
|
|
|
|
calJson = NULL;
|
|
done = FALSE;
|
|
|
|
ccode = NMAPRunCommandF(conn, buffer, CONN_BUFSIZE, "EVENTS %s%s D%s-%s Pnmap.document\r\n",
|
|
calendar ? "C" : "",
|
|
calendar ? calendar : "",
|
|
starts, ends);
|
|
do {
|
|
switch (ccode) {
|
|
case 2001 :
|
|
ccode = NMAPReadAnswer(conn, buffer, CONN_BUFSIZE, TRUE);
|
|
if (ccode != 2001) {
|
|
continue;
|
|
}
|
|
|
|
n = BongoStringSplit(buffer, ' ', split, 2);
|
|
if (n != 2 || strcmp(split[0], "nmap.document") != 0) {
|
|
continue;
|
|
}
|
|
|
|
num = atoi(split[1]);
|
|
data = MemMalloc(num);
|
|
ccode = NMAPReadCount(conn, data, num);
|
|
if (ccode != num) {
|
|
MemFree(data);
|
|
continue;
|
|
}
|
|
|
|
ccode = NMAPReadCount(conn, buffer, 2);
|
|
if (ccode != 2) {
|
|
MemFree(data);
|
|
continue;
|
|
}
|
|
|
|
if (BongoJsonParseString(data, &node) == BONGO_JSON_OK &&
|
|
node->type == BONGO_JSON_OBJECT) {
|
|
if (calJson) {
|
|
BongoCalMerge(calJson, BongoJsonNodeAsObject(node));
|
|
} else {
|
|
calJson = BongoJsonNodeAsObject(node);
|
|
}
|
|
BongoJsonNodeFreeSteal(node);
|
|
}
|
|
|
|
MemFree(data);
|
|
|
|
break;
|
|
case 1000 :
|
|
done = TRUE;
|
|
break;
|
|
default :
|
|
if (ccode < 0) {
|
|
done = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!done) {
|
|
ccode = NMAPReadAnswer(conn, buffer, CONN_BUFSIZE, TRUE);
|
|
}
|
|
} while (!done && ccode > 0);
|
|
|
|
if (calJson) {
|
|
return BongoCalObjectNew(calJson);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int
|
|
NMAPCreateCollection(Connection *conn,
|
|
const char *collectionName,
|
|
uint64_t *guid)
|
|
{
|
|
int ccode;
|
|
char buffer[CONN_BUFSIZE];
|
|
|
|
ccode = NMAPRunCommandF(conn,
|
|
buffer,
|
|
CONN_BUFSIZE, "CREATE %s\r\n",
|
|
collectionName);
|
|
|
|
if (ccode != 2002) {
|
|
return ccode;
|
|
}
|
|
|
|
ccode = NMAPReadAnswer(conn, buffer, CONN_BUFSIZE, TRUE);
|
|
|
|
if (guid) {
|
|
if (ccode == 1000) {
|
|
char *p = strchr(buffer, ' ');
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
|
|
*guid = HexToUInt64(buffer, &p);
|
|
} else if (ccode == 4226) {
|
|
char *p = strchr(buffer, ' ');
|
|
if (p) {
|
|
p = strchr(p, ' ');
|
|
}
|
|
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
|
|
*guid = HexToUInt64(buffer, &p);
|
|
}
|
|
}
|
|
|
|
return ccode;
|
|
}
|
|
|
|
int
|
|
NMAPCreateCalendar(Connection *conn,
|
|
const char *calendarName,
|
|
uint64_t *guid)
|
|
{
|
|
char buffer[CONN_BUFSIZE];
|
|
int ccode;
|
|
|
|
ccode = NMAPRunCommandF(conn,
|
|
buffer,
|
|
CONN_BUFSIZE, "WRITE /calendars %d 0 \"F%s\"\r\n",
|
|
STORE_DOCTYPE_CALENDAR,
|
|
calendarName);
|
|
|
|
if (ccode != 2002) {
|
|
return ccode;
|
|
}
|
|
|
|
ccode = NMAPReadAnswer(conn, buffer, CONN_BUFSIZE, TRUE);
|
|
if (ccode == 1000) {
|
|
char *p = strchr(buffer, ' ');
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
|
|
if (guid) {
|
|
*guid = HexToUInt64(buffer, &p);
|
|
}
|
|
}
|
|
|
|
return ccode;
|
|
}
|
|
|
|
BOOL
|
|
NMAPAddEvent(Connection *conn, BongoCalObject *cal, const char *calendar, char *uid, int uidLen)
|
|
{
|
|
char *data;
|
|
int len;
|
|
int ccode;
|
|
BOOL ret;
|
|
char buffer[CONN_BUFSIZE];
|
|
char *p;
|
|
|
|
ret = FALSE;
|
|
|
|
data = BongoJsonObjectToString(BongoCalObjectGetJson(cal));
|
|
if (!data) {
|
|
goto done;
|
|
}
|
|
|
|
len = strlen(data);
|
|
|
|
ccode = NMAPRunCommandF(conn, buffer, CONN_BUFSIZE, "WRITE /events %d %d \"L/calendars/\"%s\r\n", STORE_DOCTYPE_EVENT, len, calendar);
|
|
if (ccode != 2002) {
|
|
goto done;
|
|
}
|
|
|
|
ConnWrite(conn, data, len);
|
|
ConnFlush(conn);
|
|
|
|
ccode = NMAPReadAnswer(conn, buffer, CONN_BUFSIZE, TRUE);
|
|
if (ccode != 1000) {
|
|
goto done;
|
|
}
|
|
p = strchr(buffer, ' ');
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
|
|
if (uid) {
|
|
BongoStrNCpy(uid, buffer, uidLen);
|
|
}
|
|
|
|
done :
|
|
if (data) {
|
|
MemFree(data);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/** NMAPRunCommandF
|
|
*
|
|
* Equivalent to NMAPSendCommandF() followed by NMAPReadResponse().
|
|
*
|
|
* Return Value
|
|
* - server response code
|
|
* - -1 upon connection error
|
|
*/
|
|
|
|
int
|
|
NMAPRunCommandF(Connection *conn, char *response, size_t length, const char *format, ...)
|
|
{
|
|
int written;
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
written = ConnWriteVF(conn, format, ap);
|
|
va_end(ap);
|
|
|
|
if (written < 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (ConnFlush(conn) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return NMAPReadResponse(conn, response, length, TRUE);
|
|
}
|
|
|
|
/** Read answer from NMAP connection. Optionally parses and returns the NMAP response number.
|
|
* \param[in] conn The NMAP Connection struct.
|
|
* \param[out] response The buffer to read the response into.
|
|
* \param[in] length The maximum number of characters to read into the \c response buffer.
|
|
* \param[in] checkForResult Enables or disables parsing out the response number.
|
|
* \return If the response number was requested and correctly parsed, then it returns
|
|
* that; -1 otherwise.
|
|
*/
|
|
int
|
|
NMAPReadAnswer(Connection *conn, unsigned char *response, size_t length, BOOL checkForResult)
|
|
{
|
|
int len;
|
|
int result = -1;
|
|
size_t count;
|
|
unsigned char *cur;
|
|
|
|
len = ConnReadAnswer(conn, response, length);
|
|
if (len > 0) {
|
|
cur = response + 4;
|
|
if (checkForResult && ((*cur == ' ') || (*cur == '-') || ((cur = strchr(response, ' ')) != NULL))) {
|
|
*cur++ = '\0';
|
|
|
|
result = atoi(response);
|
|
|
|
count = len - (cur - response);
|
|
memmove(response, cur, count);
|
|
response[count] = '\0';
|
|
} else {
|
|
result = atoi(response);
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
BOOL
|
|
NMAPReadConfigFile(const unsigned char *file, unsigned char **output)
|
|
{
|
|
Connection *conn;
|
|
char buffer[CONN_BUFSIZE + 1];
|
|
CCode ccode;
|
|
BOOL retcode = FALSE;
|
|
int tries;
|
|
|
|
/* FIXME: caller should be notified when store is ready */
|
|
for (tries = 0; tries < 5; tries++) {
|
|
conn = NMAPConnect("127.0.0.1", NULL);
|
|
if (conn) {
|
|
break;
|
|
}
|
|
XplDelay(1000);
|
|
}
|
|
if (!conn) {
|
|
printf("could not connect to store\n");
|
|
return FALSE;
|
|
}
|
|
if (!NMAPAuthenticate(conn, buffer, sizeof(buffer))) {
|
|
printf("could not authenticate to the store\n");
|
|
goto nmapfinish;
|
|
}
|
|
|
|
NMAPSendCommandF(conn, "STORE _system\r\n");
|
|
ccode = NMAPReadAnswer(conn, buffer, sizeof(buffer), TRUE);
|
|
if (ccode != 1000) {
|
|
printf("cannot access _system collection\n");
|
|
goto nmapfinish;
|
|
}
|
|
|
|
if (-1 != NMAPSendCommandF(conn, "READ /config/%s\r\n", file)) {
|
|
size_t count, written;
|
|
|
|
ccode = NMAPReadPropertyValueLength(conn, "nmap.document", &count);
|
|
if (ccode != 2001) {
|
|
printf("couldn't load config from store\n");
|
|
goto nmapfinish;
|
|
}
|
|
|
|
*output = malloc(sizeof(unsigned char) * (count+1));
|
|
written = NMAPReadCount(conn, *output, count);
|
|
NMAPReadCrLf(conn);
|
|
if (written != count) {
|
|
printf("couldn't read config from store\n");
|
|
goto nmapfinish;
|
|
}
|
|
}
|
|
retcode = TRUE;
|
|
|
|
nmapfinish:
|
|
NMAPQuit(conn);
|
|
ConnFree(conn);
|
|
return retcode;
|
|
}
|
|
|
|
int
|
|
NMAPReadAnswerLine(Connection *conn, unsigned char *response, size_t length, BOOL checkForResult)
|
|
{
|
|
int len;
|
|
int result = -1 ;
|
|
size_t count;
|
|
unsigned char *cur;
|
|
|
|
len = ConnReadLine(conn, response, length);
|
|
if (len > 0) {
|
|
cur = response + 4;
|
|
if (checkForResult && ((*cur == ' ') || (*cur == '-') || ((cur = strchr(response, ' ')) != NULL))) {
|
|
*cur++ = '\0';
|
|
|
|
result = atoi(response);
|
|
|
|
count = len - (cur - response);
|
|
memmove(response, cur, count);
|
|
response[count] = '\0';
|
|
} else {
|
|
result = atoi(response);
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
__inline static Connection *
|
|
NmapConnect(unsigned char *address, struct sockaddr_in *addr, int port, TraceDestination *destination)
|
|
{
|
|
int ccode;
|
|
Connection *conn;
|
|
|
|
if (address || addr) {
|
|
conn = ConnAlloc(TRUE);
|
|
} else {
|
|
return(NULL);
|
|
}
|
|
|
|
if (conn) {
|
|
memset(&conn->socketAddress, 0, sizeof(struct sockaddr_in));
|
|
|
|
if (address) {
|
|
conn->socketAddress.sin_family = AF_INET;
|
|
conn->socketAddress.sin_addr.s_addr = inet_addr(address);
|
|
conn->socketAddress.sin_port = htons(port);
|
|
} else {
|
|
conn->socketAddress.sin_family = addr->sin_family;
|
|
conn->socketAddress.sin_addr.s_addr = addr->sin_addr.s_addr;
|
|
conn->socketAddress.sin_port = addr->sin_port;
|
|
}
|
|
|
|
conn->socket = IPsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (conn->socket != -1) {
|
|
ccode = IPconnect(conn->socket, (struct sockaddr *)&(conn->socketAddress), sizeof(struct sockaddr_in));
|
|
CONN_TRACE_BEGIN(conn, CONN_TYPE_NMAP, destination);
|
|
CONN_TRACE_EVENT(conn, CONN_TRACE_EVENT_CONNECT);
|
|
if (!ccode) {
|
|
/* Set TCP non blocking io */
|
|
ccode = 1;
|
|
setsockopt(conn->socket, IPPROTO_TCP, 1, (unsigned char *)&ccode, sizeof(ccode));
|
|
|
|
return(conn);
|
|
}
|
|
|
|
CONN_TRACE_ERROR(conn, "connect", ccode);
|
|
CONN_TRACE_EVENT(conn, CONN_TRACE_EVENT_CLOSE);
|
|
CONN_TRACE_END(conn);
|
|
IPclose(conn->socket);
|
|
conn->socket = -1;
|
|
}
|
|
|
|
ConnFree(conn);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
Connection *
|
|
NMAPConnect(unsigned char *address, struct sockaddr_in *addr)
|
|
{
|
|
return(NmapConnect(address, addr, NMAP_PORT, NULL));
|
|
}
|
|
|
|
Connection *
|
|
NMAPConnectEx(unsigned char *address, struct sockaddr_in *addr, TraceDestination *destination)
|
|
{
|
|
return(NmapConnect(address, addr, NMAP_PORT, destination));
|
|
}
|
|
|
|
Connection *
|
|
NMAPConnectQueue(unsigned char *address, struct sockaddr_in *addr)
|
|
{
|
|
return(NmapConnect(address, addr, BONGO_QUEUE_PORT, NULL));
|
|
}
|
|
|
|
Connection *
|
|
NMAPConnectQueueEx(unsigned char *address, struct sockaddr_in *addr, TraceDestination *destination)
|
|
{
|
|
return(NmapConnect(address, addr, BONGO_QUEUE_PORT, NULL));
|
|
}
|
|
|
|
BOOL
|
|
NMAPEncrypt(Connection *conn, unsigned char *response, int length, BOOL force)
|
|
{
|
|
int ccode;
|
|
BOOL result;
|
|
Connection *c = conn;
|
|
|
|
result = c->ssl.enable = FALSE;
|
|
if (!force && XplIsLocalIPAddress(conn->socketAddress.sin_addr.s_addr)) {
|
|
return(TRUE);
|
|
}
|
|
|
|
if (NMAPLibrary.context) {
|
|
setsockopt(c->socket, IPPROTO_TCP, 1, (unsigned char *)&ccode, sizeof(ccode));
|
|
|
|
if (((ccode = ConnWrite(c, "CAPA\r\n", 6)) != -1)
|
|
&& ((ccode = ConnFlush(c)) != -1)) {
|
|
while ((ccode = NMAPReadAnswer(c, response, length, TRUE)) == 2001) {
|
|
if (strcmp(response, "TLS Encryption Extension") != 0) {
|
|
continue;
|
|
}
|
|
|
|
result = TRUE;
|
|
}
|
|
|
|
if (ccode != 1000) {
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
if (result) {
|
|
ConnWrite(c, "TLS\r\n", 5);
|
|
ConnFlush(c);
|
|
if ((NMAPReadAnswer(c, response, length, TRUE)) == 1000) {
|
|
c->ssl.enable = TRUE;
|
|
NMAPLibrary.context = NMAPSSLContextAlloc();
|
|
if (NMAPLibrary.context) {
|
|
if (ConnNegotiate(c, NMAPLibrary.context)) {
|
|
CONN_TRACE_EVENT(c, CONN_TRACE_EVENT_SSL_CONNECT);
|
|
return(TRUE);
|
|
}
|
|
ConnSSLContextFree(NMAPLibrary.context);
|
|
}
|
|
NMAPLibrary.context = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
int
|
|
NMAPAuthenticateWithCookie(Connection *conn, const char *user, const char *cookie,
|
|
unsigned char *buffer, int length)
|
|
{
|
|
int ccode;
|
|
|
|
ccode = NMAPReadAnswer(conn, buffer, length, TRUE);
|
|
switch(ccode) {
|
|
case 1000:
|
|
case 4242:
|
|
return NMAPRunCommandF(conn, buffer, length, "AUTH USER %s %s NOSTORE\r\n",
|
|
user, cookie);
|
|
default:
|
|
return ccode;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AUTH SYSTEM with the Store agent, but then change to a user and
|
|
* go into their store.
|
|
* \param conn Connection to the Queue agent
|
|
* \param response Buffer to use talking to the agent
|
|
* \param length Size of the 'response' buffer
|
|
* \return Whether or not we succeeded
|
|
*/
|
|
BOOL
|
|
NMAPAuthenticateThenUserAndStore(Connection *conn, unsigned char *user)
|
|
{
|
|
char buffer[CONN_BUFSIZE+1];
|
|
|
|
if (!NMAPAuthenticateToStore(conn, buffer, CONN_BUFSIZE))
|
|
return FALSE;
|
|
|
|
if (NMAPRunCommandF(conn, buffer, CONN_BUFSIZE, "USER %s\r\n", user) != 1000)
|
|
return FALSE;
|
|
|
|
if (NMAPRunCommandF(conn, buffer, CONN_BUFSIZE, "STORE %s\r\n", user) != 1000)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* AUTH SYSTEM with the Store agent.
|
|
* \param conn Connection to the Queue agent
|
|
* \param response Buffer to use talking to the agent
|
|
* \param length Size of the 'response' buffer
|
|
* \return Whether or not we succeeded
|
|
*/
|
|
BOOL
|
|
NMAPAuthenticateToStore(Connection *conn, unsigned char *response, int length)
|
|
{
|
|
return NMAPAuthenticate(conn, response, length);
|
|
}
|
|
|
|
/**
|
|
* AUTH SYSTEM with the Queue agent.
|
|
* \param conn Connection to the Queue agent
|
|
* \param response Buffer to use talking to the agent
|
|
* \param length Size of the 'response' buffer
|
|
* \return Whether or not we succeeded
|
|
*/
|
|
BOOL
|
|
NMAPAuthenticateToQueue(Connection *conn, unsigned char *response, int length)
|
|
{
|
|
return NMAPAuthenticate(conn, response, length);
|
|
}
|
|
|
|
BOOL
|
|
NMAPAuthenticate(Connection *conn, unsigned char *response, int length)
|
|
{
|
|
int ccode;
|
|
|
|
ccode = NMAPReadAnswer(conn, response, length, TRUE);
|
|
switch (ccode) {
|
|
case 1000: {
|
|
NMAPEncrypt(conn, response, length, FALSE);
|
|
return(TRUE);
|
|
}
|
|
|
|
case 4242: {
|
|
unsigned char *ptr;
|
|
unsigned char *salt;
|
|
unsigned char message[XPLHASH_MD5_LENGTH];
|
|
xpl_hash_context ctx;
|
|
|
|
ptr = strchr(response, '<');
|
|
if (ptr) {
|
|
salt = ++ptr;
|
|
|
|
if ((ptr = strchr(ptr, '>')) != NULL) {
|
|
*ptr = '\0';
|
|
}
|
|
|
|
XplHashNew(&ctx, XPLHASH_MD5);
|
|
XplHashWrite(&ctx, salt, strlen(salt));
|
|
XplHashWrite(&ctx, NMAPLibrary.access, NMAP_HASH_SIZE);
|
|
XplHashFinal(&ctx, XPLHASH_LOWERCASE, message, XPLHASH_MD5_LENGTH);
|
|
|
|
NMAPEncrypt(conn, response, length, FALSE);
|
|
|
|
ConnWrite(conn, "AUTH SYSTEM ", 12);
|
|
ConnWrite(conn, message, 32);
|
|
ConnWrite(conn, "\r\n", 2);
|
|
|
|
if ((ccode = ConnFlush(conn)) == 46) {
|
|
if ((ccode = NMAPReadAnswer(conn, response, length, TRUE)) == 1000) {
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Fall through to the default case statement.
|
|
*/
|
|
}
|
|
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
void
|
|
NMAPQuit(Connection *conn)
|
|
{
|
|
ConnWrite(conn, "QUIT\r\n", 6);
|
|
|
|
CONN_TCP_CLOSE(conn);
|
|
|
|
return;
|
|
}
|
|
|
|
__inline static RegistrationStates
|
|
RegisterWithQueueServer(char *queueServerIpAddress, unsigned short queueServerPort, unsigned long queueNumber, const char *queueAgentServerDn, const char *queueAgentCn, unsigned long queueAgentPort)
|
|
{
|
|
unsigned long j;
|
|
Connection *conn = NULL;
|
|
unsigned char response[CONN_BUFSIZE + 1];
|
|
|
|
NMAPLibrary.state = REGISTRATION_CONNECTING;
|
|
|
|
do {
|
|
conn = NmapConnect(queueServerIpAddress, NULL, queueServerPort, NULL);
|
|
if (conn) {
|
|
NMAPLibrary.state = REGISTRATION_REGISTERING;
|
|
break;
|
|
}
|
|
|
|
for (j = 0; (j < 15) && (NMAPLibrary.state == REGISTRATION_CONNECTING); j++) {
|
|
XplDelay(1000);
|
|
}
|
|
} while (NMAPLibrary.state == REGISTRATION_CONNECTING);
|
|
|
|
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 (ConnFlush(conn) > -1) {
|
|
if (NMAPReadAnswer(conn, response, CONN_BUFSIZE, TRUE) == 1000) {
|
|
NMAPLibrary.state = REGISTRATION_COMPLETED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NMAPQuit(conn);
|
|
}
|
|
|
|
if (conn) {
|
|
ConnFree(conn);
|
|
}
|
|
|
|
return(NMAPLibrary.state);
|
|
}
|
|
|
|
RegistrationStates
|
|
QueueRegister(const unsigned char *queueAgentCn, unsigned long queueNumber, unsigned short queueAgentPort)
|
|
{
|
|
if (!queueAgentCn) {
|
|
NMAPLibrary.state = REGISTRATION_FAILED;
|
|
return(NMAPLibrary.state);
|
|
}
|
|
|
|
NMAPLibrary.state = REGISTRATION_ALLOCATING;
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
NMAPSetEncryption(bongo_ssl_context *context)
|
|
{
|
|
NMAPLibrary.context = context;
|
|
|
|
return;
|
|
}
|
|
|
|
bongo_ssl_context *
|
|
NMAPSSLContextAlloc(void)
|
|
{
|
|
ConnSSLConfiguration config;
|
|
|
|
config.certificate.file = MsgGetTLSCertPath(NULL);
|
|
config.key.type = GNUTLS_X509_FMT_PEM;
|
|
config.key.file = MsgGetTLSKeyPath(NULL);
|
|
|
|
return ConnSSLContextAlloc(&config);
|
|
}
|
|
|
|
BOOL
|
|
NMAPInitialize(void)
|
|
{
|
|
// single cred for both store and queue atm...
|
|
return MsgGetServerCredential(NMAPLibrary.access);
|
|
}
|