#include "../nick/nick.h"
#include "../parser/parser.h"
#include "../lib/splitline.h"
+#include "../lib/irc_string.h"
#include <string.h>
#include <stdio.h>
destroycommandtree(csctcpcommands);
}
-void chanservaddcommand(char *command, int flags, int maxparams, CommandHandler handler, char *description) {
+void chanservaddcommand(char *command, int flags, int maxparams, CommandHandler handler, char *description, const char *help) {
Command *newcmd;
cmdsummary *summary;
memset((void *)summary,0,sizeof(cmdsummary));
summary->def=getsstring(description, 250);
-
+ summary->defhelp=(char *)help; /* Assume that help is a constant */
+
newcmd->ext=(void *)summary;
loadcommandsummary(newcmd);
}
int notice;
reguser *rup;
int language;
- va_list va;
+ va_list va, va2;
char *message;
char *bp2,*bp;
int len;
}
va_start(va,messageid);
+ va_copy(va2, va);
vsnprintf(buf,5000,message,va);
va_end(va);
*bp2++=*bp;
}
}
+
+ /* Special case: If it's a "not enough parameters" message, show the first line of help */
+ if (messageid==QM_NOTENOUGHPARAMS) {
+ char *command=va_arg(va2, char *);
+ cs_sendhelp(np, command, 1);
+ chanservstdmessage(np, QM_TYPEHELPFORHELP, command);
+ }
+
+ va_end(va2);
}
-void chanservsendmessage(nick *np, char *message, ... ) {
+void chanservsendmessage_real(nick *np, int oneline, char *message, ... ) {
char buf[5010]; /* Very large buffer.. */
char buf2[512], *bp, *bp2;
int notice;
}
/* If we ran out of buffer, get out here */
- if (!*bp)
+ if (!*bp || (*bp=='\n' && oneline))
break;
bp2=buf2;
killuser(chanservnick, target, buf);
}
-int checkmasterpassword(reguser *rup, const char *pass) {
- if (!strncmp(rup->masterpass, pass, PASSLEN))
- return 1;
- return 0;
-}
-
int checkpassword(reguser *rup, const char *pass) {
if (!strncmp(rup->password, pass, PASSLEN))
return 1;
return 0;
}
-int setmasterpassword(reguser *rup, const char *pass) {
- strncpy(rup->masterpass, pass, PASSLEN);
- rup->masterpass[PASSLEN]='\0';
- return 1;
+int checkresponse(reguser *rup, const unsigned char *entropy, const char *response, CRAlgorithm algorithm) {
+ char usernamel[NICKLEN+1], *dp, *up;
+
+ for(up=rup->username,dp=usernamel;*up;)
+ *dp++ = ToLower(*up++);
+ *dp = '\0';
+
+ return algorithm(usernamel, rup->password, cs_calcchallenge(entropy), response);
+}
+
+int checkhashpass(reguser *rup, const char *junk, const char *hash) {
+ char usernamel[NICKLEN+1], *dp, *up;
+
+ for(up=rup->username,dp=usernamel;*up;)
+ *dp++ = ToLower(*up++);
+ *dp = '\0';
+
+ return cs_checkhashpass(usernamel, rup->password, junk, hash);
}
int setpassword(reguser *rup, const char *pass) {
void cs_checknick(nick *np) {
activeuser* aup;
reguser *rup;
- nicklist *nlp;
char userhost[USERLEN+HOSTLEN+3];
if (!(aup=getactiveuserfromnick(np))) {
assert(getactiveuserfromnick(np));
- if (IsAccount(np)) {
- if ((rup=findreguserbynick(np->authname))!=NULL) {
- aup->rup=rup;
- nlp=getnicklist();
- nlp->np=np;
- nlp->next=rup->nicks;
- rup->nicks=nlp;
- triggerhook(HOOK_CHANSERV_SETUSERID, np);
+ if (IsAccount(np) && np->auth) {
+ if (np->auth->exts[chanservaext]) {
+ rup=getreguserfromnick(np);
+ /* safe? */
+ if(rup && UHasSuspension(rup)) {
+ chanservkillstdmessage(np, QM_SUSPENDKILL);
+ return;
+ }
cs_doallautomodes(np);
} else {
- aup->rup=NULL;
/* Auto create user.. */
rup=getreguser();
rup->status=0;
- rup->ID=++lastuserID;
+ rup->ID=np->auth->userid;
+ if (rup->ID > lastuserID)
+ lastuserID=rup->ID;
strncpy(rup->username,np->authname,NICKLEN); rup->username[NICKLEN]='\0';
rup->created=time(NULL);
- rup->lastauth=time(NULL);
+ rup->lastauth=time(NULL); /* questionable */
rup->lastemailchange=0;
rup->flags=QUFLAG_NOTICE;
rup->languageid=0;
rup->suspendby=0;
rup->suspendexp=0;
+ rup->suspendtime=0;
rup->password[0]='\0';
- rup->masterpass[0]='\0';
rup->email=NULL;
rup->localpart=NULL;
rup->domain=NULL;
rup->checkshd=NULL;
rup->stealcount=0;
rup->fakeuser=NULL;
- rup->nicks=getnicklist();
- rup->nicks->np=np;
- rup->nicks->next=NULL;
addregusertohash(rup);
csdb_createuser(rup);
- aup->rup=rup;
}
- } else {
- aup->rup=NULL;
}
cs_checknickbans(np);
int i;
regchanuser *rcup, *nrcup;
regchan *rcp;
+ struct authname *anp;
/* Remove the user from all its channels */
for (rcup=rup->knownon;rcup;rcup=nrcup) {
removereguserfromhash(rup);
- if (rup->nicks) {
+ if ((anp=findauthname(rup->ID)) && anp->nicks) {
rup->status |= QUSTAT_DEAD;
} else {
freereguser(rup);
localkickuser(chanservnick, cip->channel, np, reason?reason:"Banned.");
}
+
+/*
+ * cs_sanitisechanlev: Removes impossible combinations from chanlev flags.
+ * chanservuser.c is probably not the right file for this, but nowhere better
+ * presented itself...
+ */
+flag_t cs_sanitisechanlev(flag_t flags) {
+ /* +m or +n cannot have any "punishment" flags */
+ if (flags & (QCUFLAG_MASTER | QCUFLAG_OWNER))
+ flags &= ~(QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY);
+
+ /* +d can't be +o */
+ if (flags & QCUFLAG_DENY)
+ flags &= ~QCUFLAG_OP;
+
+ /* +q can't be +v */
+ if (flags & QCUFLAG_QUIET)
+ flags &= ~QCUFLAG_VOICE;
+
+ /* +p trumps +a and +g */
+ if (flags & QCUFLAG_PROTECT)
+ flags &= ~(QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE);
+
+ /* -o can't be +a */
+ if (!(flags & QCUFLAG_OP))
+ flags &= ~QCUFLAG_AUTOOP;
+
+ /* +a or -v can't be +g. +a implies +o at this stage (see above) */
+ if (!(flags & QCUFLAG_VOICE) || (flags & QCUFLAG_AUTOOP))
+ flags &= ~QCUFLAG_AUTOVOICE;
+
+ /* +p requires +o or +v */
+ if (!(flags & (QCUFLAG_VOICE | QCUFLAG_OP)))
+ flags &= ~QCUFLAG_PROTECT;
+
+ /* The personal flags require one of +mnovk */
+ if (!(flags & (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_KNOWN)))
+ flags &= ~QCUFLAGS_PERSONAL;
+
+ return flags;
+}
/*
* findreguser:
* This function does the standard "nick or #user" lookup.
* If "sender" is not NULL, a suitable error message will
* be sent if the lookup fails.
+ * "sender" MUST be sent when a user is requesting a lookup
+ * as there is some policy code here.
*/
reguser *findreguser(nick *sender, const char *str) {
- reguser *rup;
+ reguser *rup, *vrup = getreguserfromnick(sender);;
nick *np;
if (!str || !*str)
}
if (!(rup=findreguserbynick(str+1)) && sender)
chanservstdmessage(sender, QM_UNKNOWNUSER, str);
+ } else if (*str=='&' && vrup && UHasHelperPriv(vrup)) {
+ if (str[1]=='\0') {
+ if (sender)
+ chanservstdmessage(sender, QM_UNKNOWNUSER, str);
+ return NULL;
+ }
+ if (!(rup=findreguserbyID(atoi(str+1))) && sender)
+ chanservstdmessage(sender, QM_UNKNOWNUSER, str);
} else {
if (!(np=getnickbynick(str))) {
if (sender)
chanservstdmessage(sender, QM_USERNOTAUTHED, str);
}
- if (rup && (UIsSuspended(rup) || (rup->status & QUSTAT_DEAD))) {
+ /* removed the suspended check from here, I don't see the point... */
+ if (rup && (rup->status & QUSTAT_DEAD)) {
chanservstdmessage(sender, QM_USERHASBADAUTH, rup->username);
return NULL;
}
return rup;
}
+
+/*
+ * Unbans a mask from a channel, including permbans if user has correct privs.
+ */
+void cs_unbanfn(nick *sender, chanindex *cip, UnbanFN fn, void *arg, int removepermbans) {
+ regban **rbh, *rbp;
+ chanban **cbh, *cbp;
+ regchan *rcp;
+ modechanges changes;
+ char *banstr;
+
+ rcp=cip->exts[chanservext];
+
+ if (cip->channel)
+ localsetmodeinit(&changes, cip->channel, chanservnick);
+
+ for (rbh=&(rcp->bans); *rbh; ) {
+ rbp=*rbh;
+ if (fn(arg, rbp->cbp)) {
+ banstr=bantostring(rbp->cbp);
+ /* Check perms and remove */
+ if(!removepermbans) {
+ chanservstdmessage(sender, QM_WARNNOTREMOVEDPERMBAN, banstr, cip->name->content);
+ rbh=&(rbp->next);
+ } else if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, NULL, 0, 1)) {
+ chanservstdmessage(sender, QM_NOTREMOVEDPERMBAN, banstr, cip->name->content);
+ rbh=&(rbp->next);
+ } else {
+ chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
+ if (cip->channel)
+ localdosetmode_ban(&changes, banstr, MCB_DEL);
+ /* Remove from database */
+ csdb_deleteban(rbp);
+ /* Remove from list */
+ (*rbh)=rbp->next;
+ /* Free ban/string and update setby refcount, and free actual regban */
+ freesstring(rbp->reason);
+ freechanban(rbp->cbp);
+ freeregban(rbp);
+ }
+ } else {
+ rbh=&(rbp->next);
+ }
+ }
+
+ if (cip->channel) {
+ for (cbh=&(cip->channel->bans); *cbh; ) {
+ cbp=*cbh;
+ if (fn(arg, cbp)) {
+ /* Remove */
+ banstr=bantostring(cbp);
+ chanservstdmessage(sender, QM_REMOVEDCHANBAN, banstr, cip->name->content);
+ localdosetmode_ban(&changes, banstr, MCB_DEL);
+ } else {
+ cbh=&(cbp->next);
+ }
+ }
+ localsetmodeflush(&changes,1);
+ }
+}