// // // XOVER is used by some clients, even if we don't offer it // void nntp_xover(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; citnntp *nntpstate = (citnntp *) CC->session_specific_data; char range[256]; struct listgroup_range lr; extract_token(range, cmd, 1, ' ', sizeof range); lr.lo = atol(range); if (lr.lo <= 0) { lr.lo = nntpstate->current_article_number; lr.hi = nntpstate->current_article_number; } else { char *dash = strchr(range, '-'); if (dash != NULL) { ++dash; lr.hi = atol(dash); if (lr.hi == 0) { lr.hi = LONG_MAX; } if (lr.hi < lr.lo) { lr.hi = lr.lo; } } else { lr.hi = lr.lo; } } cprintf("224 Overview information follows\r\n"); CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, nntp_xover_backend, &lr); cprintf(".\r\n"); }
/* * Request client termination */ void cmd_reqt(char *argbuf) { struct CitContext *ccptr; int sessions = 0; int which_session; struct ExpressMessage *newmsg; if (CtdlAccessCheck(ac_aide)) return; which_session = extract_int(argbuf, 0); begin_critical_section(S_SESSION_TABLE); for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { if ((ccptr->cs_pid == which_session) || (which_session == 0)) { newmsg = (struct ExpressMessage *) malloc(sizeof (struct ExpressMessage)); memset(newmsg, 0, sizeof (struct ExpressMessage)); time(&(newmsg->timestamp)); safestrncpy(newmsg->sender, CC->user.fullname, sizeof newmsg->sender); newmsg->flags |= EM_GO_AWAY; newmsg->text = strdup("Automatic logoff requested."); add_xmsg_to_context(ccptr, newmsg); ++sessions; } } end_critical_section(S_SESSION_TABLE); cprintf("%d Sent termination request to %d sessions.\n", CIT_OK, sessions); }
/* * List ALL OpenIDs in the database */ void cmd_oida(char *argbuf) { struct cdbdata *cdboi; long usernum; struct ctdluser usbuf; if (CtdlGetConfigInt("c_disable_newu")) { cprintf("%d this system does not support openid.\n", ERROR + CMD_NOT_SUPPORTED); return; } if (CtdlAccessCheck(ac_aide)) return; cdb_rewind(CDB_OPENID); cprintf("%d List of all OpenIDs in the database:\n", LISTING_FOLLOWS); while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) { if (cdboi->len > sizeof(long)) { memcpy(&usernum, cdboi->ptr, sizeof(long)); if (CtdlGetUserByNumber(&usbuf, usernum) != 0) { usbuf.fullname[0] = 0; } cprintf("%s|%ld|%s\n", cdboi->ptr + sizeof(long), usernum, usbuf.fullname ); } cdb_free(cdboi); } cprintf("000\n"); }
void cmd_smtp(char *argbuf) { char cmd[64]; char node[256]; char buf[1024]; int i; int num_mxhosts; if (CtdlAccessCheck(ac_aide)) return; extract_token(cmd, argbuf, 0, '|', sizeof cmd); if (!strcasecmp(cmd, "mx")) { extract_token(node, argbuf, 1, '|', sizeof node); num_mxhosts = getmx(buf, node); cprintf("%d %d MX hosts listed for %s\n", LISTING_FOLLOWS, num_mxhosts, node); for (i=0; i<num_mxhosts; ++i) { extract_token(node, buf, i, '|', sizeof node); cprintf("%s\n", node); } cprintf("000\n"); return; } else if (!strcasecmp(cmd, "runqueue")) { run_queue_now = 1; cprintf("%d All outbound SMTP will be retried now.\n", CIT_OK); return; } else { cprintf("%d Invalid command.\n", ERROR + ILLEGAL_VALUE); } }
/* * Administrative Get User Parameters */ void cmd_agup(char *cmdbuf) { struct ctdluser usbuf; char requested_user[128]; if (CtdlAccessCheck(ac_aide)) { return; } extract_token(requested_user, cmdbuf, 0, '|', sizeof requested_user); if (CtdlGetUser(&usbuf, requested_user) != 0) { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); return; } cprintf("%d %s|%s|%u|%ld|%ld|%d|%ld|%ld|%d\n", CIT_OK, usbuf.fullname, usbuf.password, usbuf.flags, usbuf.timescalled, usbuf.posted, (int) usbuf.axlevel, usbuf.usernum, (long)usbuf.lastcall, usbuf.USuserpurge); }
/* * Participate in real time chat in a room */ void cmd_rcht(char *argbuf) { char subcmd[16]; if (CtdlAccessCheck(ac_logged_in)) return; extract_token(subcmd, argbuf, 0, '|', sizeof subcmd); if (!strcasecmp(subcmd, "enter")) { CC->cs_flags |= CS_CHAT; cprintf("%d Entering chat mode.\n", CIT_OK); } else if (!strcasecmp(subcmd, "exit")) { CC->cs_flags &= ~CS_CHAT; cprintf("%d Exiting chat mode.\n", CIT_OK); } else if (!strcasecmp(subcmd, "send")) { roomchat_send(argbuf); } else if (!strcasecmp(subcmd, "poll")) { roomchat_poll(argbuf); } else if (!strcasecmp(subcmd, "rwho")) { roomchat_rwho(argbuf); } else { cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED); } }
/* * set password - citadel protocol implementation */ void cmd_setp(char *new_pw) { if (CtdlAccessCheck(ac_logged_in)) { return; } if ( (CC->user.uid != CTDLUID) && (CC->user.uid != (-1)) ) { cprintf("%d Not allowed. Use the 'passwd' command.\n", ERROR + NOT_HERE); return; } if (CC->is_master) { cprintf("%d The master prefix password cannot be changed with this command.\n", ERROR + NOT_HERE); return; } if (!strcasecmp(new_pw, "GENERATE_RANDOM_PASSWORD")) { char random_password[17]; snprintf(random_password, sizeof random_password, "%08lx%08lx", random(), random()); CtdlSetPassword(random_password); cprintf("%d %s\n", CIT_OK, random_password); } else { strproc(new_pw); if (IsEmptyStr(new_pw)) { cprintf("%d Password unchanged.\n", CIT_OK); return; } CtdlSetPassword(new_pw); cprintf("%d Password changed.\n", CIT_OK); } }
void cmd_log_set(char *argbuf) { void *vptr; int lset; int wlen; char which[SIZ] = ""; if (CtdlAccessCheck(ac_aide)) return; wlen = extract_token(which, argbuf, 0, '|', sizeof(which)); if (wlen < 0) wlen = 0; lset = extract_int(argbuf, 1); if (lset != 0) lset = 1; if (GetHash(LogDebugEntryTable, which, wlen, &vptr) && (vptr != NULL)) { LogDebugEntry *E = (LogDebugEntry*)vptr; E->F(lset); cprintf("%d %s|%d\n", CIT_OK, which, lset); } else { cprintf("%d Log setting %s not known\n", ERROR, which); } }
/* * Rename a user */ void cmd_renu(char *cmdbuf) { int retcode; char oldname[USERNAME_SIZE]; char newname[USERNAME_SIZE]; if (CtdlAccessCheck(ac_aide)) { return; } extract_token(oldname, cmdbuf, 0, '|', sizeof oldname); extract_token(newname, cmdbuf, 1, '|', sizeof newname); retcode = rename_user(oldname, newname); switch(retcode) { case RENAMEUSER_OK: cprintf("%d '%s' has been renamed to '%s'.\n", CIT_OK, oldname, newname); return; case RENAMEUSER_LOGGED_IN: cprintf("%d '%s' is currently logged in and cannot be renamed.\n", ERROR + ALREADY_LOGGED_IN , oldname); return; case RENAMEUSER_NOT_FOUND: cprintf("%d '%s' does not exist.\n", ERROR + NO_SUCH_USER, oldname); return; case RENAMEUSER_ALREADY_EXISTS: cprintf("%d A user named '%s' already exists.\n", ERROR + ALREADY_EXISTS, newname); return; } cprintf("%d An unknown error occurred.\n", ERROR); }
/* * Schedule or cancel a server shutdown */ void cmd_scdn(char *argbuf) { int new_state; int state = CIT_OK; char *Reply = "%d %d\n"; if (CtdlAccessCheck(ac_aide)) return; new_state = extract_int(argbuf, 0); if ((new_state == 2) || (new_state == 3)) { restart_server = 1; if (!running_as_daemon) { syslog(LOG_ERR, "The user requested restart, but not running as deamon! Geronimooooooo!\n"); Reply = "%d %d Warning, not running in deamon mode. maybe we will come up again, but don't lean on it.\n"; state = ERROR; } restart_server = extract_int(argbuf, 0); new_state -= 2; } if ((new_state == 0) || (new_state == 1)) { ScheduledShutdown = new_state; } cprintf(Reply, state, ScheduledShutdown); }
/* * List the OpenIDs associated with the currently logged in account */ void cmd_oidl(char *argbuf) { struct cdbdata *cdboi; long usernum = 0L; if (CtdlGetConfigInt("c_disable_newu")) { cprintf("%d this system does not support openid.\n", ERROR + CMD_NOT_SUPPORTED); return; } if (CtdlAccessCheck(ac_logged_in)) return; cdb_rewind(CDB_OPENID); cprintf("%d Associated OpenIDs:\n", LISTING_FOLLOWS); while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) { if (cdboi->len > sizeof(long)) { memcpy(&usernum, cdboi->ptr, sizeof(long)); if (usernum == CC->user.usernum) { cprintf("%s\n", cdboi->ptr + sizeof(long)); } } cdb_free(cdboi); } cprintf("000\n"); }
/* * validate a user */ void cmd_vali(char *v_args) { char user[128]; int newax; struct ctdluser userbuf; extract_token(user, v_args, 0, '|', sizeof user); newax = extract_int(v_args, 1); if (CtdlAccessCheck(ac_aide) || (newax > AxAideU) || (newax < AxDeleted)) { return; } if (CtdlGetUserLock(&userbuf, user) != 0) { cprintf("%d '%s' not found.\n", ERROR + NO_SUCH_USER, user); return; } userbuf.axlevel = newax; userbuf.flags = (userbuf.flags & ~US_NEEDVALID); CtdlPutUserLock(&userbuf); /* If the access level was set to zero, delete the user */ if (newax == 0) { if (purge_user(user) == 0) { cprintf("%d %s Deleted.\n", CIT_OK, userbuf.fullname); return; } } cprintf("%d User '%s' validated.\n", CIT_OK, userbuf.fullname); }
/* * assorted info we need to check at login */ void cmd_chek(char *argbuf) { int mail = 0; int regis = 0; int vali = 0; if (CtdlAccessCheck(ac_logged_in)) { return; } CtdlGetUser(&CC->user, CC->curr_user); /* no lock is needed here */ if ((REGISCALL != 0) && ((CC->user.flags & US_REGIS) == 0)) regis = 1; if (CC->user.axlevel >= AxAideU) { if (CtdlGetConfigInt("MMflags") & MM_VALID) { vali = 1; } } /* check for mail */ mail = InitialMailCheck(); cprintf("%d %d|%d|%d|%s|\n", CIT_OK, mail, regis, vali, CC->cs_inet_email); }
/* * Shut down the server */ void cmd_down(char *argbuf) { char *Reply ="%d Shutting down server. Goodbye.\n"; if (CtdlAccessCheck(ac_aide)) return; if (!IsEmptyStr(argbuf)) { int state = CIT_OK; restart_server = extract_int(argbuf, 0); if (restart_server > 0) { Reply = "%d citserver will now shut down and automatically restart.\n"; } if ((restart_server > 0) && !running_as_daemon) { syslog(LOG_ERR, "The user requested restart, but not running as daemon! Geronimooooooo!\n"); Reply = "%d Warning: citserver is not running in daemon mode and is therefore unlikely to restart automatically.\n"; state = ERROR; } cprintf(Reply, state); } else { cprintf(Reply, CIT_OK + SERVER_SHUTTING_DOWN); } CC->kill_me = KILLME_SERVER_SHUTTING_DOWN; server_shutting_down = 1; }
/* * This search command is for diagnostic purposes and may be removed or replaced. */ void cmd_srch(char *argbuf) { int num_msgs = 0; long *msgs = NULL; int i; char search_string[256]; if (CtdlAccessCheck(ac_logged_in)) return; if (!CtdlGetConfigInt("c_enable_fulltext")) { cprintf("%d Full text index is not enabled on this server.\n", ERROR + CMD_NOT_SUPPORTED); return; } extract_token(search_string, argbuf, 0, '|', sizeof search_string); ft_search(&num_msgs, &msgs, search_string); cprintf("%d %d msgs match all search words:\n", LISTING_FOLLOWS, num_msgs); if (num_msgs > 0) { for (i=0; i<num_msgs; ++i) { cprintf("%ld\n", msgs[i]); } } if (msgs != NULL) free(msgs); cprintf("000\n"); }
/* * set last read pointer */ void cmd_slrp(char *new_ptr) { long newlr; visit vbuf; visit original_vbuf; if (CtdlAccessCheck(ac_logged_in)) { return; } if (!strncasecmp(new_ptr, "highest", 7)) { newlr = CC->room.QRhighest; } else { newlr = atol(new_ptr); } CtdlLockGetCurrentUser(); CtdlGetRelationship(&vbuf, &CC->user, &CC->room); memcpy(&original_vbuf, &vbuf, sizeof(visit)); vbuf.v_lastseen = newlr; snprintf(vbuf.v_seen, sizeof vbuf.v_seen, "*:%ld", newlr); /* Only rewrite the record if it changed */ if ( (vbuf.v_lastseen != original_vbuf.v_lastseen) || (strcmp(vbuf.v_seen, original_vbuf.v_seen)) ) { CtdlSetRelationship(&vbuf, &CC->user, &CC->room); } CtdlPutCurrentUserLock(); cprintf("%d %ld\n", CIT_OK, newlr); }
/* * get room parameters (admin or room admin command) */ void cmd_getr(char *cmdbuf) { if (CtdlAccessCheck(ac_room_aide)) return; CtdlGetRoom(&CC->room, CC->room.QRname); cprintf("%d%c%s|%s|%s|%d|%d|%d|%d|%d|\n", CIT_OK, CtdlCheckExpress(), ((CC->room.QRflags & QR_MAILBOX) ? &CC->room.QRname[11] : CC->room.QRname), ((CC->room.QRflags & QR_PASSWORDED) ? CC->room.QRpasswd : ""), ((CC->room.QRflags & QR_DIRECTORY) ? CC->room.QRdirname : ""), CC->room.QRflags, (int) CC->room.QRfloor, (int) CC->room.QRorder, CC->room.QRdefaultview, CC->room.QRflags2 ); }
/* * edit a floor */ void cmd_eflr(char *argbuf) { struct floor flbuf; int floor_num; int np; np = num_parms(argbuf); if (np < 1) { cprintf("%d Usage error.\n", ERROR + ILLEGAL_VALUE); return; } if (CtdlAccessCheck(ac_aide)) return; floor_num = extract_int(argbuf, 0); lgetfloor(&flbuf, floor_num); if ((flbuf.f_flags & F_INUSE) == 0) { lputfloor(&flbuf, floor_num); cprintf("%d Floor %d is not in use.\n", ERROR + INVALID_FLOOR_OPERATION, floor_num); return; } if (np >= 2) extract_token(flbuf.f_name, argbuf, 1, '|', sizeof flbuf.f_name); lputfloor(&flbuf, floor_num); cprintf("%d Ok\n", CIT_OK); }
/* * Administrative Set User Parameters */ void cmd_asup(char *cmdbuf) { struct ctdluser usbuf; char requested_user[128]; char notify[SIZ]; int np; int newax; int deleted = 0; if (CtdlAccessCheck(ac_aide)) return; extract_token(requested_user, cmdbuf, 0, '|', sizeof requested_user); if (CtdlGetUserLock(&usbuf, requested_user) != 0) { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); return; } np = num_parms(cmdbuf); if (np > 1) extract_token(usbuf.password, cmdbuf, 1, '|', sizeof usbuf.password); if (np > 2) usbuf.flags = extract_int(cmdbuf, 2); if (np > 3) usbuf.timescalled = extract_int(cmdbuf, 3); if (np > 4) usbuf.posted = extract_int(cmdbuf, 4); if (np > 5) { newax = extract_int(cmdbuf, 5); if ((newax >= AxDeleted) && (newax <= AxAideU)) { usbuf.axlevel = newax; } } if (np > 7) { usbuf.lastcall = extract_long(cmdbuf, 7); } if (np > 8) { usbuf.USuserpurge = extract_int(cmdbuf, 8); } CtdlPutUserLock(&usbuf); if (usbuf.axlevel == AxDeleted) { if (purge_user(requested_user) == 0) { deleted = 1; } } if (deleted) { snprintf(notify, SIZ, "User \"%s\" has been deleted by %s.\n", usbuf.fullname, (CC->logged_in ? CC->user.fullname : "an administrator") ); CtdlAideMessage(notify, "User Deletion Message"); } cprintf("%d Ok", CIT_OK); if (deleted) cprintf(" (%s deleted)", requested_user); cprintf("\n"); }
/* * get user parameters */ void cmd_getu(char *cmdbuf) { if (CtdlAccessCheck(ac_logged_in)) return; CtdlGetUser(&CC->user, CC->curr_user); cprintf("%d 80|24|%d|\n", CIT_OK, (CC->user.flags & US_USER_SET)); }
/* * Halt the server without exiting the server process. */ void cmd_halt(char *argbuf) { if (CtdlAccessCheck(ac_aide)) return; cprintf("%d Halting server. Goodbye.\n", CIT_OK); server_shutting_down = 1; shutdown_and_halt = 1; }
/* * create a new floor */ void cmd_cflr(char *argbuf) { char new_floor_name[256]; struct floor flbuf; int cflr_ok; int free_slot = (-1); int a; extract_token(new_floor_name, argbuf, 0, '|', sizeof new_floor_name); cflr_ok = extract_int(argbuf, 1); if (CtdlAccessCheck(ac_aide)) return; if (IsEmptyStr(new_floor_name)) { cprintf("%d Blank floor name not allowed.\n", ERROR + ILLEGAL_VALUE); return; } for (a = 0; a < MAXFLOORS; ++a) { CtdlGetFloor(&flbuf, a); /* note any free slots while we're scanning... */ if (((flbuf.f_flags & F_INUSE) == 0) && (free_slot < 0)) free_slot = a; /* check to see if it already exists */ if ((!strcasecmp(flbuf.f_name, new_floor_name)) && (flbuf.f_flags & F_INUSE)) { cprintf("%d Floor '%s' already exists.\n", ERROR + ALREADY_EXISTS, flbuf.f_name); return; } } if (free_slot < 0) { cprintf("%d There is no space available for a new floor.\n", ERROR + INVALID_FLOOR_OPERATION); return; } if (cflr_ok == 0) { cprintf("%d ok to create...\n", CIT_OK); return; } lgetfloor(&flbuf, free_slot); flbuf.f_flags = F_INUSE; flbuf.f_ref_count = 0; safestrncpy(flbuf.f_name, new_floor_name, sizeof flbuf.f_name); lputfloor(&flbuf, free_slot); cprintf("%d %d\n", CIT_OK, free_slot); }
/* * get the name of the room admin for this room */ void cmd_geta(char *cmdbuf) { struct ctdluser usbuf; if (CtdlAccessCheck(ac_logged_in)) return; if (CtdlGetUserByNumber(&usbuf, CC->room.QRroomaide) == 0) { cprintf("%d %s\n", CIT_OK, usbuf.fullname); } else { cprintf("%d \n", CIT_OK); } }
// // Implements the LIST commands // void nntp_list(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; char list_format[64]; char wildmat_pattern[1024]; struct nntp_list_data nld; extract_token(list_format, cmd, 1, ' ', sizeof list_format); extract_token(wildmat_pattern, cmd, 2, ' ', sizeof wildmat_pattern); if (strlen(wildmat_pattern) > 0) { nld.wildmat_pattern = wildmat_pattern; } else { nld.wildmat_pattern = NULL; } if ( (strlen(cmd) < 6) || (!strcasecmp(list_format, "ACTIVE")) ) { nld.list_format = NNTP_LIST_ACTIVE; } else if (!strcasecmp(list_format, "NEWSGROUPS")) { nld.list_format = NNTP_LIST_NEWSGROUPS; } else if (!strcasecmp(list_format, "OVERVIEW.FMT")) { nld.list_format = NNTP_LIST_OVERVIEW_FMT; } else { cprintf("501 syntax error , unsupported list format\r\n"); return; } // OVERVIEW.FMT delivers a completely different type of data than all of the // other LIST commands. It's a stupid place to put it. But that's how it's // written into RFC3977, so we have to handle it here. if (nld.list_format == NNTP_LIST_OVERVIEW_FMT) { cprintf("215 Order of fields in overview database.\r\n"); cprintf("Subject:\r\n"); cprintf("From:\r\n"); cprintf("Date:\r\n"); cprintf("Message-ID:\r\n"); cprintf("References:\r\n"); cprintf("Bytes:\r\n"); cprintf("Lines:\r\n"); cprintf(".\r\n"); return; } cprintf("215 list of newsgroups follows\r\n"); CtdlGetUser(&CC->user, CC->curr_user); CtdlForEachRoom(nntp_list_backend, &nld); cprintf(".\r\n"); }
/* * Enter or exit paging-disabled mode */ void cmd_dexp(char *argbuf) { int new_state; if (CtdlAccessCheck(ac_logged_in)) return; new_state = extract_int(argbuf, 0); if ((new_state == 0) || (new_state == 1)) { CC->disable_exp = new_state; } cprintf("%d %d\n", CIT_OK, CC->disable_exp); }
/* * Citadel protocol command to do the same */ void cmd_isme(char *argbuf) { char addr[256]; if (CtdlAccessCheck(ac_logged_in)) return; extract_token(addr, argbuf, 0, '|', sizeof addr); if (CtdlIsMe(addr, sizeof addr)) { cprintf("%d %s\n", CIT_OK, addr); } else { cprintf("%d Not you.\n", ERROR + ILLEGAL_VALUE); } }
void cmd_gtsn(char *argbuf) { visit vbuf; if (CtdlAccessCheck(ac_logged_in)) { return; } /* Learn about the user and room in question */ CtdlGetRelationship(&vbuf, &CC->user, &CC->room); cprintf("%d ", CIT_OK); client_write(vbuf.v_seen, strlen(vbuf.v_seen)); client_write(HKEY("\n")); }
/* * forget (Zap) the current room */ void cmd_forg(char *argbuf) { if (CtdlAccessCheck(ac_logged_in)) { return; } if (CtdlForgetThisRoom() == 0) { cprintf("%d Ok\n", CIT_OK); } else { cprintf("%d You may not forget this room.\n", ERROR + NOT_HERE); } }
void cmd_lrms(char *argbuf) { int FloorBeingSearched = (-1); if (!IsEmptyStr(argbuf)) FloorBeingSearched = extract_int(argbuf, 0); if (CtdlAccessCheck(ac_logged_in_or_guest)) return; CtdlGetUser(&CC->user, CC->curr_user); cprintf("%d Accessible rooms:\n", LISTING_FOLLOWS); CtdlForEachRoom(cmd_lrms_backend, &FloorBeingSearched); cprintf("000\n"); }
/* * set user parameters */ void cmd_setu(char *new_parms) { if (CtdlAccessCheck(ac_logged_in)) return; if (num_parms(new_parms) < 3) { cprintf("%d Usage error.\n", ERROR + ILLEGAL_VALUE); return; } CtdlLockGetCurrentUser(); CC->user.flags = CC->user.flags & (~US_USER_SET); CC->user.flags = CC->user.flags | (extract_int(new_parms, 2) & US_USER_SET); CtdlPutCurrentUserLock(); cprintf("%d Ok\n", CIT_OK); }