Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

sipc.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001 James Hess
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the authors nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include <stddef.h>
00046 #include <sys/types.h>
00047 #include <sys/socket.h>
00048 
00049 #include "services.h"
00050 #include "options.h"
00051 #include "sipc.h"
00052 #include "nickserv.h"
00053 #include "chanserv.h"
00054 #include "hash/md5.h"
00055 #include "hash/md5pw.h"
00056 #include "log.h"
00057 extern FILE *corelog;
00058 
00059 int ipcPort = 0;
00060 
00061 int NickGetEnc(RegNickList *);
00062 int ChanGetEnc(RegChanList *);
00063 const char *GetAuthChKey(const char*, const char*, time_t, u_int32_t);
00064 const char *PrintPass(u_char pI[], char enc);
00065 extern RegId top_regnick_idnum;
00066 
00067 /********************************************************************/
00068 
00070 struct ssUInfo{
00071     char *userName; 
00072     char *password; 
00073     flag_t priv;    
00074 };
00075 
00076 const ssUInfo *getServicesSysUser(const char *username)
00077 {
00078     static ssUInfo users[] = {
00079         {"WWW/ahurt", "test",   PRIV_QUERY_NICK_ISREG | PRIV_LOGW},
00080         {"WWW/setpass", "test", PRIV_ALTER_RNICK_GEN | PRIV_RCHAN_LOGIN | PRIV_RNICK_LOGIN },
00081         {"mysid/test", "test",  PRIV_QUERY_NICK_ISREG | PRIV_QUERY_NICK_PUBLIC | PRIV_QUERY_AKILL_LIST | PRIV_QUERY_NICK_PRIVATE | PRIV_LOGW},
00082         {NULL}
00083     };
00084     int i = 0;
00085 
00086     for(i = 0; users[i].userName; i++) {
00087         if (strcmp(users[i].userName, username) == 0)
00088             return &users[i];
00089     }
00090     return NULL;
00091 }
00092 
00093 /********************************************************************/
00094 /* Handle Queries and Sets */
00095 
00096 int queryRnickString(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00097 int queryRnickStringFixed(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00098 int queryRnickFlag(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00099 int queryRnickLong(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00100 int queryRnickUint(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00101 int queryRnickUchar(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00102 int queryRnickTime(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00103 
00104 int alterRnickStringD(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00105 int alterRnickStringFixed(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00106 int alterRnickEmail(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00107 int alterRnickFlag(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00108 int alterRnickLong(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00109 int alterRnickUint(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00110 int alterRnickUchar(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00111 int alterRnickTime(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x);
00112 
00113 //#define ORNL(x) offsetof(RegNickList, x)
00114 #define ORNL(q)  (((size_t) &((RegNickList *)0)->q))
00115 
00116 struct
00117 {
00118     const char *field;
00119     int (* func)(RegNickList *, IpcConnectType *p, parse_t *pb, int x);
00120     size_t off;
00121     flag_t priv, a_priv;
00122     int (* a_func)(RegNickList *, IpcConnectType *p, parse_t *pb, int x);
00123 }
00124 rnickQueryTable[] =
00125 {
00126     { "URL", queryRnickString,  ORNL(url),
00127        0, 0, alterRnickStringD },
00128 
00129     { "EMAIL",  queryRnickStringFixed,  ORNL(email),
00130       PRIV_QUERY_NICK_PRIVATE, PRIV_ALTER_RNICK_2, alterRnickEmail },
00131 
00132     { "LAST-HOST-UNMASK",   queryRnickString,   ORNL(host),
00133       PRIV_QUERY_NICK_UNMASK, PRIV_UNDEF, queryRnickString },
00134 
00135     { "FLAGS",  queryRnickFlag,     ORNL(flags),
00136       PRIV_QUERY_NICK_PUBLIC, PRIV_ALTER_RNICK_3, alterRnickFlag },
00137 
00138     { "OPFLAGS",    queryRnickFlag,     ORNL(opflags),
00139       PRIV_QUERY_NICK_PRIVATE, PRIV_UNDEF, alterRnickFlag },
00140 
00141     { "BADPWS", queryRnickUchar,    ORNL(badpws),
00142       PRIV_QUERY_NICK_PUBLIC, PRIV_ALTER_RNICK_GEN, alterRnickUchar },
00143 
00144     { "TIMEREG",    queryRnickTime,     ORNL(timereg),
00145       PRIV_QUERY_NICK_PUBLIC, PRIV_ALTER_RNICK_3, alterRnickTime },
00146 
00147     { "NUM-MASKS",  queryRnickUint,     ORNL(amasks),
00148       PRIV_QUERY_NICK_PRIVATE, PRIV_UNDEF, alterRnickTime },
00149 
00150     { "IS-READTIME", queryRnickTime,    ORNL(is_readtime),
00151       PRIV_QUERY_NICK_PRIVATE, PRIV_ALTER_RNICK_GEN, alterRnickTime },
00152 
00153     { NULL }
00154 };
00155 
00156 /********************************************************************/
00157 
00158 int IpcConnectType::CheckPriv(flag_t pSys, flag_t pObj)
00159 {
00160     if ((pSys & PRIV_UNDEF) || (pObj & PRIV_UNDEF))
00161         return 1;
00162     if ((gpriv & pSys) != pSys)
00163         return 1;
00164 
00165     if ((opriv & pObj) != pObj)
00166         return 1;
00167     return 0;
00168 }
00169 
00170 int IpcConnectType::CheckOrPriv(flag_t pSys, flag_t pObj)
00171 {
00172     if (!(pSys & PRIV_UNDEF) && (gpriv & pSys) == pSys)
00173         return 0;
00174     if (!(pObj & PRIV_UNDEF) && (opriv & pObj) == pSys)
00175         return 0;
00176     return 1;
00177 }
00178 
00179 int queryRnickString(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00180 {
00181     char *c;
00182         if (!rnl || !rnl->nick) return 0;
00183 
00184         c = *(char **)((size_t)rnl + rnickQueryTable[x].off);
00185 
00186     if (c != NULL)
00187         p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %s", rnl->nick,
00188                     rnickQueryTable[x].field, c);
00189     else
00190         p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %s", rnl->nick,
00191                     rnickQueryTable[x].field, "");
00192     return 1;
00193 }
00194 
00195 int queryRnickStringFixed(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00196 {
00197     char *c;
00198         if (!rnl || !rnl->nick) return 0;
00199 
00200         c = (char *)((size_t)rnl + rnickQueryTable[x].off);
00201 
00202     if (c != NULL)
00203         p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %s", rnl->nick,
00204                     rnickQueryTable[x].field, c);
00205     else
00206         p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %s", rnl->nick,
00207                     rnickQueryTable[x].field, "");
00208     return 1;
00209 }
00210 
00211 int queryRnickFlag(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00212 {
00213     flag_t *c = (flag_t *)((size_t)rnl + rnickQueryTable[x].off);
00214 
00215     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00216                 rnickQueryTable[x].field, *c);
00217     return 1;
00218 }
00219 
00220 int queryRnickLong(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00221 {
00222     long *c = (long *)((size_t)rnl + rnickQueryTable[x].off);
00223 
00224     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00225                 rnickQueryTable[x].field, *c);
00226     return 1;
00227 }
00228 
00229 int queryRnickUint(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00230 {
00231     u_int *c = (u_int *)((size_t)rnl + rnickQueryTable[x].off);
00232 
00233     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00234                 rnickQueryTable[x].field, *c);
00235     return 1;
00236 }
00237 
00238 int queryRnickUchar(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00239 {
00240     u_char *c = (u_char *)((size_t)rnl + rnickQueryTable[x].off);
00241 
00242     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00243                 rnickQueryTable[x].field, *c);
00244     return 1;
00245 }
00246 
00247 int queryRnickTime(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00248 {
00249     time_t *c = (time_t *)((size_t)rnl + rnickQueryTable[x].off);
00250 
00251     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00252                 rnickQueryTable[x].field, *c);
00253     return 1;
00254 }
00255 
00256 int alterRnickStringD(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00257 {
00258     char *c = *(char **)((size_t)rnl + rnickQueryTable[x].off);
00259     char *d = parse_getarg(pb);
00260 
00261     if (c)
00262         free(c);
00263     c = (char *)0;
00264 
00265     if (d != NULL) {
00266         c = str_dup(d);
00267     }
00268     *(char **)((size_t)rnl + rnickQueryTable[x].off) = c;
00269         
00270     p->fWriteLn("OK ALTER OBJECT RNICK=%s %sx %s", rnl->nick,
00271                 rnickQueryTable[x].field, c);
00272     return 1;
00273 }
00274 
00275 int alterRnickEmail(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00276 {
00277     char *e = parse_getarg(pb);
00278 
00279     if (e == NULL)
00280         return 0;
00281     strncpyzt(rnl->email, e, EMAILLEN);
00282 
00283     p->fWriteLn("OK ALTER OBJECT RNICK=%s %sx %s", rnl->nick,
00284                 rnickQueryTable[x].field, e);
00285     return 1;
00286 }
00287 
00288 int alterRnickFlag(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00289 {
00290     flag_t *c = (flag_t *)((size_t)rnl + rnickQueryTable[x].off);
00291     char *d = parse_getarg(pb);
00292 
00293     if (d == NULL) return 0;
00294 
00295     *c = atol(d);
00296 
00297     p->fWriteLn("OK ALTER OBJECT RNICK=%s %sx %ld", rnl->nick,
00298                 rnickQueryTable[x].field, *c);
00299     return 1;
00300 }
00301 
00302 int alterRnickLong(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00303 {
00304     long *c = (long *)((size_t)rnl + rnickQueryTable[x].off);
00305     char *d = parse_getarg(pb);
00306 
00307     if (d == NULL) return 0;
00308 
00309     *c = atol(d);
00310 
00311     p->fWriteLn("OK ALTER OBJECT RNICK=%s %sx %ld", rnl->nick,
00312                 rnickQueryTable[x].field, *c);
00313     return 1;
00314 }
00315 
00316 int alterRnickUint(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00317 {
00318     u_int *c = (u_int *)((size_t)rnl + rnickQueryTable[x].off);
00319     char *d = parse_getarg(pb);
00320     int j;
00321 
00322     if (d == NULL) return 0;
00323 
00324     j = atoi(d);
00325 
00326     if (j < 0) j = 0;
00327     *c = j;
00328 
00329     p->fWriteLn("OK ALTER OBJECT RNICK=%s %sx %ld", rnl->nick,
00330                 rnickQueryTable[x].field, *c);
00331     return 1;
00332 }
00333 
00334 int alterRnickUchar(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00335 {
00336     u_char *c = (u_char *)((size_t)rnl + rnickQueryTable[x].off);
00337     char *d = parse_getarg(pb);
00338     int X;
00339 
00340     if (d == 0) return 0;
00341     X = MIN(UCHAR_MAX, MAX(0, atoi(d)));
00342     *c = X;
00343 
00344     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00345                 rnickQueryTable[x].field, *c);
00346     return 1;
00347 }
00348 
00349 int alterRnickTime(RegNickList *rnl, IpcConnectType *p, parse_t *pb, int x)
00350 {
00351     time_t *c = (time_t *)((size_t)rnl + rnickQueryTable[x].off);
00352     char *d = parse_getarg(pb);
00353     time_t e;
00354 
00355     if (d == 0) return 0;
00356     e = atol(d);
00357     *c = e;
00358 
00359     p->fWriteLn("OK QUERY OBJECT RNICK=%s %sx %ld", rnl->nick,
00360                 rnickQueryTable[x].field, *c);
00361     return 1;
00362 }
00363 /*$$*/
00364 
00368 int
00369 IpcType::alterRegNickMessage(RegNickList *rnl, const char *req, IpcConnectType *p, parse_t *pb)
00370 {
00371     char *buf;
00372     int i = 0;
00373 
00374     if (req == NULL)
00375         req = "<unknown>";
00376 
00377     if (rnl == NULL)
00378         return 0;
00379 
00380     if (p->CheckPriv(0, OPRIV_OWNER) && !(p->GetPriv() & PRIV_ALTER_RNICK_GEN)) {
00381         p->fWriteLn("ERR-NOPRIV ALTER OBJECT RNICK=%s %s "
00382                     "- User %s Not authorized to alter RNICK %s.",
00383                     rnl->nick, req, p->user, req);
00384         return 1;
00385     }
00386 
00387     for(i = 0; rnickQueryTable[i].field; i++) {
00388         if (strcmp(req, rnickQueryTable[i].field) == 0) {
00389             if ((rnickQueryTable[i].a_priv && (p->GetPriv() & rnickQueryTable[i].a_priv) != rnickQueryTable[i].a_priv)
00390                 || (rnickQueryTable[i].a_priv & PRIV_UNDEF)) 
00391             {
00392                 p->fWriteLn("ERR-NOPRIV QUERY OBJECT RNICK=%s %s"
00393                             "- User %s Not authorized to alter RNICK %s.",
00394                             rnl->nick, p->user, req, req);
00395                 return 1;
00396             }
00397             break;
00398         }
00399     }
00400 
00401     if (strcmp(req, "PASS") == 0) {
00402         buf = parse_getarg(pb);
00403 
00404         if (p->CheckPriv(0, OPRIV_SETPASS))
00405         {
00406             p->fWriteLn("ERR-NOPERM ALTER OBJECT RNICK=%s PASS - Not authorized.", rnl->nick);
00407             return 1;
00408         }
00409 
00410         if (buf == 0 || *buf == '\0' || str_cmp(buf, rnl->nick) == 0)
00411         {
00412             p->fWriteLn("ERR-SYNTAX ALTER OBJECT RNICK=%s PASS - You need to specify a valid password", rnl->nick);
00413             return 1;
00414         }
00415 
00416         pw_enter_password(buf, rnl->password, NickGetEnc(rnl));
00417         p->fWriteLn("OK ALTER OBJECT RNICK=%s PASS %s", rnl->nick, buf);
00418         rnl->flags &= ~NFORCEXFER;
00419         rnl->chpw_key = 0;
00420         return 1;
00421     }
00422 
00423     if (rnickQueryTable[i].field)
00424         return (* rnickQueryTable[i].a_func)(rnl, p, pb, i);
00425     return 0;
00426 }
00427 
00431 int
00432 IpcType::queryRegNickMessage(RegNickList *rnl, const char *req, IpcConnectType *p, parse_t *pb)
00433 {
00434     int i = 0;
00435 
00436     if (req == NULL)
00437         req = "<unknown>";
00438 
00439     if (rnl == NULL)
00440         return 0;
00441 
00442     if (!(p->GetPriv() & PRIV_QUERY_NICK_PUBLIC)) {
00443         p->fWriteLn("ERR-NOPRIV QUERY OBJECT RNICK=%s %s "
00444                     "- User %s Not authorized to query RNICK %s.",
00445                     rnl->nick, req, p->user, req);
00446         return 1;
00447     }
00448 
00449     for(i = 0; rnickQueryTable[i].field; i++) {
00450         if (strcmp(req, rnickQueryTable[i].field) == 0) {
00451             if (rnickQueryTable[i].priv && (p->GetPriv() & rnickQueryTable[i].priv) != rnickQueryTable[i].priv) 
00452             {
00453                 p->fWriteLn("ERR-NOPRIV QUERY OBJECT RNICK=%s %s"
00454                             "- User %s Not authorized to query RNICK %s.",
00455                             rnl->nick, p->user, req, req);
00456                 return 1;
00457             }
00458             break;
00459         }
00460     }
00461 
00462     if (rnickQueryTable[i].field)
00463         return (* rnickQueryTable[i].func)(rnl, p, pb, i);
00464 
00465     if (strcmp(req, "LAST-TIME") == 0) {
00466         p->fWriteLn("OK QUERY OBJECT RNICK=%s LAST-TIME %ld", rnl->nick,
00467                     rnl->timestamp);
00468         return 1;
00469     }
00470     else if (strcmp(req, "REG-TIME") == 0) {
00471         p->fWriteLn("OK QUERY OBJECT RNICK=%s REG-TIME %ld", rnl->nick,
00472                     rnl->timereg);
00473         return 1;
00474     }
00475     else if (strcmp(req, "ACC") == 0) {
00476         UserList* ul = getNickData(rnl->nick);
00477         int acc = 0;
00478 
00479         if (ul) {
00480             acc = ul->caccess > 1 ? ul->caccess : 1;
00481         }
00482 
00483         p->fWriteLn("OK QUERY OBJECT RNICK=%s ACC %ld", rnl->nick,
00484                     acc);
00485         return 1;
00486     }
00487     else if (strcmp(req, "MARK") == 0) {
00488         if (!(p->GetPriv() & PRIV_QUERY_NICK_PUBLIC)) {
00489             p->fWriteLn("ERR-NOPRIV QUERY OBJECT RNICK=%s %s "
00490                         "- User %s Not authorized to query RNICK %s.",
00491                         rnl->nick, req, p->user, req);
00492             return 1;
00493         }
00494         if (rnl->flags & NMARK)
00495             p->fWriteLn("OK QUERY OBJECT RNICK=%s MARK YES %s", rnl->nick,
00496                         rnl->markby ? rnl->markby : "*");
00497         else
00498             p->fWriteLn("OK QUERY OBJECT RNICK=%s MARK NO", rnl->nick);
00499         return 1;
00500     }
00501     else if (strcmp(req, "LAST-HOST") == 0) {
00502         if (rnl->flags & NDBISMASK)
00503             p->fWriteLn("OK QUERY OBJECT RNICK=%s LAST-HOST %s", rnl->nick,
00504                         genHostMask(rnl->host));
00505         else
00506             p->fWriteLn("OK QUERY OBJECT RNICK=%s LAST-HOST %s", rnl->nick,
00507                         rnl->host);
00508         return 1;
00509     }
00510     else if (strncmp(req, "ACCESS-", 7) == 0) {
00511         int n = atoi(req + 7), o;
00512         nAccessList *acl = NULL;
00513 
00514         if ((isdigit(req[7]) && (n < (int)rnl->amasks+1)) || req[7] == '*')
00515         {
00516             acl = LIST_FIRST(&rnl->acl);
00517 
00518             if (strcmp(req, "ACCESS-*") == 0) {
00519                 p->fWriteLn("OK QUERY OBJECT RNICK=%s ACCESS-* START",
00520                     rnl->nick);
00521                 for( ; acl != NULL ; acl = LIST_NEXT(acl, al_lst) )
00522                     p->fWriteLn("DATA RNICK=%s ACCESS-* %s",
00523                         rnl->nick, acl->mask);
00524                 p->fWriteLn("OK QUERY OBJECT RNICK=%s ACCESS-* DONE",
00525                     rnl->nick);
00526                 return 1;
00527             }
00528 
00529             if (acl != NULL)
00530             {
00531                 for( o = 0; acl ; acl = LIST_NEXT(acl, al_lst) )
00532                     if (o++ == n)
00533                         break;
00534             }
00535         }
00536 
00537         if (acl == NULL)
00538             p->fWriteLn("ERR-NOENTRY QUERY OBJECT RNICK=%s ACCESS-%d - Invalid access item",
00539                 rnl->nick, n);
00540         else {
00541 
00542             p->fWriteLn("OK QUERY OBJECT RNICK=%s ACCESS-%d %s",
00543                 rnl->nick, n, acl->mask);
00544         }
00545         return 1;
00546     }
00547     return 0;
00548 }
00549 
00550 /********************************************************************/
00551 
00557 int doNonBlock(int listenDesc)
00558 {
00559     int optionValue;
00560 
00561 #ifdef SYSV
00562     optionValue = 1;
00563 
00564     if (ioctl(listenDesc, FIONBIO, &optionValue) < 0)
00565         return -1;
00566 #else
00567     if ((optionValue = fcntl(listenDesc, F_GETFL, 0)) == -1)
00568         return -1;
00569 #ifdef O_NONBLOCK
00570     if (fcntl(listenDesc, F_SETFL, optionValue | O_NONBLOCK) == -1)
00571 #else
00572     if (fcntl(listenDesc, F_SETFL, optionValue | O_NDELAY) == -1)
00573 #endif
00574         return -1;
00575 #endif
00576     return 0;
00577 }
00578 
00584 int
00585 IpcType::start(int portNum)
00586 {
00587     struct sockaddr_in sa;
00588     int reuseAddr;
00589 
00590     listenDesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00591 
00592     if (portNum == 0)
00593         return -1;
00594 
00595     if (listenDesc < 0) {
00596         perror("socket");
00597         return -1;
00598     }
00599 
00600     bzero(&sa, sizeof(sa));
00601     sa.sin_port = htons(portNum);
00602     sa.sin_addr.s_addr = 0x100007f; /*INADDR_ANY;*/
00603     sa.sin_family = AF_INET;
00604 
00605     reuseAddr = 1;
00606     setsockopt(listenDesc, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(int));
00607 
00608     doNonBlock(listenDesc);
00609 
00610     if (bind(listenDesc, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
00611         perror("bind");
00612         return -1;
00613     }
00614 
00615     if ( listen(listenDesc, 5) < 0 ) {
00616         perror("listen");
00617         return -1;
00618     }
00619 
00620     topFd = listenDesc;
00621 
00622     return 0;
00623 }
00624 
00630 void
00631 IpcType::fdFillSet(fd_set & fset)
00632 {
00633     IpcConnectType *pConnect;
00634 
00635     if (listenDesc == -1)
00636         return;
00637 
00638     FD_SET(listenDesc, &fset);
00639 
00640     for (pConnect = links; pConnect; pConnect = pConnect->next) {
00641         if (pConnect->fd != -1) {
00642             FD_SET(pConnect->fd, &fset);
00643         }
00644     }
00645 }
00646 
00647 
00652 void
00653 IpcType::addCon(IpcConnectType *p)
00654 {
00655     p->next = links;
00656     links = p;
00657 }
00658 
00663 void
00664 IpcType::delCon(IpcConnectType *zap)
00665 {
00666     IpcConnectType *p, *p_next, *tmp;
00667 
00668     tmp = NULL;
00669 
00670     for(p = links; p; p = p_next)
00671     {
00672         p_next = p->next;
00673 
00674         if (zap == p)
00675         {
00676             if (tmp)
00677                 tmp->next = p->next;
00678             else
00679                 links = p->next;
00680             break;
00681         }
00682         else
00683             tmp = p;
00684     }
00685 
00686     topFd = listenDesc;
00687 
00688     for(p = links; p; p = p->next)
00689         if (p->fd > topFd)
00690             topFd = p->fd;
00691 }
00692 
00696 void
00697 IpcType::freeCon(IpcConnectType *zap)
00698 {
00699     zap->buf.empty();
00700     free(zap);
00701 
00702     if (zap->user)
00703         free(zap->user);
00704     if (zap->pass)
00705         free(zap->pass);
00706     if (zap->objName)
00707         free(zap->objName);
00708     if (zap->objPass)
00709         free(zap->objPass);
00710 }
00711 
00719 int
00720 IpcType::ReadPackets(IpcConnectType *ptrLink)
00721 {
00722     char sockbuf[8192+1], *b;
00723     int k, kt = 0, msgl;
00724 
00725     /* memset(sockbuf, 0, 8192);*/
00726     k = read(ptrLink->fd, sockbuf, 8191);
00727 
00728     /*if (k > 0)
00729         sockbuf[k] = '\0';
00730     else sockbuf[0] = '\0';*/
00731 
00732     while(k > 0)
00733     {
00734         kt += k;
00735         b = ptrLink->buf.shove(sockbuf, k, &msgl);
00736 
00737         if (b && *b) {
00738 
00739             strncpyzt(sockbuf, b, msgl);
00740             /* len = strlen(b); */
00741 
00742             if (msgl >= IPCBUFSIZE || msgl >= 8000)
00743                 return -1;
00744 
00745             k = read(ptrLink->fd, sockbuf + msgl, 8191 - msgl);
00746             if (k > 0)
00747                 k += msgl;
00748         }
00749         else {
00750             k = read(ptrLink->fd, sockbuf, 8191);
00751         }
00752     }
00753 
00754     if (k == 0)
00755         return -1;
00756     if (k == -1) {
00757         if (errno == EINTR || errno == EWOULDBLOCK)
00758             return 0;
00759         return -1;
00760     }
00761     return 0;
00762 }
00763 
00774 void
00775 IpcType::pollAndHandle(fd_set &readme, fd_set &writeme, fd_set &xcept)
00776 {
00777     IpcConnectType *p, *p_next;
00778     char *c;
00779 
00780     if (listenDesc == -1)
00781         return;
00782 
00783     if (FD_ISSET(listenDesc, &readme))
00784     {
00785         struct sockaddr_in sai;
00786         socklen_t alen;
00787         int pFd, ipOk;
00788 
00789         if ((pFd = accept(listenDesc, (struct sockaddr *)&sai, &alen)) != -1)
00790         {
00791             ipOk = 1;
00792 
00793             //if (sai.sin_addr.s_addr == 0x1000007f)
00794             //  ipOk = 1;
00795 
00796             if (doNonBlock(pFd) != -1 && ipOk) 
00797             {
00798                 if (pFd > topFd)
00799                     topFd = pFd;
00800                 p = (IpcConnectType *)oalloc(sizeof(IpcConnectType));
00801                 p->objType = SIPC_UNDEF;
00802                 addCon(p);
00803                 p->fd = pFd;
00804                 p->addr = sai.sin_addr;
00805             }
00806             else
00807                 close(pFd);
00808         }
00809     }
00810 
00811 
00812     for(p = links; p; p = p_next)
00813     {
00814         p_next = p->next;
00815 
00816         if (FD_ISSET(p->fd, &xcept)) {
00817             FD_CLR(p->fd, &xcept);
00818             close(p->fd);
00819             delCon(p);
00820             freeCon(p);
00821             continue;
00822         }
00823 
00824         if (FD_ISSET(p->fd, &readme)) {
00825             char buf[IPCBUFSIZE];
00826 
00827             if (ReadPackets(p) < 0)
00828             {
00829                 close(p->fd);
00830                 delCon(p);
00831                 freeCon(p);
00832                 continue;
00833             }
00834 
00835             while (p->buf.pop(buf)) {
00836                 parse_t pb;
00837 
00838                 parse_init(&pb, buf);
00839 
00840                 c = parse_getarg(&pb);
00841                 if (c == NULL)
00842                     continue;
00843 
00844                 if (strcmp(c, "AUTH") == 0) {
00845                     authMessage(p, &pb);
00846                 }
00847                 else if (strcmp(c, "QUIT") == 0) {
00848                     p->sWrite("OK QUIT\n");
00849                     close(p->fd);
00850                     p->fd = -1;
00851                 }
00852                 else if (strcmp(c, "HELP") == 0) {
00853                     p->sWrite("OK HELP\n");
00854                     p->sWrite("REPLY HELP - Commands: \n");
00855                     p->sWrite("REPLY HELP -  AUTH HELP QUERY MAKE QUIT \n");
00856                 }
00857                 else if (p->user == NULL || p->pass == NULL) {
00858                     p->fWriteLn("ERR-NOAUTH %s - You are "
00859                            "not authenticated. ",
00860                            "(Allowed: AUTH, HELP, QUIT)", buf);
00861                 }
00862                 else if (strcmp(c, "QUERY") == 0) {
00863                     queryMessage(p, &pb);
00864                 }
00865                 else if (strcmp(c, "ALTER") == 0) {
00866                     alterMessage(p, &pb);
00867                 }
00868                 else if (strcmp(c, "LOG") == 0) {
00869                     logMessage(p, &pb);
00870                 }
00871                 else if (strcmp(c, "MAKE") == 0) {
00872                     makeMessage(p, &pb);
00873                 }
00874             }
00875 
00876             if (p->fd == -1) {
00877                 delCon(p);
00878                 freeCon(p);
00879                 continue;
00880             }
00881         }
00882 
00883         if (FD_ISSET(p->fd, &writeme)) {
00884             FD_CLR(p->fd, &writeme);
00885 
00886             if (p->s == 0) {
00887                 char bufs[IPCBUFSIZE];
00888 
00889                 snprintf(
00890                     bufs, sizeof(bufs),
00891                     "HELO IAM %s\n"
00892                     "AUTH SYSTEM PID %d\n"
00893                     "AUTH SYSTEM LOGIN irc/services\n",
00894                     myname, getpid()
00895                 );
00896                 p->sWrite(bufs);
00897                 p->s = 1;
00898             }
00899         }
00900     }
00901 }
00902 
00906 void
00907 IpcType::authMessage(IpcConnectType *p, parse_t *pb)
00908 {
00909     char *buf = parse_getarg(pb);
00910 
00911     if (buf == NULL)
00912         return;
00913 
00914     if (!strcmp(buf, "SYSTEM")) {
00915         authSysMessage(p, pb);
00916     }
00917     else if (!strcmp(buf, "OBJECT")) {
00918         authObjMessage(p, pb);
00919     }
00920     else {
00921         p->sWrite("ERR-BADTYPE AUTH - No such auth type\n");
00922     }
00923 }
00924 
00928 void
00929 IpcType::queryMessage(IpcConnectType *p, parse_t *pb)
00930 {
00931     char *buf = parse_getarg(pb);
00932 
00933     if (buf == NULL)
00934         return;
00935 
00936     if (p->user == NULL) {
00937         p->sWrite("ERR-AUTH QUERY - Must authenticate to system\n");
00938         return;
00939     }
00940 
00941     if (!strcmp(buf, "SYSTEM")) {
00942         querySysMessage(p, pb);
00943     }
00944     else if (!strcmp(buf, "OBJECT")) {
00945         queryObjMessage(p, pb);
00946     }
00947     else {
00948         p->sWrite("ERR-BADTYPE QUERY - No such query type\n");
00949     }
00950 }
00951 
00952 
00956 void
00957 IpcType::logMessage(IpcConnectType *p, parse_t *pb)
00958 {
00959     char *service = parse_getarg(pb);
00960     int use_globops=0;
00961     interp::commands::services_cmd_id logt;
00962     SLogfile* logf;
00963 
00964     /* Service */
00965     if (service == NULL) {
00966         p->sWrite("ERR-AUTH ALTER - Must at least specify SERVICE - MESSAGE\n");
00967         return;
00968         }
00969 
00970     if (p->CheckPriv(PRIV_LOGW, 0)) {
00971         p->fWriteLn("LOG %s "
00972                     "- User %s does not have log writing access.",
00973                     service, p->user);
00974         return;
00975     }
00976 
00977     char* buf;
00978 
00979     while ( 1 ) {
00980         buf = parse_getarg(pb);
00981 
00982         if (buf == NULL) {
00983             p->sWrite("ERR-AUTH ALTER - Must specify a service, hyphen, message\n");
00984             return;
00985             }
00986         if (*buf == '-') {
00987             buf = parse_getallargs(pb);
00988             break;
00989         }
00990         if (!strcasecmp(buf, "GLOBOPS"))
00991             use_globops=1;
00992     }
00993 
00994     if (buf == NULL) {
00995         p->sWrite("ERR-AUTH ALTER - Must specify a service, hyphen, message\n");
00996         return;
00997         }
00998 
00999     if (!strcasecmp(service, "ChanServ")) {
01000         logt = CSE_IPC;
01001         logf = chanlog;
01002     }
01003     else if (!strcasecmp(service, "NickServ")) {
01004         logt = NSE_IPC;
01005         logf = nicklog;
01006     }
01007     else {
01008         service = "OperServ";
01009         logt = OSE_IPC;
01010         logf = operlog;
01011     }
01012 
01013     sSend(":%s GLOBOPS :(IPC:%s) %s", service, p->user, buf);
01014     logf->log(NULL, logt, NULL, 0, "(IPC:%s,%s) %s", p->user,service, buf);
01015 }
01016 
01020 void
01021 IpcType::alterMessage(IpcConnectType *p, parse_t *pb)
01022 {
01023     char *buf = parse_getarg(pb);
01024 
01025     if (buf == NULL) {
01026         p->sWrite("ERR-AUTH ALTER - Must specify target and type\n");
01027         return;
01028         }
01029 
01030     if (p->user == NULL) {
01031         p->sWrite("ERR-AUTH ALTER - Must authenticate to system\n");
01032         return;
01033     }
01034 
01035     /*if (!strcmp(buf, "SYSTEM")) {
01036         alterSysMessage(p, pb);
01037     }
01038     else*/ if (!strcmp(buf, "OBJECT")) {
01039         alterObjMessage(p, pb);
01040     }
01041     else {
01042         p->sWrite("ERR-BADTYPE QUERY - No such query type\n");
01043     }
01044 }
01045 
01049 void
01050 IpcType::authSysMessage(IpcConnectType *p, parse_t *pb)
01051 {
01052     char *str_dup(const char *);
01053     char *buf = parse_getarg(pb);
01054     const ssUInfo *q;
01055     char authBuf[IRCBUF];
01056     int valid = 0;
01057 
01058     if (buf == NULL)
01059         return;
01060 
01061     if (!strcmp(buf, "LOGIN")) {
01062 
01063         buf = parse_getarg(pb);
01064 
01065         if (buf == NULL) {
01066             p->sWrite("ERR-BADLOGIN AUTH SYSTEM LOGIN - Invalid login\n");
01067             return;
01068         }
01069 
01070         if ((q = getServicesSysUser(buf))) {
01071             valid = 1;
01072             if (p->user)
01073                 free(p->user);
01074             p->user = str_dup(buf);
01075             p->gpriv = 0;
01076             p->opriv = 0;
01077         }
01078         /*if (valid == 0) {
01079             p->sWrite("ERR-BADLOGIN AUTH SYSTEM LOGIN - Invalid login\n");
01080             return;
01081         }*/
01082 
01083         p->cookie = lrand48();
01084 
01085         p->fWriteLn("OK AUTH SYSTEM LOGIN");
01086         p->fWriteLn("AUTH COOKIE %X%X", p->fd, p->cookie);
01087         return;
01088     }
01089     else if (!strcmp(buf, "PASS")) {
01090         unsigned char digest[16], *pBuf;
01091         MD5Context ctx;
01092 
01093         buf = parse_getarg(pb);
01094 
01095         if (buf == NULL || (p->user) == NULL || (q = getServicesSysUser(p->user)) == NULL) {
01096             p->sWrite("ERR-BADLOGIN AUTH SYSTEM LOGIN - Invalid login\n");
01097             if (p->user)
01098                 SetDynBuffer(&p->user, NULL);
01099             return;
01100         }
01101 
01102         snprintf(authBuf, sizeof(authBuf), "%X%X:%s", p->fd, (u_int)p->cookie, q->password);
01103 
01104         MD5Init(&ctx);
01105         MD5Update(&ctx, (const u_char *)authBuf, strlen(authBuf));
01106         MD5Final(digest, &ctx);
01107 
01108         pBuf = (u_char *)str_dup(md5_printable(digest));
01109 
01110         if (pBuf == NULL || p == NULL) {
01111             p->sWrite("ERR-BADLOGIN AUTH SYSTEM LOGIN - Internal Failure\n");
01112             if (p->user)
01113                 SetDynBuffer(&p->user, NULL);
01114             return;
01115         }
01116 
01117         if (strcmp((char *)pBuf, buf)) {
01118             p->sWrite("ERR-BADLOGIN AUTH SYSTEM LOGIN - Invalid login\n");
01119             if (p->user)
01120                 SetDynBuffer(&p->user, NULL);
01121             return;
01122         }
01123 
01124         p->fWriteLn("OK AUTH SYSTEM PASS");
01125         p->fWriteLn("YOU ARE %s", p->user);
01126         p->pass = (char *)pBuf;
01127         p->gpriv = q->priv;
01128 
01129         if ((p->gpriv & PRIV_NOWNER_EQUIV))
01130             p->opriv |= OPRIV_OWNER;
01131         else
01132             p->opriv = 0;
01133 
01134         return;
01135     }
01136 
01137     p->fWriteLn("ERR-BADTYPE AUT SYSTEMH");
01138 }
01139 
01143 void
01144 IpcType::authObjMessage(IpcConnectType *p, parse_t *pb)
01145 {
01146     char *str_dup(const char *);
01147     char *buf = parse_getarg(pb), *buf1, *buf2, *pawd = 0, *objStr = 0;
01148     RegNickList *rnl;
01149     RegChanList *rcl;
01150     
01151     char authBuf[IRCBUF];
01152     int valid = 0;
01153 
01154     if (p->objType == SIPC_RNICK)
01155         objStr = "RNICK";
01156     else if (p->objType == SIPC_RCHAN)
01157         objStr = "RCHAN";
01158     else    objStr = "<Undef>";
01159 
01160     if (buf == NULL)
01161         return;
01162 
01163     if (!strcmp(buf, "LOGIN"))
01164     {
01165 
01166         buf1 = parse_getarg(pb);
01167         buf2 = parse_getarg(pb);
01168 
01169         objStr = buf1;
01170 
01171         if (buf1 == NULL || buf2 == NULL) {
01172             p->fWriteLn("ERR-BADLOGIN AUTH OBJECT LOGIN%s%s - Invalid login", objStr ? " " : "", objStr ? objStr : "");
01173             return;
01174         }
01175 
01176         if (!str_cmp(buf1, "RNICK") && (rnl = getRegNickData(buf2)))
01177         {
01178             p->opriv = 0;
01179             valid = 1;
01180 
01181             if (p->CheckPriv(PRIV_RNICK_LOGIN, 0)) 
01182                 valid = 0;
01183 
01184             if (p->objName)
01185                 free(p->objName);
01186             if (valid) {
01187                 p->objName = str_dup(buf2);
01188                 p->objType = SIPC_RNICK;
01189             }
01190         }
01191         else if (!str_cmp(buf1, "RCHAN") && (rcl = getRegChanData(buf2)))
01192         {
01193             p->opriv = 0;
01194             valid = 1;
01195 
01196             if (p->CheckPriv(PRIV_RCHAN_LOGIN, 0)) 
01197                 valid = 0;
01198 
01199             if (p->objName)
01200                 free(p->objName);
01201             if (valid) {
01202                 p->objName = str_dup(buf2);
01203                 p->objType = SIPC_RCHAN;
01204             }
01205         }
01206 
01207 
01208         p->cookie = lrand48();
01209         p->fWriteLn("OK AUTH OBJECT %s LOGIN", objStr);
01210         p->fWriteLn("AUTH COOKIE %X%X", p->fd, p->cookie);
01211         return;
01212     }
01213     else if (!strcmp(buf, "CHPASSKEY"))
01214     {
01215         buf1 = parse_getarg(pb);
01216 
01217         if (buf1 && p->objType == SIPC_RNICK && p->objName)
01218         {
01219             rnl = getRegNickData(p->objName);
01220 
01221             if (rnl && rnl->chpw_key)
01222             {
01223                 const char *rnE = rnl->email;
01224                 const char *rnP = PrintPass(rnl->password, NickGetEnc(rnl));
01225                 const char *pwAuthChKey;
01226 
01227                 if (rnl->flags & NFORCEXFER)
01228                     rnE = "-forced-transfer-";
01229                 pwAuthChKey = GetAuthChKey(rnE, rnP,
01230                         rnl->timereg, rnl->chpw_key);
01231                 if (strcmp(pwAuthChKey, buf1) == 0) {
01232                     p->objPass = str_dup("");
01233                     p->opriv = OPRIV_SETPASS;
01234                     p->fWriteLn("OK AUTH OBJECT SETPASS");
01235                     return;
01236                 }
01237             }
01238         }
01239 
01240         if (buf1 && p->objType == SIPC_RCHAN && p->objName)
01241         {
01242             rcl = getRegChanData(p->objName);
01243 
01244             if (rcl && rcl->chpw_key && (rnl = rcl->founderId.getNickItem()))
01245             {
01246                 const char *rcE = rnl->email;
01247                 const char *rcP = PrintPass(rcl->password, ChanGetEnc(rcl));
01248                 const char *pwAuthChKey;
01249 
01250                 if (rcl->flags & CFORCEXFER)
01251                     rcE = "-forced-transfer-";
01252                 pwAuthChKey = GetAuthChKey(rcE, rcP,
01253                         rcl->timereg, rcl->chpw_key);
01254                 if (strcmp(pwAuthChKey, buf1) == 0) {
01255                     p->objPass = str_dup("");
01256                     p->opriv = OPRIV_SETPASS;
01257                     p->fWriteLn("OK AUTH OBJECT SETPASS");
01258                     return;
01259                 }
01260             }
01261         }
01262 
01263         p->fWriteLn("ERR-BADLOGIN AUTH OBJECT %s LOGIN - Internal Failure",
01264                     objStr);
01265         if (p->objName)
01266             SetDynBuffer(&p->objName, NULL);
01267     }
01268     else if (!strcmp(buf, "PASS"))
01269     {
01270         unsigned char digest[16], *pBuf;
01271         MD5Context ctx;
01272         int valid = 0;
01273 
01274         buf = parse_getarg(pb);
01275 
01276         if (p->objType == SIPC_RNICK)
01277             objStr = "RNICK";
01278         else if (p->objType == SIPC_RCHAN)
01279             objStr = "RCHAN";
01280         else objStr = "<Undef>";
01281 
01282         if (objStr == 0) {
01283             p->fWriteLn("ERR-BADLOGIN AUTH OBJECT %s LOGIN - Invalid login", objStr);
01284             if (p->objName)
01285                 SetDynBuffer(&p->objName, NULL);
01286             return;
01287         }
01288 
01289         if (buf && p->objType == SIPC_RNICK && p->objName &&
01290             (rnl = getRegNickData(p->objName)))
01291         {
01292             valid = 1;
01293             if (rnl->flags & NENCRYPT)
01294                 pawd = md5_printable(rnl->password);
01295             else
01296                 pawd = md5_printable(md5_password(rnl->password));
01297         }
01298         else if (buf && p->objType == SIPC_RCHAN && p->objName &&
01299             (rcl = getRegChanData(p->objName)))
01300         {
01301             valid = 1;
01302             if (rcl->flags & CENCRYPT)
01303                 pawd = md5_printable(rcl->password);
01304             else
01305                 pawd = md5_printable(md5_password(rcl->password));
01306         }
01307         else {
01308             p->fWriteLn("ERR-BADLOGIN AUTH OBJECT %s LOGIN - Invalid login", objStr);
01309             if (p->objName)
01310                 SetDynBuffer(&p->objName, NULL);
01311             return;
01312         }
01313 
01314         snprintf(authBuf, sizeof(authBuf), "%X%X:%s", p->fd, (u_int)p->cookie, pawd);
01315 
01316         MD5Init(&ctx);
01317         MD5Update(&ctx, (const u_char *)authBuf, strlen(authBuf));
01318         MD5Final(digest, &ctx);
01319 
01320         pBuf = (u_char *)str_dup(md5_printable(digest));
01321 
01322         if (pBuf == NULL || p == NULL) {
01323             p->fWriteLn("ERR-BADLOGIN AUTH OBJECT %s LOGIN - Internal Failure",
01324                         objStr);
01325             if (p->objName)
01326                 SetDynBuffer(&p->objName, NULL);
01327             return;
01328         }
01329 
01330         if (strcmp((char *)pBuf, buf)) {
01331             p->fWriteLn("ERR-BADLOGIN AUTH OBJECT %s LOGIN - Invalid login", objStr);
01332             if (p->objName)
01333                 SetDynBuffer(&p->objName, NULL);
01334             return;
01335         }
01336 
01337         p->fWriteLn("OK AUTH OBJECT %s PASS", objStr);
01338         /* p->fWriteLn("YOU ARE %s", ); */
01339         p->objPass = (char *)pBuf;
01340         p->opriv = OPRIV_OWNER;
01341         return;
01342     }
01343 
01344     p->fWriteLn("ERR-BADTYPE AUTH OBJET");
01345 }
01346 
01347 
01351 int isQlined(const char *nick)
01352 {
01353     int i;
01354 
01355     const char *forbiddenPatterns[] =
01356     {
01357         "DALnet",       "SorceryNet",       "Status",
01358         "AUX",          "PRN",          "LPT?",
01359         "COM?",         "K9",           "W",
01360         "X",            "NoteOp",       "OperOp",
01361         "ChanOp",       "NickOp",       "*Serv",
01362         "HelpServ",     "*He*p*S*rv*",      "ChanServ",
01363         "*Ch*n*S*rv*",      "NickServ",     "*Ni*k*S*rv*",
01364         "MemoServ",     "*Me*o*S*rv*",      "OperServ",
01365         "*Op*r*S*rv*",      "Warlock",      "ServOp",
01366         "Sorcery*",     "IRCop",        "*IRC*op*",
01367         "kline",        "Services",     "admin*",
01368         "ms",           "ns",           "cs",
01369         "os",
01370         "ServBot",      "ChannelBot",       "*net*admin*",
01371         "Auth-*",
01372         NULL
01373     };
01374 
01375     for(i = 0; forbiddenPatterns[i]; i++)
01376         if (match(forbiddenPatterns[i], nick) == 0)
01377             return 1;
01378     return 0;
01379 }
01380 
01384 void
01385 IpcType::makeMessage(IpcConnectType *p, parse_t *pb)
01386 {
01387     char pwStuff[PASSLEN + 1];
01388     char *buf = parse_getarg(pb);
01389 
01390     if (!p->user) {
01391         p->sWrite("ERR-NOTAUTH MAKE - You must be authenticated to make something.\n");
01392         return;
01393     }
01394 
01395     if (buf != NULL)
01396     {
01397         if (strcmp(buf, "RCHAN") == 0) {
01398             p->sWrite("ERR-UNIMPLEMENTED MAKE RCHAN - Not yet implemented\n");
01399         }
01400         else if (strcmp(buf, "RNICK") == 0) {
01401             RegNickList *ptrNick;
01402             char *nick = parse_getarg(pb);
01403             char *email = parse_getarg(pb);
01404             char *host = parse_getarg(pb);
01405             char *ptrChar;
01406             int pws;
01407 
01408             if (nick == NULL) {
01409                 p->fWrite("ERR-NONICK MAKE NICK=%s - Nickname missing\n", nick);
01410                 return;
01411             }
01412 
01413             if (email == NULL) {
01414                 p->fWrite("ERR-NOEMAIL MAKE NICK=%s - Email missing\n", nick);
01415                 return;
01416             }
01417 
01418             if (host == NULL) {
01419                 p->fWrite("ERR-NOEMAIL MAKE NICK=%s - Host address missing\n", nick);
01420                 return;
01421             }
01422 
01423             if (getNickData(nick)) {
01424                 p->fWrite("ERR-NICKINUSE MAKE NICK=%s - Nickname is in use.\n", nick);
01425                 return;
01426             }
01427 
01428             if (*nick == '\0' || strlen(nick) > NICKLEN || *nick == '-'
01429                             || isdigit(*nick)) {
01430                 p->fWrite("ERR-NICKINVALID MAKE NICK=%s - Nickname not valid\n", nick);
01431                 return;
01432             }
01433 
01434             for(ptrChar = nick; *ptrChar; ptrChar++)
01435             {
01436                 if (isalnum(*ptrChar))
01437                     continue;
01438 
01439                 if (*ptrChar == '[' || *ptrChar == ']' ||
01440                     *ptrChar == '{' || *ptrChar == '}' ||
01441                     *ptrChar == '|' || *ptrChar == '_' ||
01442                     *ptrChar == '\\' || *ptrChar == '`' ||
01443                     *ptrChar == '^')
01444                     continue;
01445                 p->fWrite("ERR-NICKINVALID MAKE RNICK=%s - Nickname not valid\n", nick);
01446                 return;             
01447             }
01448 
01449             if (isQlined(nick)) {
01450                 p->fWrite("ERR-NICKQLINE MAKE RNICK=%s - Nickname reserved.\n", nick);
01451                 return;
01452             }
01453 
01454             if (getRegNickData(nick)) {
01455                 p->fWrite("ERR-NICKINUSE MAKE RNICK=%s - Nickname is in use.\n", nick);
01456                 return;
01457             }
01458 
01459 
01460             ptrNick = (RegNickList *)oalloc(sizeof(RegNickList));
01461             ptrNick->regnum.SetNext(top_regnick_idnum);
01462             strcpy(ptrNick->nick, nick);
01463             strcpy(ptrNick->user, "www-temp");
01464             SetDynBuffer(&ptrNick->host, host);
01465             strncpyzt(ptrNick->email, email, EMAILLEN);
01466             ptrNick->timereg = ptrNick->timestamp = CTime;
01467             ptrNick->amasks = 0;
01468             ptrNick->url = NULL;
01469             ptrNick->chans = 0;
01470             ptrNick->flags = (NDBISMASK);
01471             addRegNick(ptrNick);
01472 
01473             pws = lrand48();
01474             snprintf(pwStuff, 16, "%X%X", (u_int)(pws ^ p->cookie), (u_int)(pws ^ startup));
01475             pw_enter_password(pwStuff, ptrNick->password, NickGetEnc(ptrNick));
01476 
01477 //          logDump(nicklog, "%s![*ipc*:%s]@%s: REGISTER", ptrNick->nick, p->user, host);
01478             nicklog->log(NULL, NS_REGISTER, ptrNick->nick, 0, "%s![*ipc*:%s]@%s", ptrNick->nick, p->user, host);
01479             p->fWriteLn("OK MAKE RNICK=%s PASS=%s", nick, pwStuff);
01480             return;
01481         }
01482     }
01483     p->sWrite("ERR-BADTYPE MAKE - Unsupported make type (must be RNICK or RCHAN)\n");
01484 }
01485 
01489 void
01490 IpcType::querySysMessage(IpcConnectType *p, parse_t *pb)
01491 {
01492     char *buf = parse_getarg(pb);
01493 
01494     if (buf != NULL)
01495     {
01496         if (strcmp(buf, "UPTIME") == 0) {
01497             p->fWriteLn("OK QUERY SYSTEM UPTIME=%ld", time(0) - startup);
01498             return;
01499         }
01500     }
01501     p->sWrite("ERR-BADTYPE QUERY SYSTEM - No such object query type (UPTIME) \n");
01502 }
01504 
01508 void
01509 IpcType::queryObjMessage(IpcConnectType *p, parse_t *pb)
01510 {
01511     char *buf = parse_getarg(pb);
01512     int is_ignore = 0, is_ahurt = 0, is_akill = 0;
01513 
01514     if (buf != NULL)
01515     {
01516         if (strcmp(buf, "AKILL") == 0)
01517             is_akill = 1;
01518         else if (strcmp(buf, "AHURT") == 0)
01519             is_ahurt = 1;
01520         else if (strcmp(buf, "IGNORE") == 0)
01521             is_ignore = 1;
01522 
01523         if (strcmp(buf, "RNICK") == 0)
01524         {
01525             char *req;
01526             RegNickList *rnl;
01527 
01528             if ((buf = parse_getarg(pb)) == NULL) {
01529                 p->sWrite("ERR-SYNTAX QUERY OBJECT RNICK - nickname/attribute pair missing.\n");
01530                 return;
01531             }
01532 
01533             req = parse_getarg(pb);
01534 
01535             if ((rnl = getRegNickData(buf)) == NULL) {
01536 
01537                 if (req && strcmp(req, "ISREG"))
01538                     p->fWriteLn("ERR-BADTARGET QUERY OBJECT RNICK=%s - NOT_REGISTERED", buf);
01539                 else
01540                     p->fWriteLn("OK QUERY OBJECT RNICK=%s ISREG=FALSE - Nickname is not registered.", buf);
01541                 return;
01542             }
01543 
01544             if (req == NULL || strcmp(req, "ISREG") == 0) {
01545                 p->fWriteLn("OK QUERY OBJECT RNICK=%s ISREG=TRUE - Nickname is registered.", buf);
01546                 return;
01547             }
01548 
01549             if (strcmp(req, "ISBYPASS") == 0) {
01550                 if (rnl->flags & NBYPASS)
01551                     p->fWriteLn("OK QUERY OBJECT RNICK=%s ISBYPASS=TRUE", buf);
01552                 else
01553                     p->fWriteLn("OK QUERY OBJECT RNICK=%s ISBYPASS=FALSE", buf);
01554             }
01555 
01556 
01557             if (queryRegNickMessage(rnl, req, p, pb))
01558                 return;
01559 
01560             p->fWriteLn("ERR-BADATT QUERY OBJECT RNICK EATTR - Known attributes (ISREG, ISBYPASS)");
01561 
01562             return;
01563         }
01564         else if (is_akill || is_ahurt || is_ignore) {
01565             const char *tar = parse_getarg(pb), *akstr;
01566 
01567             akstr = is_ignore ? "IGNORE" :
01568                     is_ahurt ?  "AHURT"  :
01569                     "AKILL";
01570 
01571             if (!(p->GetPriv() & PRIV_QUERY_AKILL_LIST)) {
01572                 p->fWriteLn("ERR-NOPRIV QUERY OBJECT %s=LIST "
01573                             "- User %s Not authorized to query %s.",
01574                             akstr, p->user, akstr);
01575                 return;
01576             }
01577 
01578             if (tar && strcmp(tar, "LIST") == 0)
01579                 tar = NULL;
01580 
01581 
01582             {
01583                 p->fWriteLn("START QUERY OBJECT %s=LIST",
01584                             akstr);
01585                 p->sendAkills(is_ignore ? A_IGNORE : is_ahurt ? A_AHURT : A_AKILL, tar);
01586                 p->fWriteLn("OK QUERY OBJECT %s=LIST",
01587                             akstr);
01588             }           
01589             return;
01590         }
01591         else if (strcmp(buf, "RCHAN") == 0)
01592         {
01593             if ((buf = parse_getarg(pb)) == NULL) {
01594                 p->sWrite("ERR-BADSYNTAX QUERY OBJECT RCHAN - channel/attribute pair missing.\n");
01595                 return;
01596             }
01597 
01598             return;
01599         }
01600     }
01601     
01602     p->sWrite("ERR-BADTYPE QUERY OBJECT - No such object query type (RCHAN, RNICK, AKILL, AHURT, IGNORE) \n");
01603 }
01604 
01605 
01609 void
01610 IpcType::alterObjMessage(IpcConnectType *p, parse_t *pb)
01611 {
01612     char *buf = parse_getarg(pb);
01613 //  int is_ignore = 0, is_ahurt = 0, is_akill = 0;
01614 
01615     if (buf != NULL)
01616     {
01617 //      if (strcmp(buf, "AKILL") == 0)
01618 //          is_akill = 1;
01619 //      else if (strcmp(buf, "AHURT") == 0)
01620 //          is_ahurt = 1;
01621 //      else if (strcmp(buf, "IGNORE") == 0)
01622 //          is_ignore = 1;
01623 
01624         if (strcmp(buf, "RNICK") == 0)
01625         {
01626             char *req;
01627             RegNickList *rnl;
01628 
01629             if ((buf = parse_getarg(pb)) == NULL) {
01630                 p->sWrite("ERR-SYNTAX QUERY OBJECT RNICK - nickname/attribute pair missing.\n");
01631                 return;
01632             }
01633 
01634             req = parse_getarg(pb);
01635 
01636             if ((rnl = getRegNickData(buf)) == NULL) {
01637                 p->fWriteLn("ERR-BADTARGET ALTER OBJECT RNICK=%s - NOT_REGISTERED", buf);
01638                 return;
01639             }
01640 
01641 //          if (req == NULL || strcmp(req, "DROP") == 0) {
01642 //              p->fWriteLn("OK QUERY OBJECT RNICK=%s ISREG=TRUE - Nickname is registered.", buf);
01643 //              return;
01644 //          }
01645 
01646             if (strcmp(req, "+BYPASS") == 0) {
01647                 if (p->CheckPriv(PRIV_SET_BYPASS, 0)) {
01648                     p->fWriteLn("ERR-NOPRIV ALTER OBJECT RNICK=%s %s"
01649                     "- Not authorized to alter RNICK %s.",
01650                     rnl->nick, req, req);
01651                     return;
01652                 }
01653                 p->fWriteLn("OK ALTER OBJECT RNICK=%s ISBYPASS=TRUE", buf);
01654                 rnl->flags |= NBYPASS;
01655             }
01656 
01657             if (strcmp(req, "-BYPASS") == 0) {
01658                 if (p->CheckPriv(PRIV_UNSET_BYPASS, 0)) {
01659                     p->fWriteLn("ERR-NOPRIV ALTER OBJECT RNICK=%s %s"
01660                     "- Not authorized to alter RNICK %s.",
01661                     rnl->nick, req, req);
01662                     return;
01663                 }
01664                 p->fWriteLn("OK ALTER OBJECT RNICK=%s ISBYPASS=FALSE", buf);
01665                 rnl->flags &= ~NBYPASS;
01666             }
01667 
01668 
01669             if (alterRegNickMessage(rnl, req, p, pb))
01670                 return;
01671 
01672             p->fWriteLn("ERR-BADATT ALTER OBJECT RNICK EATTR - Known attributes (ISREG, ISBYPASS)");
01673 
01674             return;
01675         }
01676         else if (strcmp(buf, "RCHAN") == 0)
01677         {
01678             RegChanList *rcl;
01679 
01680             if ((buf = parse_getarg(pb)) == NULL) {
01681                 p->sWrite("ERR-BADSYNTAX ALTER OBJECT RCHAN - channel/attribute pair missing.\n");
01682                 return;
01683             }
01684 
01685             rcl = getRegChanData(buf);
01686 
01687             if (rcl == NULL) {
01688                 p->sWrite("ERR-NOTARGET ALTER OBJECT RCHAN\n");
01689                 return;
01690             }
01691 
01692             if ((buf = parse_getarg(pb)) == NULL) {
01693                 p->sWrite("ERR-BADSYNTAX ALTER OBJECT RCHAN - channel/attribute pair missing.\n");
01694                 return;
01695             }
01696 
01697             if (strcmp(buf, "PASS") == 0)
01698             {
01699                 if ((buf = parse_getarg(pb)) == NULL) {
01700                     p->sWrite("ERR-BADSYNTAX ALTER OBJECT RCHAN - attribute value missing.\n");
01701                     return;
01702                 }
01703 
01704                 if (p->CheckPriv(0, OPRIV_SETPASS))
01705                 {
01706                     p->fWriteLn("ERR-NOPERM ALTER OBJECT RCHAN=%s PASS - Not authorized.", rcl->name);
01707                     return;
01708                 }
01709     
01710                 if (buf == 0 || *buf == '\0' || str_cmp(buf, rcl->name) == 0)
01711                 {
01712                     p->fWriteLn("ERR-SYNTAX ALTER OBJECT RCHAN=%s PASS - You need to specify a valid password", rcl->name);
01713                     return;
01714                 }
01715 
01716                 pw_enter_password(buf, rcl->password, ChanGetEnc(rcl));
01717                 rcl->flags &= ~CFORCEXFER;
01718                 rcl->chpw_key = 0;
01719                 p->fWriteLn("OK ALTER OBJECT RCHAN=%s PASS %s", rcl->name, buf);
01720                 return;
01721             }
01722 
01723 //
01724             return;
01725         }
01726     }
01727     
01728     p->sWrite("ERR-BADTYPE QUERY OBJECT - No such object alter type (RNICK) \n");
01729 }
01730 
01734 void
01735 IpcConnectType::sWrite(const char *buf)
01736 {
01737     int len, retcode = send(fd, buf, len=strlen(buf), 0);
01738 
01739     if (retcode == -1) {
01740         if (errno != EINTR && errno != EWOULDBLOCK &&
01741             errno != EMSGSIZE) {
01742             if (fd != -1)
01743                 close(fd);
01744             fd = -1;
01745         }
01746         return;
01747     }
01748     else if (retcode > 0 && retcode < len) {
01749         sWrite(buf + retcode);
01750     }
01751 }
01752 
01753 void
01754 IpcConnectType::fWrite(const char *buf, ...)
01755 {
01756     char stuff[IRCBUF];
01757     va_list ap;
01758 
01759     va_start(ap, buf);
01760     vsnprintf(stuff, sizeof(stuff), buf, ap);
01761     va_end(ap);
01762 
01763     sWrite(stuff);
01764 }
01765 
01766 void
01767 IpcConnectType::fWriteLn(const char *buf, ...)
01768 {
01769     char stuff[IRCBUF];
01770     va_list ap;
01771 
01772     va_start(ap, buf);
01773     vsnprintf(stuff, sizeof(stuff), buf, ap);
01774     va_end(ap);
01775 
01776     send(fd, stuff, strlen(stuff), 0);
01777     send(fd, "\n", 1, 0);
01778 }
01779 

Generated at Sat Oct 25 20:56:09 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.