static void iauth_loc_xquery(struct server *source, const char routing[], const char query[]) { if (!strncmp(query, "LOGIN2 ", strlen("LOGIN2 "))) { /* Make "user" static for better valgrind tests. */ static struct userNode user; const char *ip_str, *hostname, *username, *account, *password; struct handle_info *hi = NULL; char *qdup, *saveptr = NULL; unsigned int ii; int valid = 0; /* Parse the arguments. */ qdup = strdup(query + strlen("LOGIN2 ")); ip_str = strtok_r(qdup, " ", &saveptr); hostname = strtok_r(NULL, " ", &saveptr); username = strtok_r(NULL, " ", &saveptr); account = strtok_r(NULL, " ", &saveptr); password = strtok_r(NULL, " ", &saveptr); if (!password) { login2_bad_syntax: irc_xresponse(source, routing, "NO Bad LOGIN2 syntax"); free(qdup); return; } if (account[0] == ':') account++; /* Set up (the rest of) the fake user. */ user.nick = "?"; if (!irc_pton(&user.ip, NULL, ip_str)) goto login2_bad_syntax; strncpy(user.ident, username, sizeof(user.ident)); strncpy(user.hostname, hostname, sizeof(user.hostname)); /* Check against the account. */ hi = get_handle_info(account); if (hi && (hi->masks->used == 0)) valid = 1; for (ii = 0; hi && (ii < hi->masks->used); ++ii) { if (user_matches_glob(&user, hi->masks->list[ii], 0)) valid = 1; } if (hi && !checkpass(password, hi->passwd)) valid = 0; /* Send our response. */ free(qdup); if (valid) { char response[68]; snprintf(response, sizeof(response), "OK %s:%lu", hi->handle, hi->registered); irc_xresponse(source, routing, response); } else { irc_xresponse(source, routing, "AGAIN Bad username, account or source"); } } /* else unknown or unsupported command */ }
static void qserver_accept(UNUSED_ARG(struct io_fd *listener), struct io_fd *fd) { struct qserverClient *client; struct sockaddr_storage ss; socklen_t sa_len; unsigned int ii; unsigned int jj; int res; char nick[NICKLEN+1]; char host[HOSTLEN+1]; char ip[HOSTLEN+1]; client = calloc(1, sizeof(*client)); fd->data = client; fd->line_reads = 1; fd->readable_cb = qserver_readable; fd->destroy_cb = qserver_destroy_fd; for (ii = 0; ii < qserver_nbots; ++ii) if (qserver_clients[ii] == NULL) break; if (ii == qserver_nbots) { qserver_nbots += 8; qserver_clients = realloc(qserver_clients, qserver_nbots * sizeof(qserver_clients[0])); for (jj = ii; jj < qserver_nbots; ++jj) qserver_clients[jj] = NULL; } client->id = ii; client->fd = fd; qserver_clients[client->id] = client; snprintf(nick, sizeof(nick), " QServ%04d", client->id); safestrncpy(host, "srvx.dummy.user", sizeof(host)); safestrncpy(ip, "0.0.0.0", sizeof(ip)); sa_len = sizeof(ss); res = getpeername(fd->fd, (struct sockaddr*)&ss, &sa_len); if (res == 0) { getnameinfo((struct sockaddr*)&ss, sa_len, ip, sizeof(host), NULL, 0, NI_NUMERICHOST); if (getnameinfo((struct sockaddr*)&ss, sa_len, host, sizeof(host), NULL, 0, 0) != 0) safestrncpy(host, ip, sizeof(host)); } client->user = AddLocalUser(nick, nick+1, host, "qserver dummy user", "*+oi"); irc_pton(&client->user->ip, NULL, ip); dict_insert(qserver_dict, client->user->nick, client); reg_privmsg_func(client->user, qserver_privmsg); reg_notice_func(client->user, qserver_notice); }
char * generate_hostmask(struct userNode *user, int options) { irc_in_addr_t ip; char *nickname, *ident, *hostname, *mask; int len, ii; /* figure out string parts */ if (options & GENMASK_OMITNICK) nickname = NULL; else if (options & GENMASK_USENICK) nickname = user->nick; else nickname = "*"; if (options & GENMASK_STRICT_IDENT) // sethost - reed/apples if (IsSetHost(user)) { ident = alloca(strcspn(user->sethost, "@")+2); safestrncpy(ident, user->sethost, strcspn(user->sethost, "@")+1); } else ident = user->ident; else if (options & GENMASK_ANY_IDENT) ident = "*"; else { // sethost - reed/apples if (IsSetHost(user)) { ident = alloca(strcspn(user->sethost, "@")+3); ident[0] = '*'; safestrncpy(ident+1, user->sethost, strcspn(user->sethost, "@")+1); } else { ident = alloca(strlen(user->ident)+2); ident[0] = '*'; strcpy(ident+1, user->ident + ((*user->ident == '~')?1:0)); } } hostname = user->hostname; if (IsFakeHost(user) && IsHiddenHost(user) && !(options & GENMASK_NO_HIDING)) { hostname = user->fakehost; } else if (IsHiddenHost(user)) { int style = 1; char *data; data = conf_get_data("server/hidden_host_type", RECDB_QSTRING); if (data) style = atoi(data); if (((style == 1) || (style == 3)) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) { hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2); sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix); } else if (((style == 2) || (style == 3)) && !(options & GENMASK_NO_HIDING)) { hostname = alloca(strlen(user->crypthost)); sprintf(hostname, "%s", user->crypthost); } } else if (options & GENMASK_STRICT_HOST) { if (options & GENMASK_BYIP) hostname = (char*)irc_ntoa(&user->ip); } else if ((options & GENMASK_BYIP) || irc_pton(&ip, NULL, hostname)) { /* Should generate an IP-based hostmask. */ hostname = alloca(IRC_NTOP_MAX_SIZE); hostname[IRC_NTOP_MAX_SIZE-1] = '\0'; if (irc_in_addr_is_ipv4(user->ip)) { /* By popular acclaim, a /16 hostmask is used. */ sprintf(hostname, "%d.%d.*", user->ip.in6_8[12], user->ip.in6_8[13]); } else if (irc_in_addr_is_ipv6(user->ip)) { /* Who knows what the default mask should be? Use a /48 to start with. */ sprintf(hostname, "%x:%x:%x:*", user->ip.in6[0], user->ip.in6[1], user->ip.in6[2]); } else { /* Unknown type; just copy IP directly. */ irc_ntop(hostname, IRC_NTOP_MAX_SIZE, &user->ip); } } else { int cnt; /* This heuristic could be made smarter. Is it worth the effort? */ for (ii=cnt=0; hostname[ii]; ii++) if (hostname[ii] == '.') cnt++; if (cnt == 0 || cnt == 1) { /* only a one- or two-level domain name; leave hostname */ } else if (cnt == 2) { for (ii=0; user->hostname[ii] != '.'; ii++) ; /* Add 3 to account for the *. and \0. */ hostname = alloca(strlen(user->hostname+ii)+3); sprintf(hostname, "*.%s", user->hostname+ii+1); } else { for (cnt=3, ii--; cnt; ii--) if (user->hostname[ii] == '.') cnt--; /* The loop above will overshoot the dot one character; we skip forward two (the one character and the dot) when printing, so we only add one for the \0. */ hostname = alloca(strlen(user->hostname+ii)+1); sprintf(hostname, "*.%s", user->hostname+ii+2); } } // sethost - reed/apples if (IsSetHost(user)) hostname = strchr(user->sethost, '@') + 1; /* Emit hostmask */ len = strlen(ident) + strlen(hostname) + 2; if (nickname) { len += strlen(nickname) + 1; mask = malloc(len); sprintf(mask, "%s!%s@%s", nickname, ident, hostname); } else { mask = malloc(len); sprintf(mask, "%s@%s", ident, hostname); } return mask; }