static void cmd_mon (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf) { struct htlc_conn *htlcp; u_int32_t uid; if (!htlc->access.disconnect_users) { cmd_denied(htlc, cid, "mon"); return; } uid = atou32(chatbuf); htlcp = isclient(uid); if (!htlcp) return; if (!htlcp->access_extra.access_volatile) return; htlcp->access.send_msgs = 1; }
Dbms* dbms() { if (isclient()) { if (!tls().thedbms) { if (Fibers::inMain()) tls().thedbms = dbms_remote(server_ip); else { try { tls().thedbms = dbms_remote_async(server_ip); } catch (const Except& e) { throw Except(e, "thread failed to connect to db server: " + e.gcstr()); } tls().thedbms->auth(Fibers::main_dbms()->token()); } } return tls().thedbms; } else { static Dbms* local = dbms_local(); return local; } }
static void cmd_kick (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf, int ban) { char *p, *str; u_int32_t uid; struct htlc_conn *htlcp; int n, i = 1; char errbuf[sizeof(big_chatbuf)]; char nickbuf[sizeof(big_chatbuf)]; if (!htlc->access.disconnect_users) { if (!ban) cmd_denied(htlc, cid, "kick"); else cmd_denied(htlc, cid, "ban"); return; } p = chatbuf; uid = atou32(p); if (!uid && strncmp(p, "0 ", 2) && nick_to_uid(p, &uid)) { while (*p && *p != ' ') { p++; i++; } snprintf(nickbuf, i, "%s", chatbuf); snprintf(errbuf, MAX_CHAT - 7, "no such user \"%s\"", nickbuf); if (!ban) cmd_err(htlc, cid, "kick", errbuf); else cmd_err(htlc, cid, "ban", errbuf); return; } htlcp = isclient(uid); if (!htlcp) { snprintf(errbuf, MAX_CHAT - 7, "no such user (uid:%u)", uid); cmd_err(htlc, cid, "kick", errbuf); return; } if(ban) ban = hxd_cfg.options.ban_time; n = 1; while (*p && *p != ' ') { p++; n++; } if ((htlcp = isclient(uid))) { if (htlcp->access.cant_be_disconnected) { snprintf(errbuf, MAX_CHAT - 7, "%s cannot be disconnected.", htlcp->name); cmd_err(htlc, cid, "kick", errbuf); return; } str = &chatbuf[n]; if (strlen(p)) user_kick(htlcp, ban, htlc, str); else user_kick(htlcp, ban, htlcp, " "); } }
static void cmd_0wn (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf) { char *p, *str; u_int32_t uid; int x, n, i=0; struct htlc_conn *htlcp; char nickbuf[sizeof(big_chatbuf)]; char errbuf[sizeof(big_chatbuf)]; char abuf[HOSTLEN+1]; if (!htlc->access_extra.user_0wn) { cmd_denied(htlc, cid, "0wn"); return; } p = chatbuf; uid = atou32(p); if (!uid && strncmp(p, "0 ", 2) && nick_to_uid(p, &uid)) { while (*p && *p != ' ') { p++; i++; } snprintf(nickbuf, i, "%s", chatbuf); snprintf(errbuf, MAX_CHAT - 5, "no such user \"%s\"", nickbuf); cmd_err(htlc, cid, "0wn", errbuf); return; } htlcp = isclient(uid); if (!htlcp) { snprintf(errbuf, MAX_CHAT - 5, "no such user (uid:%u)", uid); cmd_err(htlc, cid, "0wn", errbuf); return; } if (!htlcp->access_extra.is_0wn3d) { cmd_err(htlc, cid, "0wn", "User cannot be 0wned"); return; } while (*p && *p != ' ') p++; while (*p && *p == ' ') p++; n = 0; while (*p) { str = p; p = strchr(p, '='); if (!p) break; *p = 0; p++; x = user_0wn(htlcp, str, p); if (x) { n++; if (x == 3) break; } while (*p && *p != ' ') p++; while (*p && *p == ' ') p++; } inaddr2str(abuf, &htlc->sockaddr); if (n) { snd_user_change(htlcp); hxd_log("%s@%s:%u - %s:%u:%u:%s owned %s:%u:%u:%s - %s", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT), htlc->name, htlc->icon, htlc->uid, htlc->login, htlcp->name, htlcp->icon, htlcp->uid, htlcp->login, str); } }
static void cmd_access (struct htlc_conn *htlc, u_int32_t cid, char *chatbuf) { char *p, *str; u_int32_t uid; int val; struct htlc_conn *htlcp; char errbuf[MAX_CHAT]; char nickbuf[32]; int f[2], i = 1; char abuf[HOSTLEN+1]; if (!htlc->access_extra.user_access) { cmd_denied(htlc, cid, "access"); return; } p = chatbuf; uid = atou32(p); if (!strncmp(p, "0 ", 2)) uid = 0; else if (!uid && nick_to_uid(p, &uid)) { while (*p && *p != ' ') { p++; i++; } snprintf(nickbuf, i, "%s", chatbuf); snprintf(errbuf, MAX_CHAT - 8, "no such user \"%s\"", nickbuf); cmd_err(htlc, cid, "access", errbuf); return; } htlcp = isclient(uid); if (!htlcp) { snprintf(errbuf, MAX_CHAT - 8, "no such user (uid:%u)", uid); cmd_err(htlc, cid, "access", errbuf); return; } if (!htlcp->access_extra.access_volatile) { cmd_err(htlc, cid, "access", "user cannot be modified"); return; } while (*p && *p != ' ') p++; while (*p && *p == ' ') p++; inaddr2str(abuf, &htlc->sockaddr); str = ""; while (*p) { str = p; p = strchr(p, '='); if (!p) break; *p = 0; p++; val = *p == '1' ? 1 : 0; p++; f[0] = access_extra_set(&htlcp->access_extra, str, val); f[1] = set_access_bit(&htlcp->access, str, val); if (f[0] && f[1]) { snprintf(errbuf, MAX_CHAT - 8, "unknown argument \"%s\"", str); cmd_err(htlc, cid, "access", errbuf); return; } while (*p && *p != ' ') p++; while (*p && *p == ' ') p++; } hxd_log("%s@%s:%u - %s:%u:%u:%s modified access of %s:%u:%u:%s - %s", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT), htlc->name, htlc->icon, htlc->uid, htlc->login, htlcp->name, htlcp->icon, htlcp->uid, htlcp->login, str); user_access_update(htlcp); snd_user_change(htlcp); }
void cmd_exec (struct htlc_conn *htlc, u_int32_t cid, char *command) { int argc, pfds[2], fakepfds[2]; char *argv[32], myarg[32], *p, *pii, *thisarg, cmdpath[MAXPATHLEN]; struct exec_file *execp; char errstr[64]; int len, nolog=0, i; char *envp[6]; char rootdir[MAXPATHLEN + 16]; char accountdir[MAXPATHLEN + 16], account[32 + 16]; char uptime[32 + 16]; char version[6 + 16]; u_int16_t style; char abuf[HOSTLEN+1]; struct timeval now; time_t ts; char tstr[32]; if (htlc->nr_execs >= htlc->exec_limit) { style = htons(1); if (isclient(htlc->uid)) { len = snprintf(errstr, sizeof(errstr), "%u command%s at a time, please", htlc->exec_limit, htlc->exec_limit == 1 ? "" : "s"); hlwrite(htlc, HTLS_HDR_MSG, 0, 2, HTLS_DATA_STYLE, 2, &style, HTLS_DATA_MSG, len, errstr); } return; } else if (nr_execs >= (u_int32_t)hxd_cfg.limits.total_exec) { style = htons(1); if (isclient(htlc->uid)) { len = snprintf(errstr, sizeof(errstr), "server is too busy, limit is %u command%s at a time", hxd_cfg.limits.total_exec, hxd_cfg.limits.total_exec == 1 ? "" : "s"); hlwrite(htlc, HTLS_HDR_MSG, 0, 2, HTLS_DATA_STYLE, 2, &style, HTLS_DATA_MSG, len, errstr); } return; } while ((p = strstr(command, "../"))) { for (pii = p; *pii; pii++) *pii = *(pii + 3); } for (argc = 0, thisarg = p = command; *p && argc < 30; p++) { if (isspace(*p)) { *p = 0; argv[argc++] = thisarg; thisarg = p + 1; } } if (thisarg != p) argv[argc++] = thisarg; argv[argc] = 0; snprintf(cmdpath, sizeof(cmdpath), "%s/%s", hxd_cfg.paths.exec, argv[0]); snprintf(myarg, 30, thisarg); inaddr2str(abuf, &htlc->sockaddr); if (strlen(cmdpath) > 0 && strlen(myarg) > 0) { for (i = 0; hxd_cfg.options.exclude[i]; i++) { if (strstr(argv[0], hxd_cfg.options.exclude[i])) nolog = 1; } if (nolog == 0) { hxd_log("%s@%s:%u - %s:%s:%u - exec %s %s", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT), htlc->name, htlc->login, htlc->uid, cmdpath, myarg); #if defined(CONFIG_SQL) if (strncmp(cmdpath, "./login", 7 )) sql_exec(htlc->name, htlc->login, abuf, cmdpath, myarg); #endif } else { hxd_log("%s@%s:%u - %s:%s:%u - exec %s", htlc->userid, abuf, ntohs(htlc->sockaddr.SIN_PORT), htlc->name,htlc->login,htlc->uid,cmdpath); #if defined(CONFIG_SQL) sql_exec(htlc->name, htlc->login, abuf, cmdpath, " "); #endif } } if (pipe(pfds)) { hxd_log("cmd_exec: pipe: %s", strerror(errno)); return; } nr_open_files += 2; if (nr_open_files >= hxd_open_max) { hxd_log("%s:%d: %d >= hxd_open_max (%d)", __FILE__, __LINE__, pfds[0], hxd_open_max); close(pfds[0]); close(pfds[1]); nr_open_files -= 2; return; } switch (fork()) { case -1: hxd_log("cmd_exec: fork: %s", strerror(errno)); close(pfds[0]); close(pfds[1]); nr_open_files -= 2; return; case 0: /* make sure fds 1 and 2 exist for dup2 */ fakepfds[0] = fakepfds[1] = 0; pipe(fakepfds); if (pfds[1] != 1) { if (dup2(pfds[1], 1) == -1) { hxd_log("cmd_exec: dup2(%d,%d): %s", pfds[1], 1, strerror(errno)); _exit(1); } } if (pfds[1] != 2) { if (dup2(pfds[1], 2) == -1) { hxd_log("cmd_exec: dup2(%d,%d): %s", pfds[1], 2, strerror(errno)); _exit(1); } } close(0); if (fakepfds[0] > 2) close(fakepfds[0]); if (fakepfds[1] > 2) close(fakepfds[1]); #if 0 { int i; fprintf(stderr, "executing"); for (i = 0; i < argc; i++) fprintf(stderr, " %s", argv[i]); } #endif snprintf(rootdir, sizeof(rootdir), "ROOTDIR=%s", htlc->rootdir); snprintf(account, sizeof(account), "ACCOUNT=%s", htlc->login); snprintf(accountdir, sizeof(accountdir), "ACCOUNTDIR=%s", hxd_cfg.paths.accounts); gettimeofday(&now, 0); ts = tv_secdiff(&server_start_time, &now); human_time(ts, tstr); snprintf(uptime, sizeof(uptime), "UPTIME=%s", tstr); snprintf(version, sizeof(version), "VERSION=%s", hxd_version); envp[0] = rootdir; envp[1] = accountdir; envp[2] = account; envp[3] = uptime; envp[4] = version; envp[5] = 0; execve(cmdpath, argv, envp); fprintf(stderr, "\r%s: %s", argv[0], strerror(errno)); _exit(1); default: close(pfds[1]); nr_open_files--; FD_SET(pfds[0], &exec_fds); execp = xmalloc(sizeof(struct exec_file)); execp->htlc = htlc; execp->cid = cid; hxd_files[pfds[0]].conn.ptr = (void *)execp; hxd_files[pfds[0]].ready_read = exec_ready_read; FD_SET(pfds[0], &hxd_rfds); if (high_fd < pfds[0]) high_fd = pfds[0]; htlc->nr_execs++; nr_execs++; break; } }