Public paste
Undefined
By: Guest | Date: Jun 9 2010 14:22 | Format: None | Expires: never | Size: 31.34 KB | Hits: 483

  1. /*******************************************************************************
  2.  * shroudBNC - an object-oriented framework for IRC                            *
  3.  * Copyright (C) 2005-2007 Gunnar Beutner                                      *
  4.  *                                                                             *
  5.  * This program is free software; you can redistribute it and/or               *
  6.  * modify it under the terms of the GNU General Public License                 *
  7.  * as published by the Free Software Foundation; either version 2              *
  8.  * of the License, or (at your option) any later version.                      *
  9.  *                                                                             *
  10.  * This program is distributed in the hope that it will be useful,             *
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of              *
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
  13.  * GNU General Public License for more details.                                *
  14.  *                                                                             *
  15.  * You should have received a copy of the GNU General Public License           *
  16.  * along with this program; if not, write to the Free Software                 *
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *
  18.  *******************************************************************************/
  19.  
  20. #include "StdAfx.h"
  21.  
  22. extern "C" {
  23.         #include "md5/global.h"
  24.         #include "md5/md5.h"
  25. }
  26.  
  27. /**
  28.  * ArgTokenize
  29.  *
  30.  * Tokenizes a string (i.e. splits it into arguments). ArgFree must
  31.  * eventually be called on the returned string.
  32.  *
  33.  * @param Data the string
  34.  */
  35. const char *ArgTokenize(const char *Data) {
  36.         char *Copy;
  37.         size_t LengthData, Size;
  38.  
  39.         if (Data == NULL) {
  40.                 return NULL;
  41.         }
  42.  
  43.         LengthData = strlen(Data);
  44.  
  45.         Size = LengthData + 2;
  46.         Copy = (char *)malloc(Size);
  47.  
  48.         CHECK_ALLOC_RESULT(Copy, malloc) {
  49.                 return NULL;
  50.         } CHECK_ALLOC_RESULT_END;
  51.  
  52.         strmcpy(Copy, Data, Size);
  53.         Copy[LengthData + 1] = '';
  54.  
  55.         for (unsigned int i = 0; i < LengthData; i++) {
  56.                 if (Copy[i] == ' ' && Copy[i + 1] != ' ' && Copy[i + 1] != '') {
  57.                         Copy[i] = '';
  58.  
  59.                         if (i > 0 && Copy[i + 1] == ':') {
  60.                                 break;
  61.                         }
  62.                 }
  63.         }
  64.  
  65.         return Copy;
  66. }
  67.  
  68. /**
  69.  * ArgParseServerLine
  70.  *
  71.  * Tokenizes a line which was read from an irc server.
  72.  *
  73.  * @param Data the line
  74.  */
  75. const char *ArgParseServerLine(const char *Data) {
  76.         if (Data != NULL && Data[0] == ':') {
  77.                 Data++;
  78.         }
  79.  
  80.         return ArgTokenize(Data);
  81. }
  82.  
  83. /**
  84.  * ArgGet
  85.  *
  86.  * Retrieves an argument from a tokenized string.
  87.  *
  88.  * @param Args the tokenized string
  89.  * @param Arg the index of the argument which is to be returned
  90.  */
  91. const char *ArgGet(const char *Args, int Arg) {
  92.         for (int i = 0; i < Arg - 1; i++) {
  93.                 Args += strlen(Args) + 1;
  94.  
  95.                 if (Args[0] == '') {
  96.                         return NULL;
  97.                 }
  98.         }
  99.  
  100.         if (Args[0] == ':') {
  101.                 Args++;
  102.         }
  103.  
  104.         return Args;
  105. }
  106.  
  107. /**
  108.  * ArgCount
  109.  *
  110.  * Returns the number of arguments in a tokenized string.
  111.  *
  112.  * @param Args the tokenized string
  113.  */
  114. int ArgCount(const char *Args) {
  115.         int Count = 0;
  116.  
  117.         if (Args == NULL) {
  118.                 return 0;
  119.         }
  120.  
  121.         while (true) {
  122.                 Args += strlen(Args) + 1;
  123.                 Count++;
  124.  
  125.                 if (strlen(Args) == 0) {
  126.                         return Count;
  127.                 }
  128.         }
  129. }
  130.  
  131. /**
  132.  * ArgToArray
  133.  *
  134.  * Converts a tokenized string into an array. ArgFreeArray must
  135.  * eventually be called on the returned string.
  136.  *
  137.  * @param Args the tokenized string.
  138.  */
  139. const char **ArgToArray(const char *Args) {
  140.         int Count = ArgCount(Args);
  141.  
  142.         const char **ArgArray = (const char **)malloc(Count * sizeof(const char *));
  143.  
  144.         CHECK_ALLOC_RESULT(ArgArray, malloc) {
  145.                 return NULL;
  146.         } CHECK_ALLOC_RESULT_END;
  147.  
  148.         for (int i = 0; i < Count; i++) {
  149.                 ArgArray[i] = ArgGet(Args, i + 1);
  150.         }
  151.  
  152.         return ArgArray;
  153. }
  154.  
  155. /**
  156.  * ArgRejoinArray
  157.  *
  158.  * "Rejoins" arguments in an array.
  159.  *
  160.  * @param ArgV the array
  161.  * @param Index the index of the first argument which is to be rejoined
  162.  */
  163. void ArgRejoinArray(const char **ArgV, int Index) {
  164.         int Count = ArgCount(ArgV[0]);
  165.  
  166.         if (Count - 1 <= Index) {
  167.                 return;
  168.         }
  169.  
  170.         for (int i = Index + 1; i < Count; i++) {
  171.                 char *Arg = const_cast<char *>(ArgV[i]);
  172.  
  173.                 if (strchr(Arg, ' ') != NULL || *(Arg - 1) == ':') {
  174.                         *(Arg - 1) = ':';
  175.                         *(Arg - 2) = ' ';
  176.                 } else {
  177.                         *(Arg - 1) = ' ';
  178.                 }
  179.         }
  180. }
  181.  
  182. /**
  183.  * ArgDupArray
  184.  *
  185.  * Duplicates an array of arguments.
  186.  *
  187.  * @param ArgV the array
  188.  */
  189. const char **ArgDupArray(const char **ArgV) {
  190.         char **Dup;
  191.         size_t Len = 0;
  192.         size_t Offset;
  193.         int Count = ArgCount(ArgV[0]);
  194.  
  195.         for (int i = 0; i < Count; i++) {
  196.                 Len += strlen(ArgV[i]) + 1;
  197.         }
  198.  
  199.         Dup = (char **)malloc(Count * sizeof(char *) + Len + 2);
  200.  
  201.         Offset = (char *)Dup + Count * sizeof(char *) - ArgV[0];
  202.  
  203.         memcpy(Dup, ArgV, Count * sizeof(char *));
  204.         memcpy((char *)Dup + Count * sizeof(char *), ArgV[0], Len + 2);
  205.  
  206.         for (int i = 0; i < Count; i++)
  207.                 Dup[i] += Offset;
  208.  
  209.         return (const char **)Dup;
  210. }
  211.  
  212. /**
  213.  * ArgFree
  214.  *
  215.  * Frees a tokenized string.
  216.  *
  217.  * @param Args the tokenized string
  218.  */
  219. void ArgFree(const char *Args) {
  220.         free(const_cast<char *>(Args));
  221. }
  222.  
  223. /**
  224.  * ArgFreeArray
  225.  *
  226.  * Frees an array of arguments.
  227.  *
  228.  * @param Array the array
  229.  */
  230. void ArgFreeArray(const char **Array) {
  231.         free(const_cast<char **>(Array));
  232. }
  233.  
  234. /**
  235.  * ArgTokenize2
  236.  *
  237.  * Tokenizes a string and returns it.
  238.  *
  239.  * @param String the string
  240.  */
  241. tokendata_t ArgTokenize2(const char *String) {
  242.         tokendata_t tokens;
  243.         register unsigned int a = 1;
  244.         size_t Len = min(strlen(String), sizeof(tokens.String) - 1);
  245.  
  246.         memset(tokens.String, 0, sizeof(tokens.String));
  247.         strmcpy(tokens.String, String, sizeof(tokens.String));
  248.  
  249.         tokens.Pointers[0] = 0;
  250.  
  251.         for (unsigned int i = 0; i < Len; i++) {
  252.                 if (String[i] == ' ' && String[i + 1] != ' ') {
  253.                         if (String[i + 1] == '') {
  254.                                 tokens.String[i] = '';
  255.  
  256.                                 continue;
  257.                         }
  258.  
  259.                         tokens.Pointers[a] = i + 1;
  260.                         tokens.String[i] = '';
  261.  
  262.                         a++;
  263.  
  264.                         if (a >= 32) {
  265.                                 break;
  266.                         }
  267.  
  268.                         if (String[i + 1] == ':') {
  269.                                 tokens.Pointers[a - 1]++;
  270.  
  271.                                 break;
  272.                         }
  273.                 }
  274.         }
  275.  
  276.         tokens.Count = a;
  277.  
  278.         return tokens;
  279. }
  280.  
  281. /**
  282.  * ArgToArray2
  283.  *
  284.  * Constructs a pointer array for a tokendata_t structure. The returned
  285.  * array has to be passed to ArgFreeArray.
  286.  *
  287.  * @param Tokens the tokenized string
  288.  */
  289. const char **ArgToArray2(const tokendata_t& Tokens) {
  290.         const char **Pointers;
  291.        
  292.         Pointers = (const char **)malloc(sizeof(const char *) * 33);
  293.  
  294.         memset(Pointers, 0, sizeof(const char *) * 33);
  295.  
  296.         CHECK_ALLOC_RESULT(Pointers, malloc) {
  297.                 return NULL;
  298.         } CHECK_ALLOC_RESULT_END;
  299.  
  300.         for (unsigned int i = 0; i < min(Tokens.Count, 32); i++) {
  301.                 Pointers[i] = Tokens.Pointers[i] + Tokens.String;
  302.         }
  303.  
  304.         return Pointers;
  305. }
  306.  
  307. /**
  308.  * ArgGet2
  309.  *
  310.  * Retrieves an argument from a tokenized string.
  311.  *
  312.  * @param Tokens the tokenized string
  313.  * @param Arg the index of the argument which is to be returned
  314.  */
  315. const char *ArgGet2(const tokendata_t& Tokens, unsigned int Arg) {
  316.         if (Arg >= Tokens.Count) {
  317.                 return NULL;
  318.         } else {
  319.                 return Tokens.Pointers[Arg] + Tokens.String;
  320.         }
  321. }
  322.  
  323. /**
  324.  * ArgCount2
  325.  *
  326.  * Returns the number of arguments in a tokenized string.
  327.  *
  328.  * @param Tokens the tokenized string
  329.  */
  330. unsigned int ArgCount2(const tokendata_t& Tokens) {
  331.         return Tokens.Count;
  332. }
  333.  
  334. /**
  335.  * SocketAndConnect
  336.  *
  337.  * Creates a socket and connects to the specified host/port. You should use
  338.  * SocketAndConnectResolved instead wherever possible as this function uses
  339.  * blocking DNS requests.
  340.  *
  341.  * @param Host the host
  342.  * @param Port the port
  343.  * @param BindIp the ip address/hostname which should be used for binding the socket
  344.  */
  345. SOCKET SocketAndConnect(const char *Host, unsigned short Port, const char *BindIp) {
  346.         unsigned long lTrue = 1;
  347.         sockaddr_in sin, sloc;
  348.         SOCKET Socket;
  349.         hostent *hent;
  350.         unsigned long addr;
  351.         int code;
  352.  
  353.         if (Host == NULL || Port == 0) {
  354.                 return INVALID_SOCKET;
  355.         }
  356.  
  357.         Socket = safe_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  358.  
  359.         if (Socket == INVALID_SOCKET) {
  360.                 return INVALID_SOCKET;
  361.         }
  362.  
  363.         safe_ioctlsocket(Socket, FIONBIO, &lTrue);
  364.  
  365.         if (BindIp && *BindIp) {
  366.                 sloc.sin_family = AF_INET;
  367.                 sloc.sin_port = 0;
  368.  
  369.                 hent = gethostbyname(BindIp);
  370.  
  371.                 if (hent) {
  372.                         in_addr *peer = (in_addr *)hent->h_addr_list[0];
  373.  
  374.                         sloc.sin_addr.s_addr = peer->s_addr;
  375.                 } else {
  376.                         addr = inet_addr(BindIp);
  377.  
  378.                         sloc.sin_addr.s_addr = addr;
  379.                 }
  380.  
  381.                 safe_bind(Socket, (sockaddr *)&sloc, sizeof(sloc));
  382.         }
  383.  
  384.         sin.sin_family = AF_INET;
  385.         sin.sin_port = htons(Port);
  386.  
  387.         hent = gethostbyname(Host);
  388.  
  389.         if (hent) {
  390.                 in_addr *peer = (in_addr *)hent->h_addr_list[0];
  391.  
  392.                 sin.sin_addr.s_addr = peer->s_addr;
  393.         } else {
  394.                 addr = inet_addr(Host);
  395.  
  396.                 sin.sin_addr.s_addr = addr;
  397.         }
  398.  
  399.         code = safe_connect(Socket, (const sockaddr *)&sin, sizeof(sin));
  400.  
  401. #ifdef _WIN32
  402.         if (code != 0 && safe_errno() != WSAEWOULDBLOCK) {
  403. #else
  404.         if (code != 0 && safe_errno() != EINPROGRESS) {
  405. #endif
  406.                 safe_closesocket(Socket);
  407.  
  408.                 return INVALID_SOCKET;
  409.         }
  410.  
  411.         return Socket;
  412. }
  413.  
  414. /**
  415.  * SocketAndConnectResolved
  416.  *
  417.  * Creates a socket and connects to the specified host/port.
  418.  *
  419.  * @param Host the host's ip address
  420.  * @param BindIp the ip address which should be used for binding the socket
  421.  */
  422. SOCKET SocketAndConnectResolved(const sockaddr *Host, const sockaddr *BindIp) {
  423.         unsigned long lTrue = 1;
  424.         int Code, Size;
  425.  
  426.         SOCKET Socket = safe_socket(Host->sa_family, SOCK_STREAM, IPPROTO_TCP);
  427.  
  428.         if (Socket == INVALID_SOCKET) {
  429.                 return INVALID_SOCKET;
  430.         }
  431.  
  432.         safe_ioctlsocket(Socket, FIONBIO, &lTrue);
  433.  
  434.         if (BindIp != NULL) {
  435.                 safe_bind(Socket, (sockaddr *)BindIp, SOCKADDR_LEN(BindIp->sa_family));
  436.         }
  437.  
  438. #ifdef IPV6
  439.         if (Host->sa_family == AF_INET) {
  440. #endif
  441.                 Size = sizeof(sockaddr_in);
  442. #ifdef IPV6
  443.         } else {
  444.                 Size = sizeof(sockaddr_in6);
  445.         }
  446. #endif
  447.  
  448.         Code = safe_connect(Socket, Host, Size);
  449.  
  450. #ifdef _WIN32
  451.         if (Code != 0 && safe_errno() != WSAEWOULDBLOCK) {
  452. #else
  453.         if (Code != 0 && safe_errno() != EINPROGRESS) {
  454. #endif
  455.                 safe_closesocket(Socket);
  456.  
  457.                 return INVALID_SOCKET;
  458.         }
  459.  
  460.         return Socket;
  461. }
  462.  
  463. /**
  464.  * NickFromHostname
  465.  *
  466.  * Given a complete hostmask (nick!ident@host) this function returns a copy
  467.  * of the nickname. The result must be passed to free() when it is no longer used.
  468.  *
  469.  * @param Hostmask the hostmask
  470.  */
  471. char *NickFromHostmask(const char *Hostmask) {
  472.         char *Copy;
  473.         const char *ExclamationMark;
  474.  
  475.         ExclamationMark = strstr(Hostmask, "!");
  476.  
  477.         if (ExclamationMark == NULL) {
  478.                 return NULL;
  479.         }
  480.  
  481.         Copy = strdup(Hostmask);
  482.  
  483.         if (Copy == NULL) {
  484.                 LOGERROR("strdup() failed. Could not parse hostmask (%s).", Hostmask);
  485.  
  486.                 return NULL;
  487.         }
  488.  
  489.         Copy[ExclamationMark - Hostmask] = '';
  490.  
  491.         return Copy;
  492. }
  493.  
  494. /**
  495.  * CreateListener
  496.  *
  497.  * Creates a new listening socket.
  498.  *
  499.  * @param Port the port this socket should listen on
  500.  * @param BindIp the IP address this socket should be bound to
  501.  * @param Family address family (i.e. IPv4 or IPv6)
  502.  */
  503. SOCKET CreateListener(unsigned short Port, const char *BindIp, int Family) {
  504.         sockaddr *saddr;
  505.         sockaddr_in sin;
  506. #ifdef IPV6
  507.         sockaddr_in6 sin6;
  508. #endif
  509.         const int optTrue = 1;
  510.         bool Bound = false;
  511.         SOCKET Listener;
  512.         hostent *hent;
  513.  
  514.         Listener = safe_socket(Family, SOCK_STREAM, IPPROTO_TCP);
  515.  
  516.         if (Listener == INVALID_SOCKET) {
  517.                 return INVALID_SOCKET;
  518.         }
  519.  
  520. #ifndef _WIN32
  521.         safe_setsockopt(Listener, SOL_SOCKET, SO_REUSEADDR, (char *)&optTrue, sizeof(optTrue));
  522. #endif
  523.  
  524. #ifdef IPV6
  525.         if (Family == AF_INET) {
  526. #endif
  527.                 sin.sin_family = AF_INET;
  528.                 sin.sin_port = htons(Port);
  529.  
  530.                 saddr = (sockaddr *)&sin;
  531. #ifdef IPV6
  532.         } else {
  533.                 memset(&sin6, 0, sizeof(sin6));
  534.                 sin6.sin6_family = AF_INET6;
  535.                 sin6.sin6_port = htons(Port);
  536.  
  537.                 saddr = (sockaddr *)&sin6;
  538.  
  539. #if !defined(_WIN32) && defined(IPV6_V6ONLY)
  540.                 safe_setsockopt(Listener, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&optTrue, sizeof(optTrue));
  541. #endif
  542.         }
  543. #endif
  544.  
  545.         if (BindIp) {
  546.                 hent = gethostbyname(BindIp);
  547.  
  548.                 if (hent) {
  549. #ifdef IPV6
  550.                         if (Family = AF_INET) {
  551. #endif
  552.                                 sin.sin_addr.s_addr = ((in_addr*)hent->h_addr_list[0])->s_addr;
  553. #ifdef IPV6
  554.                         } else {
  555.                                 memcpy(&(sin6.sin6_addr.s6_addr), &(((in6_addr*)hent->h_addr_list[0])->s6_addr), sizeof(in6_addr));
  556.                         }
  557. #endif
  558.  
  559.                         Bound = true;
  560.                 }
  561.         }
  562.  
  563.         if (!Bound) {
  564. #ifdef IPV6
  565.                 if (Family == AF_INET) {
  566. #endif
  567.                         sin.sin_addr.s_addr = htonl(INADDR_ANY);
  568. #ifdef IPV6
  569.                 } else {
  570.                         memcpy(&(sin6.sin6_addr.s6_addr), &in6addr_any, sizeof(in6_addr));
  571.                 }
  572. #endif
  573.         }
  574.  
  575.         if (safe_bind(Listener, saddr, SOCKADDR_LEN(Family)) != 0) {
  576.                 safe_closesocket(Listener);
  577.  
  578.                 return INVALID_SOCKET;
  579.         }
  580.  
  581.         if (safe_listen(Listener, SOMAXCONN) != 0) {
  582.                 safe_closesocket(Listener);
  583.  
  584.                 return INVALID_SOCKET;
  585.         }
  586.  
  587.         return Listener;
  588. }
  589.  
  590. /**
  591.  * UtilSaltedMd5
  592.  *
  593.  * Computes the MD5 hash of a given string and returns
  594.  * a string representation of the hash.
  595.  *
  596.  * @param String the string which should be hashed
  597.  */
  598. const char *UtilMd5(const char *String, const char *Salt) {
  599.         sMD5_CTX context;
  600.         unsigned char digest[16];
  601.         char *StringAndSalt, *StringPtr;
  602.         static char *SaltAndResult = NULL;
  603.  
  604.         free(SaltAndResult);
  605.  
  606.         if (Salt != NULL) {
  607.                 asprintf(&StringAndSalt, "%s%s", String, Salt);
  608.         } else {
  609.                 asprintf(&StringAndSalt, "%s", String);
  610.         }
  611.  
  612.         MD5Init(&context);
  613.         MD5Update(&context, (unsigned char *)StringAndSalt, strlen(StringAndSalt));
  614.         MD5Final(digest, &context);
  615.  
  616.         free(StringAndSalt);
  617.  
  618.         if (Salt != NULL) {
  619.                 SaltAndResult = (char *)malloc(strlen(Salt) + 50);
  620.                 strmcpy(SaltAndResult, Salt, strlen(Salt) + 50);
  621.                 strmcat(SaltAndResult, "$", strlen(Salt) + 50);
  622.                 StringPtr = SaltAndResult + strlen(SaltAndResult);
  623.         } else {
  624.                 StringPtr = SaltAndResult = (char *)malloc(50);
  625.         }
  626.  
  627.         for (int i = 0; i < 16; i++) {
  628. #undef sprintf
  629.                 sprintf(StringPtr + i * 2, "%02x", digest[i]);
  630.         }
  631.  
  632.         return SaltAndResult;
  633. }
  634.  
  635. /**
  636.  * GenerateSalt
  637.  *
  638.  * Generates a salt value which is suitable for use with UtilMd5().
  639.  */
  640. const char *GenerateSalt(void) {
  641.         static char Salt[33];
  642.  
  643.         for (unsigned int i = 0; i < sizeof(Salt) - 1; i++) {
  644.                 do {
  645.                         Salt[i] = 0x21 + rand() % (0xFF - 0x21);
  646.                 } while (Salt[i] == '$');
  647.         }
  648.  
  649.         Salt[sizeof(Salt) - 1] = '';
  650.  
  651.         return Salt;
  652. }
  653.  
  654. /**
  655.  * SaltFromHash
  656.  *
  657.  * Returns the salt value for a hash (or NULL if there is none).
  658.  *
  659.  * @param Hash the hash value
  660.  */
  661. const char *SaltFromHash(const char *Hash) {
  662.         static char *Salt = NULL;
  663.         const char *HashSign;
  664.  
  665.         HashSign = strchr(Hash, '$');
  666.  
  667.         if (HashSign == NULL) {
  668.                 return NULL;
  669.         }
  670.  
  671.         free(Salt);
  672.  
  673.         Salt = (char *)malloc(HashSign - Hash + 1);
  674.         strmcpy(Salt, Hash, HashSign - Hash + 1);
  675.  
  676.         return Salt;
  677. }
  678.  
  679. /**
  680.  * FlushCommands
  681.  *
  682.  * Destroy a list of commands.
  683.  *
  684.  * @param Commands the list
  685.  */
  686. void FlushCommands(commandlist_t *Commands) {
  687.         if (Commands != NULL && *Commands != NULL) {
  688.                 delete *Commands;
  689.                 *Commands = NULL;
  690.         }
  691. }
  692.  
  693. /**
  694.  * DestroyCommandT
  695.  *
  696.  * Destroy a command and frees any resources which it used. This function
  697.  * is used internally by the hashtable which is used for storing commands.
  698.  *
  699.  * @param Command the command which is to be destroyed
  700.  */
  701. static void DestroyCommandT(command_t *Command) {
  702.         free(Command->Category);
  703.         free(Command->Description);
  704.         free(Command->HelpText);
  705.         free(Command);
  706. }
  707.  
  708. /**
  709.  * AddCommand
  710.  *
  711.  * Adds a command to a list of commands.
  712.  *
  713.  * @param Commands the list of commands
  714.  * @param Name the name of the command
  715.  * @param Category the category of the command (e.g. "Admin" or "User")
  716.  * @param Description a short description of the command
  717.  * @param HelpText the associated help text (can contain embedded \n characters
  718.  */
  719. void AddCommand(commandlist_t *Commands, const char *Name, const char *Category, const char *Description, const char *HelpText) {
  720.         command_t *Command;
  721.  
  722.         if (Commands == NULL) {
  723.                 return;
  724.         }
  725.  
  726.         if (*Commands == NULL) {
  727.                 *Commands = new CHashtable<command_t *, false, 16>();
  728.  
  729.                 if (*Commands == NULL) {
  730.                         LOGERROR("new operator failed. Could not add command.");
  731.  
  732.                         return;
  733.                 }
  734.  
  735.                 (*Commands)->RegisterValueDestructor(DestroyCommandT);
  736.         }
  737.  
  738.         Command = (command_t *)malloc(sizeof(command_t));
  739.  
  740.         if (Command == NULL) {
  741.                 LOGERROR("malloc() failed. Could not add command.");
  742.  
  743.                 return;
  744.         }
  745.  
  746.         Command->Category = strdup(Category);
  747.         Command->Description = strdup(Description);
  748.         Command->HelpText = HelpText ? strdup(HelpText) : NULL;
  749.  
  750.         (*Commands)->Add(Name, Command);
  751. }
  752.  
  753. /**
  754.  * DeleteCommand
  755.  *
  756.  * Removes a command from a list of commands.
  757.  *
  758.  * @param Commands the list of commands
  759.  * @param Name the name of the command which is to be removed
  760.  */
  761. void DeleteCommand(commandlist_t *Commands, const char *Name) {
  762.         if (Commands != NULL && *Commands != NULL) {
  763.                 (*Commands)->Remove(Name);
  764.         }
  765. }
  766.  
  767. /**
  768.  * CmpCommandT
  769.  *
  770.  * Compares two commands. This function is intended to be used with qsort().
  771.  *
  772.  * @param pA the first command
  773.  * @param pB the second command
  774.  */
  775. int CmpCommandT(const void *pA, const void *pB) {
  776.         const hash_t<command_t *> *a = (const hash_t<command_t *> *)pA;
  777.         const hash_t<command_t *> *b = (const hash_t<command_t *> *)pB;
  778.  
  779.         int CmpCat = strcasecmp(a->Value->Category, b->Value->Category);
  780.  
  781.         if (CmpCat == 0) {
  782.                 return strcasecmp(a->Name, b->Name);
  783.         } else {
  784.                 return CmpCat;
  785.         }
  786. }
  787.  
  788. /**
  789.  * DestroyString
  790.  *
  791.  * Frees a string. Used by CHashtable
  792.  *
  793.  * @param String the string
  794.  */
  795. void DestroyString(char *String) {
  796.         free(String);
  797. }
  798.  
  799. /**
  800.  * IpToString
  801.  *
  802.  * Converts a sockaddr struct into a string.
  803.  *
  804.  * @param Address the address
  805.  */
  806. const char *IpToString(sockaddr *Address) {
  807.         static char Buffer[256];
  808.  
  809. #ifdef _WIN32
  810.         sockaddr *Copy = (sockaddr *)malloc(SOCKADDR_LEN(Address->sa_family));
  811.         DWORD BufferLength = sizeof(Buffer);
  812.  
  813.         CHECK_ALLOC_RESULT(Copy, malloc) {
  814.                 return "<out of memory>";
  815.         } CHECK_ALLOC_RESULT_END;
  816.  
  817.         memcpy(Copy, Address, SOCKADDR_LEN(Address->sa_family));
  818.  
  819.         if (Address->sa_family == AF_INET) {
  820.                 ((sockaddr_in *)Address)->sin_port = 0;
  821.         } else {
  822.                 ((sockaddr_in6 *)Address)->sin6_port = 0;
  823.         }
  824.  
  825.         WSAAddressToString(Address, SOCKADDR_LEN(Address->sa_family), NULL, Buffer, &BufferLength);
  826.  
  827.         free(Copy);
  828. #else
  829.         void *IpAddress;
  830.  
  831.         if (Address->sa_family == AF_INET) {
  832.                 IpAddress = &(((sockaddr_in *)Address)->sin_addr);
  833.         } else {
  834.                 IpAddress = &(((sockaddr_in6 *)Address)->sin6_addr);
  835.         }
  836.  
  837.         inet_ntop(Address->sa_family, IpAddress, Buffer, sizeof(Buffer));
  838. #endif
  839.  
  840.         return Buffer;
  841. }
  842.  
  843. /**
  844.  * CompareAddress
  845.  *
  846.  * Compares two sockaddr structs.
  847.  *
  848.  * @param pA the first sockaddr
  849.  * @param pB the second sockaddr
  850.  */
  851. int CompareAddress(const sockaddr *pA, const sockaddr *pB) {
  852.         if (pA == NULL || pB == NULL) {
  853.                 return -1; // two NULL addresses are never equal
  854.         }
  855.  
  856.         if (pA->sa_family != pB->sa_family) {
  857.                 return -1;
  858.         }
  859.  
  860.         if (pA->sa_family == AF_INET) {
  861.                 if (((sockaddr_in *)pA)->sin_addr.s_addr == ((sockaddr_in *)pB)->sin_addr.s_addr) {
  862.                         return 0;
  863.                 } else {
  864.                         return 1;
  865.                 }
  866.         }
  867.  
  868.         if (pA->sa_family == AF_INET6) {
  869.                 if (((sockaddr_in6 *)pA)->sin6_addr.s6_addr == ((sockaddr_in6 *)pB)->sin6_addr.s6_addr) {
  870.                         return 0;
  871.                 } else {
  872.                         return 1;
  873.                 }
  874.         }
  875.  
  876.         return 2;
  877. }
  878.  
  879. /**
  880.  * StrTrim
  881.  *
  882.  * Removes leading and trailing spaces from a string.
  883.  *
  884.  * @param String the string
  885.  */
  886. void StrTrim(char *String) {
  887.         size_t Length = strlen(String);
  888.         size_t Offset = 0, i;
  889.  
  890.         // remove leading spaces
  891.         for (i = 0; i < Length; i++) {
  892.                 if (String[i] == ' ') {
  893.                         Offset++;
  894.                 } else {
  895.                         break;
  896.                 }
  897.         }
  898.  
  899.         if (Offset > 0) {
  900.                 for (i = 0; i < Length; i++) {
  901.                         String[i] = String[i + Offset];
  902.                 }
  903.         }
  904.  
  905.         // remove trailing spaces
  906.         while (String[strlen(String) - 1] == ' ') {
  907.                 String[strlen(String) - 1] = '';
  908.         }
  909. }
  910.  
  911. /**
  912.  * SetPermissions
  913.  *
  914.  * A wrapper for chmod.
  915.  *
  916.  * @param Filename the file
  917.  * @param Modes the new permissions
  918.  */
  919. int SetPermissions(const char *Filename, int Modes) {
  920. #ifndef _WIN32
  921.         return chmod(Filename, Modes);
  922. #else
  923.         return 1;
  924. #endif
  925. }
  926.  
  927. /**
  928.  * RegisterZone
  929.  *
  930.  * Registers a zone information object.
  931.  *
  932.  * @param ZoneInformation the zone information object
  933.  */
  934. bool RegisterZone(CZoneInformation *ZoneInformation) {
  935.         if (g_Bouncer != NULL) {
  936.                 g_Bouncer->RegisterZone(ZoneInformation);
  937.  
  938.                 return true;
  939.         } else {
  940. #ifdef _DEBUG
  941.                 safe_printf("Error in RegisterZone!n");
  942. #endif
  943.  
  944.                 return false;
  945.         }
  946. }
  947.  
  948. /**
  949.  * FreeString
  950.  *
  951.  * Calls free() on a string.
  952.  *
  953.  * @param String the string
  954.  */
  955. void FreeString(char *String) {
  956.         free(String);
  957. }
  958.  
  959. /**
  960.  * FreeUString
  961.  *
  962.  * Calls ufree() on a string.
  963.  *
  964.  * @param String the string
  965.  */
  966. void FreeUString(char *String) {
  967.         ufree(String);
  968. }
  969.  
  970. /**
  971.  * strmcpy
  972.  *
  973.  * Behaves like strncpy. However this function guarantees that Destination
  974.  * will always be zero-terminated (unless Size is 0).
  975.  *
  976.  * @param Destination destination string
  977.  * @param Source source string
  978.  * @param Size size of the Destination buffer
  979.  */
  980. char *strmcpy(char *Destination, const char *Source, size_t Size) {
  981.         size_t CopyLength = min(strlen(Source), (Size > 0) ? Size - 1 : 0);
  982.  
  983.         memcpy(Destination, Source, CopyLength);
  984.         Destination[CopyLength] = '';
  985.  
  986.         return Destination;
  987. }
  988.  
  989. /**
  990.  * strmcat
  991.  *
  992.  * Behaves like strncat. However this function guarantees that Destination
  993.  * will always be zero-terminated (unless Size is 0).
  994.  *
  995.  * @param Destination destination string
  996.  * @param Source source string
  997.  * @param Size size of the Destination buffer
  998.  */
  999. char *strmcat(char *Destination, const char *Source, size_t Size) {
  1000.         size_t Offset = strlen(Destination);
  1001.         size_t CopyLength = min(strlen(Source), Size - Offset - 1);
  1002.  
  1003. #ifdef _DEBUG
  1004.         if (CopyLength != strlen(Source)) {
  1005.                 DebugBreak();
  1006.         }
  1007. #endif
  1008.  
  1009.         memcpy(Destination + Offset, Source, CopyLength);
  1010.         Destination[Offset + CopyLength] = '';
  1011.  
  1012.         return Destination;
  1013. }
  1014.  
  1015. #if defined(_DEBUG) && defined(_WIN32)
  1016. LONG WINAPI GuardPageHandler(EXCEPTION_POINTERS *Exception) {
  1017.         char charSymbol[sizeof(SYMBOL_INFO) + 200];
  1018.         SYMBOL_INFO *Symbol = (SYMBOL_INFO *)charSymbol;
  1019.         IMAGEHLP_LINE64 Line;
  1020.  
  1021.         if (Exception->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
  1022.                 Symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  1023.                 Symbol->MaxNameLen = sizeof(charSymbol) - sizeof(SYMBOL_INFO);
  1024.                 SymFromAddr(GetCurrentProcess(), (DWORD64)Exception->ExceptionRecord->ExceptionAddress, NULL, Symbol);
  1025.  
  1026.                 Line.SizeOfStruct = sizeof(Line);
  1027.  
  1028.                 if (SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)Exception->ExceptionRecord->ExceptionAddress, 0, &Line)) {
  1029.                         safe_printf("Hit guard page at %s. (%s:%d)n", Symbol->Name, Line.FileName, Line.LineNumber);
  1030.                 } else {
  1031.                         safe_printf("Hit guard page at %s.n", Symbol->Name);
  1032.                 }
  1033.  
  1034.                 return EXCEPTION_CONTINUE_EXECUTION;
  1035.         }
  1036.  
  1037.         return EXCEPTION_CONTINUE_SEARCH;
  1038. }
  1039.  
  1040. void mstacktrace(void) {
  1041.         STACKFRAME64 Frame;
  1042.         DWORD FramePointer;
  1043.  
  1044. //      return; /* ... */
  1045.  
  1046.         __asm mov FramePointer, ebp
  1047.  
  1048.         memset(&Frame, 0, sizeof(Frame));
  1049.  
  1050.         Frame.AddrPC.Offset = (DWORD64)_ReturnAddress();
  1051.         Frame.AddrPC.Mode = AddrModeFlat;
  1052.         Frame.AddrFrame.Offset = FramePointer;
  1053.         Frame.AddrFrame.Mode = AddrModeFlat;
  1054.  
  1055.         if (g_Bouncer != NULL) {
  1056.                 g_Bouncer->Log("---");
  1057.         }
  1058.  
  1059.         while (StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &Frame, NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
  1060.                 char charSymbol[sizeof(SYMBOL_INFO) + 200];
  1061.                 SYMBOL_INFO *Symbol = (SYMBOL_INFO *)charSymbol;
  1062.  
  1063.                 if (Frame.AddrPC.Offset == 0) {
  1064.                         break;
  1065.                 }
  1066.  
  1067.                 Symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  1068.                 Symbol->MaxNameLen = sizeof(charSymbol) - sizeof(SYMBOL_INFO);
  1069.                 SymFromAddr(GetCurrentProcess(), (DWORD64)Frame.AddrPC.Offset, NULL, Symbol);
  1070.  
  1071.                 if (g_Bouncer != NULL) {
  1072.                         g_Bouncer->Log("Call from %s", Symbol->Name);
  1073.                 }
  1074.         }
  1075. }
  1076.  
  1077. void mmark(void *Block) {
  1078.         DWORD Dummy;
  1079.         mblock *RealBlock;
  1080.  
  1081.         if (Block == NULL) {
  1082.                 return;
  1083.         }
  1084.  
  1085.         RealBlock = (mblock *)Block - 1;
  1086.  
  1087.         VirtualProtect(RealBlock, sizeof(mblock), PAGE_READWRITE, &Dummy);
  1088.  
  1089.         if (RealBlock->Marker != BLOCKMARKER) {
  1090.                 return;
  1091.         }
  1092.  
  1093.         VirtualProtect(RealBlock, sizeof(mblock) + RealBlock->Size, PAGE_READWRITE, &Dummy);
  1094. }
  1095. #endif
  1096.  
  1097. void mclaimmanager(mmanager_t *Manager) {
  1098.         Manager->ReferenceCount++;
  1099. }
  1100.  
  1101. void mreleasemanager(mmanager_t *Manager) {
  1102.         if (Manager != NULL) {
  1103.                 Manager->ReferenceCount--;
  1104.  
  1105.                 if (Manager->ReferenceCount == 0) {
  1106.                         free(Manager);
  1107.                 }
  1108.         }
  1109. }
  1110.  
  1111. void *mmalloc(size_t Size, CUser *Owner) {
  1112. #if defined(_DEBUG) && defined(_WIN32)
  1113.         DWORD Dummy;
  1114. #endif
  1115.         mblock *Block;
  1116.  
  1117.         if (Owner != NULL && !Owner->MemoryAddBytes(Size)) {
  1118.                 return NULL;
  1119.         }
  1120.  
  1121. #if defined(_DEBUG) && defined(_WIN32)
  1122.         Block = (mblock *)VirtualAlloc(NULL, sizeof(mblock) + Size, MEM_RESERVE |  MEM_COMMIT, PAGE_READWRITE);
  1123. #else
  1124.         Block = (mblock *)malloc(sizeof(mblock) + Size);
  1125. #endif
  1126.  
  1127.         if (Block == NULL) {
  1128.                 if (Owner != NULL) {
  1129.                         Owner->MemoryRemoveBytes(Size);
  1130.                 }
  1131.  
  1132.                 return NULL;
  1133.         }
  1134.  
  1135.         Block->Size = Size;
  1136.  
  1137.         if (Owner != NULL) {
  1138.                 Block->Manager = Owner->MemoryGetManager();
  1139.                 mclaimmanager(Block->Manager);
  1140.         } else {
  1141.                 Block->Manager = NULL;
  1142.         }
  1143.  
  1144. #if defined(_DEBUG) && defined(_WIN32)
  1145.         Block->Marker = BLOCKMARKER;
  1146. #endif
  1147.  
  1148. #if defined(_DEBUG) && defined(_WIN32)
  1149. /*      if (Block->Manager != NULL && g_Bouncer != NULL) {
  1150.                 safe_printf("%p = mmalloc(%d, %p), mgr refcount = %dn", Block + 1, Size, Owner, Owner->MemoryGetManager()->ReferenceCount);
  1151.         }*/
  1152.  
  1153.         VirtualProtect(Block, sizeof(mblock) + Size, PAGE_READWRITE | PAGE_GUARD, &Dummy);
  1154.  
  1155. //      mstacktrace();
  1156. #endif
  1157.  
  1158.         return Block + 1;
  1159. }
  1160.  
  1161. void mfree(void *Block) {
  1162.         mblock *RealBlock;
  1163.         unsigned int DebugRefCount;
  1164.  
  1165.         if (Block == NULL) {
  1166.                 return;
  1167.         }
  1168.  
  1169.         mmark(Block);
  1170.  
  1171.         RealBlock = (mblock *)Block - 1;
  1172.  
  1173. #if defined(_DEBUG) && defined(_WIN32)
  1174.         if (RealBlock->Marker == 0xaaaaaaaa) {
  1175.                 DebugBreak();
  1176.         }
  1177.  
  1178.         if (RealBlock->Marker != BLOCKMARKER) {
  1179.                 free(Block);
  1180.  
  1181.                 return;
  1182.         }
  1183. #endif
  1184.  
  1185. #ifdef _DEBUG
  1186.         RealBlock->Marker = 0xaaaaaaaa;
  1187. #endif
  1188.  
  1189.         if (RealBlock->Manager != NULL) {
  1190.                 DebugRefCount = RealBlock->Manager->ReferenceCount - 1;
  1191.         }
  1192.  
  1193.         if (RealBlock->Manager != NULL && RealBlock->Manager->RealManager != NULL) {
  1194.                 RealBlock->Manager->RealManager->MemoryRemoveBytes(RealBlock->Size);
  1195.  
  1196.                 mreleasemanager(RealBlock->Manager);
  1197.         }
  1198.  
  1199. #if defined(_DEBUG) && defined(_WIN32)
  1200. /*      if (RealBlock->Manager != NULL && g_Bouncer != NULL) {
  1201.                 safe_printf("mfree(%p), mgr refcount = %dn", Block, DebugRefCount);
  1202.         }*/
  1203.  
  1204.         VirtualFree(RealBlock, 0, MEM_RELEASE);
  1205.  
  1206. //      mstacktrace();
  1207. #else
  1208.         free(RealBlock);
  1209. #endif
  1210. }
  1211.  
  1212. void *mrealloc(void *Block, size_t NewSize, CUser *Manager) {
  1213. #if defined(_DEBUG) && defined(_WIN32)
  1214.         DWORD Dummy;
  1215. #endif
  1216.         mblock *RealBlock, *NewRealBlock;
  1217.         mmanager_t *NewManager;
  1218.  
  1219.         if (Block == NULL) {
  1220.                 return mmalloc(NewSize, Manager);
  1221.         }
  1222.  
  1223.         RealBlock = (mblock *)Block - 1;
  1224.  
  1225.         mmark(Block);
  1226.  
  1227.         if (RealBlock->Manager->RealManager != NULL) {
  1228.                 RealBlock->Manager->RealManager->MemoryRemoveBytes(RealBlock->Size);
  1229.         }
  1230.  
  1231.         if (Manager != NULL && !Manager->MemoryAddBytes(NewSize)) {
  1232.                 return NULL;
  1233.         }
  1234.  
  1235. #if defined(_DEBUG) && defined(_WIN32)
  1236.         NewRealBlock = (mblock *)VirtualAlloc(NULL, sizeof(mblock) + NewSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  1237.  
  1238.         if (NewRealBlock != NULL) {
  1239.                 memcpy(NewRealBlock, RealBlock, sizeof(mblock) + RealBlock->Size);
  1240.                 mfree(Block);
  1241.         }
  1242. #else
  1243.         NewRealBlock = (mblock *)realloc(RealBlock, sizeof(mblock) + NewSize);
  1244. #endif
  1245.  
  1246.         if (NewRealBlock == NULL) {
  1247.                 if (Manager != NULL) {
  1248.                         Manager->MemoryRemoveBytes(RealBlock->Size);
  1249.                 }
  1250.  
  1251.                 return NULL;
  1252.         }
  1253.  
  1254.         NewRealBlock->Size = NewSize;
  1255.  
  1256.         NewManager = Manager->MemoryGetManager();
  1257.         mclaimmanager(NewManager);
  1258.  
  1259.         mreleasemanager(NewRealBlock->Manager);
  1260.         NewRealBlock->Manager = NewManager;
  1261.  
  1262. #if defined(_DEBUG) && defined(_WIN32)
  1263.         NewRealBlock->Marker = BLOCKMARKER;
  1264.  
  1265.         VirtualProtect(NewRealBlock, sizeof(mblock) + NewSize, PAGE_READWRITE | PAGE_GUARD, &Dummy);
  1266.  
  1267. /*      if (NewManager != NULL && g_Bouncer != NULL) {
  1268.                 safe_printf("%p = mrealloc(%p, %d, %p), mgr refcount = %dn", NewRealBlock + 1, Block, NewSize, Manager, NewManager->ReferenceCount);
  1269.         }*/
  1270. //      mstacktrace();
  1271. #endif
  1272.  
  1273.         return NewRealBlock + 1;
  1274. }
  1275.  
  1276. char *mstrdup(const char *String, CUser *Manager) {
  1277.         size_t Length;
  1278.         char *Copy;
  1279.  
  1280.         Length = strlen(String);
  1281.  
  1282.         Copy = (char *)mmalloc(Length + 1, Manager);
  1283.  
  1284.         if (Copy == NULL) {
  1285.                 return NULL;
  1286.         }
  1287.  
  1288.         mmark(Copy);
  1289.         memcpy(Copy, String, Length + 1);
  1290.  
  1291.         return Copy;
  1292. }
  1293.  
  1294. extern "C" struct pollfd *registersocket(int Socket) {
  1295.         pollfd *PollFd = NULL;
  1296.         pollfd NewPollFd;
  1297.         bool NewStruct = true;
  1298.         CVector<pollfd> *PollFds;
  1299.  
  1300.         unregistersocket(Socket);
  1301.  
  1302.         PollFds = &(g_Bouncer->m_PollFds);
  1303.  
  1304.         for (unsigned int i = 0; i < PollFds->GetLength(); i++) {
  1305.                 if (PollFds->Get(i).fd == INVALID_SOCKET) {
  1306.                         PollFd = PollFds->GetAddressOf(i);
  1307.                         NewStruct = false;
  1308.  
  1309.                         break;
  1310.                 }
  1311.         }
  1312.  
  1313.         if (NewStruct) {
  1314.                 PollFd = &NewPollFd;
  1315.         }
  1316.  
  1317.         PollFd->fd = Socket;
  1318.         PollFd->events = 0;
  1319.         PollFd->revents = 0;
  1320.  
  1321.         if (NewStruct) {
  1322.                 if (!PollFds->Insert(*PollFd)) {
  1323.                         return NULL;
  1324.                 }
  1325.  
  1326.                 PollFd = PollFds->GetAddressOf(PollFds->GetLength() - 1);
  1327.         }
  1328.  
  1329.         return PollFd;
  1330. }
  1331.  
  1332. extern "C" void unregistersocket(int Socket) {
  1333.         CVector<pollfd> *PollFds;
  1334.  
  1335.         PollFds = &(g_Bouncer->m_PollFds);
  1336.  
  1337.         for (unsigned int i = 0; i < PollFds->GetLength(); i++) {
  1338.                 pollfd *PFd = PollFds->GetAddressOf(i);
  1339.  
  1340.                 if (PFd->fd == Socket) {
  1341.                         PFd->fd = INVALID_SOCKET;
  1342.                         PFd->events = 0;
  1343.                 }
  1344.         }
  1345. }
  1346.  
  1347. const sockaddr *HostEntToSockAddr(hostent *HostEnt) {
  1348.         static char Buffer[MAX_SOCKADDR_LEN];
  1349.         sockaddr_in *sin4;
  1350.         sockaddr_in6 *sin6;
  1351.  
  1352.         memset(Buffer, 0, sizeof(Buffer));
  1353.  
  1354. #ifdef IPV6
  1355.         if (HostEnt->h_addrtype == AF_INET) {
  1356. #endif
  1357.                 sin4 = (sockaddr_in *)Buffer;
  1358.  
  1359.                 sin4->sin_family = AF_INET;
  1360.                 sin4->sin_port = 0;
  1361.                 memcpy(&(sin4->sin_addr), HostEnt->h_addr_list[0], sizeof(in_addr));
  1362. #ifdef IPV6
  1363.         } else {
  1364.                 sin6 = (sockaddr_in6 *)Buffer;
  1365.  
  1366.                 sin6->sin6_family = AF_INET6;
  1367.                 sin6->sin6_port = 0;
  1368.                 memcpy(&(sin6->sin6_addr), HostEnt->h_addr_list[0], sizeof(in6_addr));
  1369.         }
  1370. #endif
  1371.  
  1372.         return (sockaddr *)Buffer;
  1373. }
  1374.  
  1375. bool StringToIp(const char *IP, int Family, sockaddr *SockAddr, socklen_t Length) {
  1376.         socklen_t *LengthPtr = &Length;
  1377.  
  1378.         memset(SockAddr, 0, Length);
  1379.  
  1380. #ifdef _WIN32
  1381.         if (WSAStringToAddress(const_cast<char *>(IP), Family, NULL, SockAddr, LengthPtr) != 0) {
  1382.                 return false;
  1383.         }
  1384. #else
  1385.         if (Length < SOCKADDR_LEN(Family)) {
  1386.                 return false;
  1387.         }
  1388.  
  1389.         if (inet_pton(Family, IP, SockAddr) <= 0) {
  1390.                 return false;
  1391.         }
  1392. #endif
  1393.  
  1394.         return true;
  1395. }
  1396.  
  1397. static int safe_passwd_cb(char *Buffer, int Size, int RWFlag, void *Cookie) {
  1398.         int Result;
  1399.         char ConfirmBuffer[128];
  1400.  
  1401.         if (g_Bouncer->IsDaemonized()) {
  1402.                 LOGERROR("Password is required to decrypt the SSL certificate. However shroudBNC"
  1403.                         " is daemonized and cannot read user input. Re-run shroudBNC with --foreground please.");
  1404.                 g_Bouncer->Fatal();
  1405.  
  1406.                 return -1;
  1407.         }
  1408.  
  1409.         if (Size > 128) {
  1410.                 Size = 128; // nobody could seriously have such a passphrase...
  1411.         }
  1412.  
  1413.         do {
  1414.                 safe_print("PEM passphrase: ");
  1415.                
  1416.                 Result = safe_scan_passwd(Buffer, Size);
  1417.                 safe_print("n");
  1418.                
  1419.                 if (Result <= 0) {
  1420.                         return 0;
  1421.                 }
  1422.  
  1423.                 if (RWFlag == 1) {
  1424.                         safe_print("Confirm PEM passphrase: ");
  1425.                        
  1426.                         Result = safe_scan_passwd(ConfirmBuffer, sizeof(ConfirmBuffer));
  1427.                         safe_print("n");
  1428.  
  1429.                         if (Result <= 0) {
  1430.                                 return 0;
  1431.                         }
  1432.  
  1433.                         if (strcmp(Buffer, ConfirmBuffer) != 0) {
  1434.                                 safe_print("The passwords you specified do not match. Please try again.n");
  1435.  
  1436.                                 continue;
  1437.                         }
  1438.                 }
  1439.  
  1440.                 break;
  1441.         } while (1);
  1442.  
  1443.         return strlen(Buffer);
  1444. }
  1445.  
  1446. void SSL_CTX_set_safe_passwd_cb(SSL_CTX *Context) {
  1447. #ifdef USESSL
  1448.         SSL_CTX_set_default_passwd_cb(Context, safe_passwd_cb);
  1449. #endif
  1450. }